Коннектор MongoDB Atlas на основе HTTP для бессерверных сред выполнения (например, Cloudflare Workers и Deno Deploy) с использованием собственного API Fetch.

Случаи использования

  • mongo-http.js можно использовать, когда клиент не поддерживает необработанное TCP-соединение, но поддерживает HTTP-соединение, например, некоторые бессерверные среды выполнения или Cloudflare Workers.
  • Его также можно использовать в бессерверных средах выполнения, где повторное использование соединения MongoDB не всегда может быть доступно или требует ручного кэширования.
  • К сожалению, его пока нельзя использовать на стороне браузера из-за CORS. Вот поток для запроса функции CORS

Мотивация

Несколько месяцев назад я мигрировал Medium Rare (китайский парсер и поисковик статей на Medium) с Heroku на Cloudflare Workers. Я использовал MongoDB Data API для замены драйвера MongoDB Node.js. Во время путешествия я почувствовал, что неоднократно делал вызовы fetch в Data API, и мне не хватает знакомого API драйвера Node.js. Поэтому я построил эту тонкую оболочку поверх Data API, которую я (и, надеюсь, другие) смогу использовать в будущих бессерверных проектах!

Настройте MongoDB Atlas, чтобы получить идентификатор приложения и ключ API.

Прежде чем использовать mongo-http.js (API данных MongoDB), вам необходимо получить идентификатор приложения и ключ API. Подробнее читайте в Учебнике по MongoDB Atlas.

Монтаж

npm install mongo-http --save

Инициализация

Вы можете инициализировать client, database или collection, как показано ниже. Обычно мы хотели бы инициализировать соединение database.

Вы также можете инициализировать клиент для подключения к нескольким базам данных.

import { initClient } from 'mongo-http';
const client = initClient({
  appId: process.env.appId,
  apiKey: process.env.apiKey,
});
const db = client.database({ databaseName: process.env.databaseName });
const result = await db.collection('articles').find({
  filter: {
    $or: [{ categories: { $in: ['javascript', 'reactjs', 'nodejs', 'mongodb'] } }],
  },
});

Как инициализировать базу данных

import { initDatabase } from 'mongo-http';
const db = initDatabase({
  appId: process.env.appId || '',
  apiKey: process.env.apiKey || '',
  databaseName: process.env.databaseName || '',
});
const result = await db.collection('articles').find({});

Как инициализировать коллекцию

import { initDatabase } from 'mongo-http';
const articlesCollection = initCollection({
  appId: process.env.appId || '',
  apiKey: process.env.apiKey || '',
  databaseName: process.env.databaseName || '',
  collectionName: 'articles',
});
const result = await articlesCollection.find({});

Это отражает то, как драйвер MongoDB Node.js инициализирует эти три экземпляра.

const { MongoClient } = require("mongodb");
const client = new MongoClient(process.env.uri);
await client.connect();

const db = client.db("<your database>");

const collection = db.collection("<your collection>");
const document = await collection.findOne({});

Учебник и примеры

Вы можете найти GitHub README.md API doc здесь. Входные параметры отражают Data API, но используют аналогичные API драйвера Node.js.

Далее давайте рассмотрим, как создать (insertOne), прочитать (find), обновить (updateOne) и удалить (deleteOne) документ. Допустим, у нас есть две коллекции — articles и writers и документ выглядит так:

const article = {
  _id: 'article-1-object-id',
  writerId: 'patrick-writer-object-id',
  title: 'Migrating a Node.js App to Cloudflare Workers From Heroku',
  tags: ['javascript', 'cloudflare-workers', 'heroku', 'nodejs']
}

const writer = {
  _id: 'patrick-writer-object-id',
  name: 'Patrick Chiu',
  latestArticlesAt: '2023-01-01T12:15:00.000Z'
}

1. insertOne

Допустим, мы очистили статью и хотели бы вставить документ в articles.

const result = await db.collection('articles').insertOne({
  writerId: 'patrick-writer-object-id',
  title: 'Introducing mongo-http.js',
  tags: ['javascript', 'mongodb', 'serverless', 'nodejs', 'cloudflare-workers']
});

// If the insertion is successful
// => isSuccess: true, insertedId: 'object-id'
const { isSuccess, insertedId } = result;

2. найти

Затем мы разрабатываем конечную точку /articles, которая поддерживает пользователей для поиска по tags. Здесь я использую hono.js в качестве веб-фреймворка.

import { Hono } from 'hono';
const app = new Hono();

// For illustration purpose,
// I skip a lot of details, such as error handling
app.get('/v1/articles', async (c) => {
  const { tags = '' } = c.req.query();

  if (tags === '') {
    return c.json({ articles: [] });
  }

  const tagArray = tags
    .split(',')
    .slice(0, 10)
    .map((tag) => tag.trim());

  const result = db.collection('articles').find({
    filter: { tags: { $in: tagArray } }
  });

  const { isSuccess, documents } = result;
  return c.json({ articles: documents || [] });
});

3. обновлениеОдин

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

const result = db.collection('writers').updateOne({
  filter: { writerId: 'patrick-writer-object-id' },
  update: {
    latestArticlesAt: '2023-01-04T19:30:00.000Z'
  },
});

// If the update is successful
// => isSuccess: true, matchedCount: 1, modifiedCount: 1
// Since it is an existing document, upsertedId will be nil
const { isSuccess, matchedCount, modifiedCount, upsertedId } = result;

4. удалитьОдин

Если пользователь удаляет свою учетную запись Medium, мы хотим удалить документ пользователя.

const result = await db.collection('writers').deleteOne({
  filter: { writerId: 'non-existing-writer-object-id' },
});

// If the delete is successful
// => isSuccess: true, deletedCount: 1
const { isSuccess, deletedCount } = result;

Заключение

В будущих статьях я надеюсь продемонстрировать полные примеры использования mongo-http с различными веб-фреймворками (например, hono.js и itty) в различных бессерверных средах выполнения (например, Cloudflare Workers, Digital Ocean functions, и Дено Деплой)

Want to Connect?

If you find the package and tutorial useful, 
please give mongo-http a look and connect with me on LinkedIn!