2017-04-23 64 views
0

我有一個非常簡單的MongoDb查詢使用$查找和$匹配。我的問題是我無法確定查詢中$匹配的正確位置。如果我將$匹配放在$ lookup上面,我會得到預期的結果(通過$ match正確過濾),但它們不包含鏈接文檔的「世界」數組。如果我將$ match放在查詢下面,我會得到所有父記錄,包括鏈接文檔的「世界」數組,但$匹配不起作用。

我在做什麼錯?

server.get(`${routePfx}/${model}s/with-linked`, function (req, res, next) { 
    console && console.log('Finding all with linked names ' + model.toUpperCase() + 's...'); 
    db.collection(model).aggregate(
     { 
      "$lookup": { 
       from: "world", 
       localField: "worldId", 
       foreignField: "_id", 
       as: "world" 
      } 
     }, 
     { "$match": { "del": false } } 
    ).toArray(function (err, docs) { 
     res.json(201, docs); 
     next(); 
    }); 
}); 

編輯:我找到了!你注意到的細微差別?...

server.get(`${routePfx}/${model}/:id/with-linked`, function (req, res, next) { 
    console && console.log('Finding ' + model.toUpperCase() + ' by Id with linked names...'); 
    db.collection(model).aggregate([ 
     { "$match": { "_id": new ObjectId(req.params.id) } }, 
     { 
      "$lookup": { 
       from: "world", 
       localField: "worldId", 
       foreignField: "_id", 
       as: "world" 
      } 
     } 
    ]).toArray(function (err, docs) { 
     res.json(201, docs); 
     next(); 
    }); 
}); 

回答

0

的聚合函數需要一個數組...

server.get(`${routePfx}/${model}/:id/with-linked`, function (req, res, next) { 
    console && console.log('Finding ' + model.toUpperCase() + ' by Id with linked names...'); 
    db.collection(model).aggregate([ 
     { "$match": { "_id": new ObjectId(req.params.id) } }, 
     { 
      "$lookup": { 
       from: "world", 
       localField: "worldId", 
       foreignField: "_id", 
       as: "world" 
      } 
     } 
    ]).toArray(function (err, docs) { 
     res.json(201, docs); 
     next(); 
    }); 
}); 
+0

對於您的情況,聚合應該與/不使用數組相同。我注意到你改變了從發佈的問題到答案的$匹配階段。你能否確認你有正確的比賽階段? – Veeram

+0

沒有數組是絕對必要的。我只是將$匹配移動到頂部並添加了數組包裝器,並且按預期工作:-) – Locohost

0

一般使用$match$lookup之前過濾輸入文檔,並使用$match$lookup來過濾連接的數據。

"world"是一組文檔。您必須使用$unwind + $match或使用$filter匹配來自worlds陣列的字段。

$unwind + $match經過優化,僅在您使用$lookup with $match應用過濾器時纔有效。

db.collection(model).aggregate([{ 
    "$lookup": { 
     from: "world", 
     localField: "worldId", 
     foreignField: "_id", 
     as: "world" 
    } 
}, { 
    "$unwind": "$world" 
}, { 
    "$match": { 
     "world.del": false 
    } 
}]) 

或者

db.collection(model).aggregate([{ 
    "$lookup": { 
     from: "world", 
     localField: "worldId", 
     foreignField: "_id", 
     as: "world" 
    } 
    }, { 
    $addFields: { 
     items: { 
      $filter: { 
       input: "$world", 
       as: "result", 
       cond: { 
        $eq: ["$$result.del", false] 
       } 
      } 
     } 
    } 
    }]) 

另外,如果你使用$match其中包括來自輸入文檔字段和數據連接優化的$lookup階段之前輸入文檔移動$match

+0

感謝您的回覆。我發現了這個錯誤。聚合需要一個數組: - / – Locohost