将对象数组转换为虚拟 mongodb 集合

converting an array of objects to a virtual mongodb collection

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
  },
  ...
]

试试这个:

{
   $set: {
      data: {
         $filter: {
            input: serviceData,
            cond: { $eq: ["$$this._id", "$_id"] }
         }
      }
   }
}

您在客户端代码中已经有 serviceData,所以您需要做的就是 $match 到您的目标集合中,然后在客户端“加入”material像这样:

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 => x['_id']);

// Create a key lookup dictionary (_id => 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.

的“根”文档中