Cloud Firestore – это гибкая и масштабируемая база данных документов NoSQL, предоставляемая Firebase. Он позволяет разработчикам хранить, извлекать и запрашивать данные для своих приложений. Хотя Firestore не поддерживает традиционные соединения в стиле SQL, существует несколько методов достижения аналогичных результатов путем объединения нескольких документов. В этой статье мы рассмотрим шесть различных методов с примерами кода для объединения нескольких документов в Cloud Firestore.
- Денормализация.
Денормализация предполагает дублирование данных в нескольких документах для обеспечения эффективности запросов. Допустим, у нас есть две коллекции: «Пользователи» и «Заказы». Каждый документ заказа содержит поле «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 };
});
- Объединения вручную.
Если денормализация не подходит для вашей модели данных, вы можете выполнить объединения вручную, выполнив несколько запросов и объединив результаты программным способом:
// 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 };
});
- Запросы агрегации.
Запросы агрегации позволяют группировать, фильтровать и вычислять данные в нескольких документах. Вы можете использовать агрегацию для косвенного выполнения соединений:
// 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 };
});
- Обновления в режиме реального времени.
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
});
- Облачные функции.
Если вам требуются сложные соединения или необходимо выполнить преобразование данных, вы можете использовать облачные функции. Облачные функции могут запускаться по событиям Firestore и выполнять операции соединения в бессерверной среде:
exports.joinDocuments = functions.firestore
.document('orders/{orderId}')
.onWrite(async (change, context) => {
// Perform join logic here
});
Хотя Cloud Firestore не обеспечивает функцию прямого соединения, упомянутые выше методы предлагают гибкие способы достижения аналогичных результатов. Будь то денормализация, объединение вручную, объединение подколлекций, агрегирующие запросы, обновления в реальном времени или интеграция облачных функций, у разработчиков есть несколько вариантов объединения нескольких документов в Cloud Firestore. Поняв эти методы и выбрав наиболее подходящий для вашего конкретного случая использования, вы сможете эффективно запрашивать и извлекать объединенные данные из ваших коллекций Firestore.