6 способов объединить несколько документов в Cloud Firestore: подробное руководство

Cloud Firestore – это гибкая и масштабируемая база данных документов NoSQL, предоставляемая Firebase. Он позволяет разработчикам хранить, извлекать и запрашивать данные для своих приложений. Хотя Firestore не поддерживает традиционные соединения в стиле SQL, существует несколько методов достижения аналогичных результатов путем объединения нескольких документов. В этой статье мы рассмотрим шесть различных методов с примерами кода для объединения нескольких документов в Cloud Firestore.

  1. Денормализация.
    Денормализация предполагает дублирование данных в нескольких документах для обеспечения эффективности запросов. Допустим, у нас есть две коллекции: «Пользователи» и «Заказы». Каждый документ заказа содержит поле «userId», указывающее на пользователя, которому он принадлежит. Мы можем денормализовать информацию о пользователе в каждом документе заказа для выполнения объединений:
// Query orders collection
const ordersSnapshot = await db.collection('orders').get();
// Join users collection using denormalization
const ordersWithUser = ordersSnapshot.docs.map((orderDoc) => {
  const orderData = orderDoc.data();
  const userId = orderData.userId;
  const userDoc = await db.collection('users').doc(userId).get();
  const userData = userDoc.data();
  return { ...orderData, user: userData };
});
  1. Объединения вручную.
    Если денормализация не подходит для вашей модели данных, вы можете выполнить объединения вручную, выполнив несколько запросов и объединив результаты программным способом:
// Query orders collection
const ordersSnapshot = await db.collection('orders').get();
// Get user IDs from orders
const userIds = ordersSnapshot.docs.map((orderDoc) => orderDoc.data().userId);
// Query users collection based on user IDs
const usersSnapshot = await db.collection('users').where('id', 'in', userIds).get();
// Combine orders and user data
const ordersWithUser = ordersSnapshot.docs.map((orderDoc) => {
  const orderData = orderDoc.data();
  const userId = orderData.userId;
  const userData = usersSnapshot.docs.find((userDoc) => userDoc.data().id === userId).data();
  return { ...orderData, user: userData };
});

<ол старт="3">

  • Объединение подколлекций.
    Firestore позволяет вкладывать коллекции в документы. Вы можете использовать объединения подколлекций для запроса связанных документов внутри подколлекции:
  • // Query users collection
    const usersSnapshot = await db.collection('users').get();
    // Join subcollection "orders" for each user
    const usersWithOrders = usersSnapshot.docs.map(async (userDoc) => {
      const userData = userDoc.data();
      const ordersSnapshot = await userDoc.ref.collection('orders').get();
      const ordersData = ordersSnapshot.docs.map((orderDoc) => orderDoc.data());
      return { ...userData, orders: ordersData };
    });
    1. Запросы агрегации.
      Запросы агрегации позволяют группировать, фильтровать и вычислять данные в нескольких документах. Вы можете использовать агрегацию для косвенного выполнения соединений:
    // Query orders collection
    const ordersSnapshot = await db.collection('orders').get();
    // Group orders by user ID
    const ordersByUser = {};
    ordersSnapshot.docs.forEach((orderDoc) => {
      const orderData = orderDoc.data();
      const userId = orderData.userId;
      if (!ordersByUser[userId]) {
        ordersByUser[userId] = [];
      }
      ordersByUser[userId].push(orderData);
    });
    // Query users collection
    const usersSnapshot = await db.collection('users').get();
    // Combine orders and user data
    const ordersWithUser = usersSnapshot.docs.map((userDoc) => {
      const userData = userDoc.data();
      const userId = userDoc.id;
      const userOrders = ordersByUser[userId] || [];
      return { ...userData, orders: userOrders };
    });
    1. Обновления в режиме реального времени.
      Firestore предоставляет обновления в режиме реального времени через прослушиватели. Вы можете отслеживать изменения в нескольких коллекциях и соответствующим образом обновлять свой пользовательский интерфейс:
    // Listen for changes in orders collection
    db.collection('orders').onSnapshot((ordersSnapshot) => {
      // Perform join logic here
    });
    // Listen for changes in users collection
    db.collection('users').onSnapshot((usersSnapshot) => {
      // Perform join logic here
    });
    1. Облачные функции.
      Если вам требуются сложные соединения или необходимо выполнить преобразование данных, вы можете использовать облачные функции. Облачные функции могут запускаться по событиям Firestore и выполнять операции соединения в бессерверной среде:
    exports.joinDocuments = functions.firestore
      .document('orders/{orderId}')
      .onWrite(async (change, context) => {
        // Perform join logic here
      });

    Хотя Cloud Firestore не обеспечивает функцию прямого соединения, упомянутые выше методы предлагают гибкие способы достижения аналогичных результатов. Будь то денормализация, объединение вручную, объединение подколлекций, агрегирующие запросы, обновления в реальном времени или интеграция облачных функций, у разработчиков есть несколько вариантов объединения нескольких документов в Cloud Firestore. Поняв эти методы и выбрав наиболее подходящий для вашего конкретного случая использования, вы сможете эффективно запрашивать и извлекать объединенные данные из ваших коллекций Firestore.