在Moongoose (MongoDB)中通过嵌入引用数组查找文档

Find documents by array of embedded references in Moongoose (MongoDB)

本文关键字:引用 数组 文档 查找 Moongoose MongoDB      更新时间:2023-09-26

假设我有以下集合模式

var terminalSchema = new mongoose.Schema({
    name: 'String', 
    ip: 'String'
});
var wayPointSchema = new mongoose.Schema({
    name: 'String',
    description: 'String',
    long: 'Number',
    lat: 'Number',
    distances: [{
        toTerminal : { type: Schema.Types.ObjectId, ref: 'Terminal' },
        km : 'Number',
        minutes: 'Number'
    }]
});

如何找到所有的路径点与终端。IP = '10.0.0.1'

我尝试了以下方法,但没有成功…

WayPoint.find()
.populate({
    path: 'distances.toTerminal',
    match:  { 'distances.toTerminal.ip': '10.0.0.1'},
})
.exec(function(err, wp) {
    if(err || !wp) {
          throw err;
        } else {
          console.log(wp);
        }
})

返回整个集合

更新-进度?

我认为我已经对下面的代码取得了一些进展,因为它现在只显示[object]匹配子文档和null不匹配的子文档。

WayPoint.find({'distances.toTerminal': {$exists: true}})
.populate({
    path: 'distances.toTerminal',
    select: 'description',
    match:  { ip: '10.0.0.1'}
})
.exec(function(err, wp) {
    if(err || !wp) {
          throw err;
        } else {
          console.log(wp);
        }
})

这里.populate()的"match"部分实际上不是来自"WayPoint"对象的"完整"可视化路径,而实际上只适用于"Terminal"对象。"WayPoint"只有参考,所以你这样做:

WayPoint.find()
    .populate({
        "path": "distances.toTerminal",
        "match": { "ip": "10.0.0.1" }
    })
    .exec(function(err,wp) {
        if (err) throw err;  // or otherwise handle
        wp = wp.filter(function(doc) {
            doc.distances = doc.distances.filter(function(distance) {
                return distance.toTerminal != null;
            });
            return doc.distances.length > 0;
        });
        console.dir(wp);
    });

通过"终端"ip值来查找"WayPoint"真的不是一个非常有效的方法,因为猫鼬实际上会获取所有的"WayPoint"项目,你必须自己"过滤"才能找到匹配的。

更好的方法是"嵌入"文档,然后您可以发出顶级查询,只查找匹配的文档:

WayPoint.find({ "distances.toTerminal.ip": "10.0.0.1" },function(err,wp) {

这是一般的MongoDB方式,但如果你不能这样做,或者它是不切实际的,那么你会更好地找到_id匹配的"终端"对象或对象,并将其传递给你的"WayPoint"查询。来自"async"库的一点帮助来清理代码:

async.waterfall(
    [
        function(callback) {
            Terminal.find({ "ip": "10.0.0.1" },function(err,terms) {
                if (err) throw err;
                ids = terms.map(function(term) { return term._id; });
                callback(err,ids);
            });
        },
        function(ids,callback) {
            WayPoint.find(
               { "distances.toTerminal": { "$in": ids } },
               function(err,wp) {
                   if (err) throw err;
                   console.dir( wp );
                   callback();
               }
            );
        }
    ]
);