簡體   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