Знакомство со стеком TERN и переходом с MERN на TERN. MERN — это стек веб-технологий, состоящий из MongoDB, Express.js, React и Node.js. В этом руководстве предполагается, что вы используете Tigris Cloud или собственный экземпляр Tigris.

Что такое МЕРН?

MERN (MongoDB, Express.js, React и Node.js) является альтернативой MEAN (MongoDB, Express.js, Angular и Node.js). MEAN был представлен в 2013 году, а MERN последовал за ним по мере того, как React становился все более популярным в 2018 году.

Стек MERN состоит из:

  • Браузер: React с помощью JavaScript или TypeScript (перенесено в JavaScript)
  • Сервер: Express.js с JavaScript или TypeScript (переведено в JavaScript)
  • База данных: MongoDB, скорее всего, использует драйвер MongoDB Node.js, хотя может использоваться ODM, такой как Mongoose.

Что такое ТЕРН?

TERN (Tigris, Express.js, React и Node.js) использует идеи MERN и заменяет MongoDB на Tigris.

  • Браузер: React с помощью JavaScript или TypeScript (перенесено в JavaScript)
  • Сервер: Express.js с JavaScript или TypeScript (переведено в JavaScript)
  • База данных: Tigris Database с использованием Tigris TypeScript SDK, который предоставляет встроенный ODM.

Зачем переходить с MERN на TERN?

Итак, зачем вам переходить с MERN (MongoDB) на TERN (Tigris)? Tigris — это бессерверная база данных NoSQL и поисковая платформа, а также альтернатива MongoDB.

У Tigris есть несколько преимуществ перед MongoDB. Тигр:

Убежденный? Если да, то фантастика! Если нет, дайте нам знать, почему.

Как перейти с MERN на TERN

Чтобы следовать дальше, вам понадобится следующее:

В этом руководстве мы будем использовать разветвленную и слегка обновленную версию примера MongoDB MERN, используемого в официальном руководстве по стеку MongoDB MERN.

Примененные обновления заключаются в использовании новейшей версии драйвера MongoDB Node.js (для поддержки сетевого протокола MongoDB 6.0+), удалении неиспользуемой зависимости Mongoose ODM, обновлении кода для использования промисов, определении имени базы данных в переменная среды, используйте encodeURIComponent при передаче параметров в URL-адресах от клиента и добавляйте теги alt к изображениям (не обязательно для этого руководства, но мне показалось, что это правильно).

Чтобы продолжить, клонируйте обновленный репозиторий пример стека TERN и переключитесь на ветку mern:

git clone https://github.com/tigrisdata-community/tern-stack-example.git
cd tern-stack-example
git checkout mern

Если у вас запущен экземпляр MongoDB, вы можете попробовать пример MERN, следуя инструкциям в файле README.

Теперь мы можем начать миграцию.

Вы можете перейти с MERN на TERN (и с любого приложения MongoDB на Tigris) в один или два этапа.

Двухэтапный процесс, описанный здесь, таков:

  1. Начните с использования совместимости с Tigris MongoDB
  2. Перенос вашего кода на использование Tigris TypeScript SDK

Использование совместимости с Tigris MongoDB

Недавно мы выпустили бета-версию Совместимость с Tigris MongoDB, которая позволяет подключаться к Tigris с использованием проводного протокола MongoDB 6.0+. С точки зрения MERN это, вероятно, означает приложение, использующее драйвер MongoDB Node.js.

Обновить приложение, которое мы только что клонировали, для использования совместимости с Tigris MongoDB так же просто, как обновить строку подключения. Итак, заходим в Tigris Console и создаем новый проект. Затем вы попадете в раздел **Начало работы** вашего проекта. Оттуда щелкните вкладку **Совместимость с MongoDB** и строку подключения MongoDB, которую вы видите на этой вкладке.

Либо обновите, либо создайте файл mern/server/config.env, установив значение ATLAS_URI в строку подключения Tigris MongoDB. Кроме того, установите DATABASE_NAME на имя только что созданного проекта Tigris. Ваш файл будет выглядеть примерно так:

мерн/сервер/config.env

ATLAS_URI=mongodb://{TIGRIS_CLIENT_ID}:{TIGRIS_CLIENT_SECRET}@m1k.preview.tigrisdata.cloud:27018?authMechanism=PLAIN&tls=true
DATABASE_NAME=mern-to-tern

