Как доставать данные из нескольких коллекций одновременно в базах данных
Что проверяют
Различаете ли вы две задачи: связать документы из разных коллекций в одном ответе и просто выполнить несколько независимых запросов параллельно. Следом обычно спрашивают, чем $lookup отличается от populate() в Mongoose и когда схему лучше пересобрать, чем джойнить.
Как отвечать
Начните с того, что джойн в MongoDB делается агрегацией:
$lookup: левое внешнее соединение.{ $lookup: { from: "orders", localField: "_id", foreignField: "userId", as: "orders" } }добавит каждому пользователю массив его заказов. Форма сletиpipelineпозволяет фильтровать и проецировать присоединяемые документы;$unwind: разворачивает массив, если нужна запись на каждую пару пользователь и заказ;$unionWith: не соединение, а объединение, когда документы двух коллекций нужно склеить в одну выдачу;populate()в Mongoose: это не джойн на сервере, а второй запрос с$inпо собранным идентификаторам, лишний круг до базы на каждый уровень вложенности.
Если данные не связаны, а просто нужны вместе, хватит Promise.all([users.find(q1).toArray(), orders.find(q2).toArray()]): запросы уйдут параллельно через пул соединений драйвера. Чтобы один упавший запрос не ронял остальные, берут Promise.allSettled.
На foreignField нужен индекс, иначе $lookup может сканировать присоединяемую коллекцию на каждый входной документ. Фильтры $match ставят как можно раньше в конвейере.
Хороший финал: если вы постоянно джойните одни и те же коллекции, возможно, данные стоит встроить в документ. Модель в MongoDB строится от запросов, а не от нормализации.
Где спотыкаются
Отвечают только про Promise.all, выгружают обе коллекции целиком через find({}) и связывают уже в JavaScript. На больших объёмах это память процесса Node.js и лишний трафик.
Создают новый MongoClient на каждый запрос и закрывают его. Клиент держит пул соединений и создаётся один раз при старте приложения.
Забывают про лимит документа в 16 МБ. Если у пользователя сотни тысяч заказов, массив из $lookup раздувает документ за предел, и агрегация падает. Спасает $unwind сразу после $lookup или ограничение внутри pipeline.