繁体   English   中英

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

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

假设我有以下收集模式

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'
    }]
});

如何使用terminal.ip = '10 .0.0.1'查找所有WayPoint

我没有运气就尝试了以下方法...

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()的“匹配”部分实际上不是来自“ WayPoint”对象的“完整”可视化路径,而是实际上仅适用于“终端”对象。 “ 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);
    });

这实际上不是通过“ Terminal” ip值查找“ WayPoint”的一种非常有效的方法,因为猫鼬实际上会获取所有“ WayPoint”项,并且您必须“过滤”自己才能找到匹配的项。

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

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

那是MongoDB的通用方法,但是如果您不能这样做或不可行,那么最好找到匹配的“ Terminal”对象的_id并将其传递给“ WayPoint”查询。 来自“异步”库的一些帮助来清理代码:

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();
               }
            );
        }
    ]
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM