#node.js #mongodb #mongoose #aggregation-framework
#node.js #mongodb #мангуст #агрегирование-основа
Вопрос:
let serviceData = await getServiceData();
Я получаю некоторые данные из внешней службы, которая представляет собой массив объектов, таких как:
[ { _id x y }, ... ]
Есть ли какой-либо способ использовать этот результат на этапе поиска, фактически не создавая его как коллекцию в базе данных? Я хочу создать агрегацию для другой коллекции со схемой, подобной
new Schema({ _id a b );
и в этом выполните поиск, как:
{ from: serviceData, localField: "_id", foreignField: "_id", as: "data" }
и, наконец, получить
[ { _id x y a b }, ... ]
Комментарии:
1. Ясность: Вы пытаетесь использовать в
serviceData
качестве целевого списка_id
для поиска в другой коллекции?2. @BuzzMoschetti Я хочу присоединиться к ним так же, как мы это делаем на этапе поиска с коллекцией, и получить все свойства, включая x и y.
Ответ №1:
Попробуй вот это:
{ $set: { data: { $filter: { input: serviceData, cond: { $eq: ["$this._id", "$_id"] } } } } }
Комментарии:
1. Мне нужны все поля после присоединения. Пожалуйста, ознакомьтесь с обновлением.
2. Вот что ты получаешь. Возможно, предоставьте некоторые реальные примеры данных и желаемый результат.
Ответ №2:
У вас уже есть serviceData
код на стороне клиента, поэтому все, что вам нужно сделать $match
, это войти в свою целевую коллекцию, а затем «присоединиться» к материалам на стороне клиента, как это:
var svcdata = [ { _id: 1, x: 3, y: 7 }, { _id: 2, x: 8, y: 9 } ]; // Create an array of _id from the given serviceData: var zzz = svcdata.map(x =gt; x['_id']); // Create a key lookup dictionary (_id =gt; rest of serviceData). // All fields will be picked up; no need to enumerate // x, y, z, etc.: var svcdict = {}; svcdata.forEach(function(item) { svcdict[item['_id']] = item; }); // This is all you need to find the material in your collection: c=db.foo.aggregate([ {$match: {_id: {$in: zzz} }} ]); // As you pull each doc from the DB, key-match on _id and add it // to the materal: c.forEach(function(doc) { doc['svcdata'] = svcdict[doc['_id']]; printjson(doc); });
В итоге это выглядит примерно так:
{ "_id" : 1, "name" : "N1", "svcdata" : { "_id" : 1, "x" : 3, "y" : 7 } } { "_id" : 2, "name" : "N2", "svcdata" : { "_id" : 2, "x" : 8, "y" : 9 } }
Это «безопасный» подход, потому что вы избегаете конфликтов имен входящих serviceData
полей с полями в ваших документах, т. е. это пространство имен. Конечно, вы можете по своему выбору выполнить общую итерацию svcdict[doc[_id]]
и вставить каждое поле в «корневой» документ, поступающий из MongoDB.