Затем следуйте существующим инструкциям README, чтобы запустить сервер и клиент.

В одном терминале запустите сервер с помощью:

cd mern/server
npm install
npm start

Вывод командной строки сервера

В другом терминале запустите клиент с помощью:

cd mern/client
npm install
npm start

Вывод командной строки клиента

Когда вы запускаете клиент, браузер автоматически открывает браузер. По умолчанию приложение будет работать на http://localhost:3000. Попробуйте приложение, чтобы увидеть его в действии.

Помните, что все, что мы сделали, чтобы это приложение работало с базой данных Tigris, — это обновили строку подключения, чтобы она указывала на Tigris Cloud.

Миграция с драйвера MongoDB Node.js на Tigris SDK

Совместимость с Tigris MongoDB — отличный первый шаг в миграции приложения MERN. Но чтобы в полной мере воспользоваться преимуществами TERN и Tigris, рекомендуется обновить приложение для использования Tigris TypeScript SDK. Для этого требуется больше работы, но изменения довольно небольшие, как будет показано в этом разделе.

Поскольку клиент и сервер отделены через API, предоставляемый приложением Express.js, нам нужно обновить код только для конечных точек API Express.js.

Обновить зависимости

Начнем с обновления зависимостей приложения MERN, чтобы использовать те, которые требуются TERN; удалите драйвер mongodb и добавьте @tigrisdata/core:

npm uninstall monodb
npm i @tigrisdata/core

Добавить конфигурацию Tigris

Обновите файл mern/server/config.env, чтобы он содержал дополнительную конфигурацию Tigris:

мерн/сервер/config.env

- ATLAS_URI=mongodb+srv://<username>:<password>@sandbox.jadwj.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
- DATABASE_NAME=mern-to-tern
PORT=5000
+ TIGRIS_CLIENT_ID={TIGRIS_CLIENT_ID}
+ TIGRIS_CLIENT_SECRET={TIGRIS_CLIENT_SECRET}
+ TIGRIS_PROJECT=mern-to-tern
+ TIGRIS_URI=api.preview.tigrisdata.cloud
+ TIGRIS_DB_BRANCH=main

Замена {TIGRIS_CLIENT_ID} и {TIGRIS_CLIENT_SECRET} реальными значениями из ключей приложения вашего проекта Tigris.

Определите схему вашей базы данных в TypeScript

Установите TypeScript как зависимость разработки:

npm i -D typescript

Добавьте следующее к mern/server/tsconfig.json:

мерн/сервер/tsconfig.json

