MongoDb:将一个集合的文档嵌套在另一个集合中以获取查询结果



假设我有两个MongoDb集合(带有示例字段):

People: 
_id: 2
name: 'bob'
carIds: [1,2,3]

Cars:
_id: 82
model: 'Camry'

有没有一种方法可以返回一个带有新字段CarsPeople列表,该字段将具有一个Cars数组,该数组具有与People中的carIds匹配的carId

我不想永久性地创建字段,只是为了查询结果。我能用地图做这个吗?我试过了:

var peopleWithCars = db.people.find({
}).map(function(doc) {
    var carIds = doc.carIds; 
    var cars = db.cars.find({
        _id: { $in: carIds} 
    })
    doc.cars= cars;
    return doc;
});
return peopleWithCars ;

得到:

错误:第18行:非法的返回语句

编辑-这就是最终奏效的:

db.people.find({
        }).map(function(doc) {
        var carIds = doc.carIds; 
        var cars = db.cars.find({
            _id: { $in: carIds} 
        }).toArray(); 
        doc.cars= cars;
        return doc;
    });

出于某种原因,它仍然不喜欢vars,但这会强制返回项,而不是查询它们。

find()方法返回一个游标。您需要将其转换为数组(cursor.toArray()IIRC)。这应该能解决你的两个问题。
var cars= db.find(...).toArray()

但老实说,如果你想经常使用这个查询,那不是最好的设计。您最好在car中添加一个字段"personId",然后用一个查询来查询cars集合。

对单个查询可以采取的一种方法是使用聚合框架并运行具有$lookup运算符的管道。这将对同一数据库中的未排序集合执行左外部联接,以筛选"联接"集合中的文档进行处理。$lookup阶段在输入文档中的字段与"联接"集合的文档中的域之间进行相等匹配。

以下示例显示了如何将其应用于您的案例:

db.people.aggregate([
    { "$unwind": "$carIds" },
    {
        "$lookup": {
            from: "cars",
            localField: "carIds",
            foreignField: "_id",
            as: "cars"
        }
    },
    { "$unwind": "$cars" },
    {
        "$group": {
            "_id": "$_id",
            "name": { "$first": "$name" },
            "cars": { "$push": "$cars" }
        }
    }
])

最新更新