Mongo 3.6 - 解析嵌套对象列表中的引用对象

Mongo 3.6 - Resolve referenced object in nested list of objects

我有一个包含以下格式文档的集合:

db.companies.find({})

{
    'name': 'ABC Trading Ltd',
    'telephone': '01292 480 485',
    'comments': [{
        'user': 'joe.bloggs@example.com',
        'date': 'example',
        'text': 'This is an example comment.'
     },
     {
        'user': 'jane.bloggs@example.com',
        'date': 'example',
        'text': 'This is an example comment.'
     }] 
}

我还有一个如下所示的用户集合:

db.users.find({})

{
    'email': 'joe.bloggs@example.com',
    'firstname': 'Joe',
    'lastname': 'Bloggs'
},
{
    'email': 'jane.bloggs@example.com',
    'firstname': 'Jane',
    'lastname': 'Bloggs'
}

我正在尝试做的是使用 $lookup 以便最终查询的结果如下所示:

{
    'name': 'ABC Trading Ltd',
    'telephone': '01292 480 485',
    'comments': [{
        'user': {
              'email': 'joe.bloggs@example.com',
              'firstname': 'Joe',
              'lastname': 'Bloggs'
        },
        'date': 'example',
        'text': 'This is an example comment.'
     },
     {
        'user': {
              'email': 'jane.bloggs@example.com',
              'firstname': 'Jane',
              'lastname': 'Bloggs'
        },
        'date': 'example',
        'text': 'This is an example comment.'
     }] 
}

现在我知道我可以使用如下方式查找值:

db.companies.aggregate[{"$lookup": {
           "from": "users",
           "localField": "user",
           "foreignField": "email",
           "as": "user"
        }}, {"$addFields": {
            "user": {"$arrayElemAt": ["$user", 0]}
        }}]

但是,这只有在用户是文档中的顶级用户并且只有一个字段需要替换的情况下才有效。

请试试这个:

db.companies.aggregate([{$unwind : '$comments'},{"$lookup": {
           "from": "users",
           "localField": "comments.user",
           "foreignField": "email",
           "as": "user"
        }}, {$addFields : {'comments.user': {"$arrayElemAt": ["$user", 0]}}},{$project : {user :0}}, 
        {$group:{_id:'$_id', comments:{$push : '$comments'}, data: {$first :'$$ROOT'}}}, {$addFields :{'data.comments':'$comments'}}, {$replaceRoot:{'newRoot': '$data'}}])

注意: 通常我们不必 $unwind 评论 $lookup 除非需要,因为不同有价值的对象需要映射,另外,如果可能,请尝试使用 $match 作为第一阶段和适当的索引,以便在 $lookup 上获得更好的性能。