{
  "compilerOptions": {
    "target": "es2016",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

Определите схему в TypeScript, чтобы она соответствовала автоматически сгенерированной схеме, созданной при использовании приложения через совместимость с Tigris MongoDB:

import {
  Field,
  PrimaryKey,
  TigrisCollection,
  TigrisDataTypes,
} from "@tigrisdata/core";
@TigrisCollection("records")
export class Record {
  @Field({ elements: TigrisDataTypes.STRING })
  $k?: string[];
  @PrimaryKey(TigrisDataTypes.BYTE_STRING, { order: 1, autoGenerate: true })
  _id?: string;
  @Field()
  name!: string;
  @Field()
  position!: string;
  @Field()
  level!: string;
}

Декоратор @TigrisCollection("records") и предоставленное значение records информируют Tigris о наличии records коллекции документов типа Record в структуре, определенной этим классом.

Поля _id, name, position и level используются в приложении. Поле $k не используется, но необходимо, чтобы приложение могло продолжать работать с автоматически созданной схемой совместимости MongoDB. Как вы увидите, все поля приложения имеют тип string.

КОНЧИК

Вы также можете получить эту схему из Консоли Tigris в разделе Ваш проект -> База данных -> щелкните по схеме записей -> выберите TypeScript из выпадающего списка:

Имея схему, нам нужно проверить ее с помощью Tigris и использовать с SDK Tigris TypeScript. Для этого создайте скрипт mern/server/script/setup.ts со следующим содержимым:

мерн/сервер/скрипты/setup.ts

import { Tigris } from "@tigrisdata/core";
import { Record } from "../db/record";
import dotenv from "dotenv";
dotenv.config({ path: "./config.env" });
async function main() {
  // setup client
  const tigrisClient = new Tigris();
  // ensure branch exists, create it if it needs to be created dynamically
  await tigrisClient.getDatabase().initializeBranch();
  // register schemas
  await tigrisClient.registerSchemas([Record]);
}
main()
  .then(async () => {
    console.log("Setup complete ...");
    process.exit(0);
  })
  .catch(async (e) => {
    console.error(e);
    process.exit(1);
  });

В приведенном выше коде конфигурация загружается с использованием dotenv, а клиент Tigris создается и назначается переменной tigrisClient, которая использует загруженные переменные среды. Затем база данных и ветвь базы данных инициализируются с помощью tigrisClient.getDatabase().initializeBranch(). Наконец, зарегистрируйте схему Record через tigrisClient.registerSchemas([Record]).

Обновите package.json, чтобы использовать сценарий установки:

{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
+   "setup": "npx ts-node scripts/setup.ts",
+   "prestart": "npm run setup",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
+   "@tigrisdata/core": "^1.0.0-beta.44",
    "cors": "^2.8.5",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
-   "mongodb": "5.2",
-   "mongoose": "^5.12.4"
+   "reflect-metadata": "^0.1.13"
+ },
+ "devDependencies": {
+   "typescript": "^5.0.4"
  }
}

Это добавляет сценарий setup NPM, используемый prestart, который автоматически предшествует сценарию, определенному в сценарии start NPM.

Примечание: приведенный выше diff также показывает другие измененные зависимости.

Определив схему, мы можем перейти к обновлению кода приложения.

Обновить код подключения

Затем обновите код подключения, определенный в mern/server/db/conn.js, удалив драйвер MongoDB Node.js и обновив код для использования SDK Tigris TypeScript:

Мерн/сервер/БД/conn.js

- const { MongoClient } = require("mongodb");
- const Db = process.env.ATLAS_URI;
+ const { Tigris } = require("@tigrisdata/core");
- const client = new MongoClient(Db, {
-   useNewUrlParser: true,
-   useUnifiedTopology: true,
- });
+ const client = new Tigris();
var _db;
module.exports = {
  connectToServer: async function (callback) {
    try {
-     const db = await client.connect();
-     _db = db.db(process.ENV.DATABASE_NAME);
-     console.log("Successfully connected to MongoDB.");
+     _db = await client.getDatabase();
+     console.log("Successfully connected to Tigris.");
      return callback();
    } catch (err) {
      return callback(err);

Клиент Tigris создается и автоматически использует переменные среды, которые мы определили в файле mern/server/config.env.

Другое отличие, на которое стоит обратить внимание, заключается в том, что мы не называем базу данных, которая используется в client.getDatabase(), поскольку каждый проект Tigris имеет только одну базу данных.

Общие изменения кода MERN в TERN

Постоянная разница во всех изменениях маршрута Express.js:

  1. MongoDB ObjectId больше не используется
  2. Запрос содержит filter для идентификации документа. Итак, с { _id: new ObjectId(req.params.id) } на { filter: { _id: req.params.id } } последовательное изменение кода во всех маршрутах
  3. Доступ к коллекциям осуществляется через getCollection(collectionName) вместо collection(collectionName)

Перенос базы данных MERN для чтения в базу данных TERN для чтения

Обновите маршрут GET /record:

мерн/сервер/маршруты/record.js

- const ObjectId = require("mongodb").ObjectId;
// This section will help you get a list of all the records.
recordRoutes.route("/record").get(async function (req, res) {
- let db_connect = dbo.getDb("employees");
- const result = await db_connect.collection("records").find({}).toArray();
+ let db_connect = dbo.getDb();
+ const result = await db_connect.getCollection("records").findMany().toArray();
  return res.json(result);
});

Чтобы получить несколько документов с помощью Tigris SDK, используйте findMany, не передавая никаких параметров. Это возвращает курсор, который предоставляет функцию toArray для получения Array результатов.

Если вы перезапустите серверное приложение, вы увидите главную страницу приложения, на которой отображаются сотрудники, но через вызов GET /record, который теперь использует Tigris SDK.

Перенос базы данных MERN create в базу данных TERN create

Обновите маршрут POST /record/add:

Примечание. Чтобы быть более верным REST, это должно быть POST /record

мерн/сервер/маршруты/record.js

recordRoutes.route("/record/add").post(async function (req, res) {
  let db_connect = dbo.getDb();
  let myobj = {
    name: req.body.name,
    position: req.body.position,
    level: req.body.level,
  };
- const result = db_connect.collection("records").insertOne(myobj);
+ const result = await db_connect.getCollection("records").insertOne(myobj);
  res.json(result);
});

В этом случае сигнатура метода для insertOne остается прежней.

Перенести обновление базы данных MERN в обновление базы данных TERN

Измените маршрут POST /update/:id:

Примечание. Для большего удобства REST это должно быть PATCH /record/:id или PATCH /record/:id, если он заменяет весь ресурс.

мерн/сервер/маршруты/record.js

recordRoutes.route("/update/:id").post(async function (req, res) {
  let db_connect = dbo.getDb();
- let myquery = { _id: new ObjectId(req.params.id) };
- let newvalues = {
+ const myquery = {
+   filter: { _id: req.params.id },
+   fields: {
      $set: {
        name: req.body.name,
        position: req.body.position,
        level: req.body.level,
      },
+   },
  };
- const result = await db_connect
-   .collection("records")
-   .updateOne(myquery, newvalues);
+ const result = await db_connect.getCollection("records").updateOne(myquery);
  console.log("1 document updated");
  res.json(result);
});

Функция updateOne Tigris SDK отличается от драйвера MongoDB Node.js тем, что она принимает один параметр со следующими свойствами для достижения того же результата:

  1. filter фильтр, используемый для поиска документа, который нужно обновить
  2. fields, где это свойство может использовать синтаксис $set, поддерживаемый драйвером MongoDB.

Перенести удаление базы данных MERN на удаление базы данных TERN

Наконец, обновите маршрут DELETE /:id:

Примечание. Полиция REST: это должно быть DELETE /record/:id

мерн/сервер/маршруты/record.js

recordRoutes.route("/:id").delete(async (req, res) => {
  let db_connect = dbo.getDb();
- let myquery = { _id: new ObjectId(req.params.id) };
- const result = await db_connect.collection("records").deleteOne(myquery);
+ let myquery = { filter: { _id: req.params.id } };
+ const result = await db_connect.getCollection("records").deleteOne(myquery);
  res.json(result);
});

Как уже говорилось, единственное изменение здесь — это filter, требуемый для Tigris SDK.

Обновить логотип

Давайте добавим логотип Tigris 😄 Возьмите Зеленый логотип Tigris, сохраните его в tern/client/public и обновите mern/client/src/components/navbar.js следующим образом:

Мерн/клиент/SRC/компоненты/navbar.js

<NavLink className="navbar-brand" to="/">
  <img
-   alt="MongoDB logo"
+   alt="Tigris logo"
    style={{ width: 25 + "%" }}
-   src="https://d3cy9zhslanhfa.cloudfront.net/media/3800C044-6298-4575-A05D5C6B7623EE37/4B45D0EC-3482-4759-82DA37D8EA07D229/webimage-8A27671A-8A53-45DC-89D7BF8537F15A0D.png"
+   src="/tigris-logo-green.png"
  ></img>
</NavLink>

Запустите приложение TERN

И с применением этих обновлений приложение MERN преобразуется в стек TERN 🎉

Поскольку никаких функциональных изменений во внешнем интерфейсе нет (только обновление логотипа), вам нужно только остановить и запустить сервер только для того, чтобы увидеть изменения в действии:

npm start

И вы увидите следующий вывод:

npm start
> [email protected] prestart
> npm run setup

> [email protected] setup
> npx ts-node scripts/setup.ts
info - Using reflection to infer type of Record#$k
info - Using reflection to infer type of Record#name
info - Using reflection to infer type of Record#position
info - Using reflection to infer type of Record#level
info - Using Tigris at: api.preview.tigrisdata.cloud:443
info - Using database branch: 'main'
event - Creating collection: 'records' in project: 'mern-to-tern'
Setup complete ...
> [email protected] start
> node server.js
info - Using Tigris at: api.preview.tigrisdata.cloud:443
Server is running on port: 5000
Successfully connected to Tigris.