преобразование массива объектов в виртуальную коллекцию mongodb

#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.