将数组字段中的每个ObjectId解析为另一个集合中的对象

时间:2017-03-26 15:25:55

标签: mongodb aggregation-framework

这是一个非常具体的问题,我一直在搜寻堆栈溢出数小时寻找解决方案。

我有两个系列:

事件:

{   
    _id : ObjectId,
    title : $title,
    other fields etc...,
    artist : ObjectId,
    targets : [ObjectId,ObjectId,ObjectId]
}

艺术家:

{   
    _id : ObjectId,
    name : $name,
    other fields etc...
}

每个事件都有一个包含多个目标的字段,保存为ObjectId。我需要使用聚合和$lookup的某种组合的查询来返回一个事件(与.find( { _id : ObjectId_of_event } )匹配,每个目标都解析为一个对象

它有望像这样:

{   _id : ObjectId,
    title : $title,
    other fields...,
    targets : [ {   
                   _id : ObjectId_1,
                   name : $name,
                   other fields etc...
                },
                {   
                   _id : ObjectId_2,
                   name : $name,
                   other fields etc...
                },
                {   
                   _id : ObjectId_3,
                   name : $name,
                   other fields etc...
                } ]
}

我尝试过聚合,应用$lookup然后在mongodb管道中使用$group但是还没有找到方法将所有目标保留在目标数组中并且只解析每个ObjectId。 / p>

//编辑额外信息

我目前正在运行的查询:

db.collection("events").aggregate([
     { $match: { _id : object } }, 
     { $lookup : { 
                  from: "artists",
                  localField: "artist",
                  foreignField: "_id",
                  as: "artist_object" 
     }},
     { $unwind : "$targets"},
     { $lookup : { 
                  from: "artists",
                  localField: "targets",
                  foreignField: "_id",
                  as: "targets_objects" 
                 }} 
      }} ]).toArray(function(queryErr, main_event) etc... 

返回:

     [ { event : { _id : ObjectId,
                  title : $title,
                  artist : ObjectId,
                  targets : { artist_object_of_first_target }
                  artist_object : { artist object }
       },
       { event : { _id : ObjectId,
                  title : $title,
                  artist : ObjectId,
                  targets : { artist_object_of_second_target }
                  artist_object : { artist object }
       },
       { event : { _id : ObjectId,
                  title : $title,
                  artist : ObjectId,
                  targets : { artist_object_of_third_target }
                  artist_object : { artist object }
       }]

有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:0)

从mongodb版本3.3.4,您现在可以将数组传递到localField中的$lookup,在您的情况下为targets,因此您可以使用与ObjectId相同的_id获取艺术家集合中的对象在目标数组中。您首先需要通过_id匹配事件中的文档。

db.collection('events').aggregate([
    {$match: {
        _id: ObjectId("58d7deaf20362d084071ea0e")
    }},
    {$lookup: {
        from: 'artists',
        localField: 'targets',
        foreignField: '_id',
        as: 'targets'
    }}
    ]).toArray().then(result => {
        console.log(JSON.stringify(result, 0, 4))
    })

也不要忘记从mongodb获取ObjectId,以便您可以在查询中使用它。

const mongodb = require('mongodb');
var ObjectId = mongodb.ObjectId;

最终结果将如下所示。

[{
  "_id": "58d7deaf20362d084071ea0e",
  "title": "Event 1",
  "targets": [{
    "_id": "58d7ded4785cdf10a8847f78",
    "name": "Artist 1"
  }, {
    "_id": "58d7dedf8f37180f0ce1db38",
    "name": "Artist 4"
  }]
}]