use*_*480 2 mongoose mongodb node.js mongodb-query
我知道这违反了MongoDB及其No-SQL模型的设计,但我试图在一个集合中查找Documents,然后使用结果中的ID字段来查找另一个集合中的相应记录.有效地尝试模拟联接.
//query is irrelevant to question
var results = collectionOne.find(query).limit(limit);
var a = [];
results.forEach(function(r)
{
var aquery = { id : {$eq : r.id}};
collectionTwo.find(aquery).limit(limit).exec(function, b)
{
if (err)
{
res.render('error',
{
status : 500
});
}
else
{
a.push(b);
}
});
});
res.jsonp(a);
Run Code Online (Sandbox Code Playgroud)
虽然MongoDB中有一些新功能,例如$lookup"加入",但您的具体操作并不需要这样.你在这里所做的只是从另一个集合中返回结果,该集合基于_id前一个值的匹配位置.
为此,最好的选择是使用另一个集合再发出一个查询$in.
// Mongoose turns a cursor to an array by default in the callback method
collectionOne.find(query,{ "_id": 1}).limit(limit).exec(function(err,results) {
// Just get array of _id values
var ids = results.map(function(el) { return el._id } );
// Not sure if you really mean both collections have the same primary key
// I'm presuming two different fields being "id" as opposed to "_id"
collectionTwo.find({ "id": { "$in": ids } },function(err,items) {
// matching results are here
})
})
Run Code Online (Sandbox Code Playgroud)
而已.
您所做的只是返回_id值的第一个查询结果作为"列表",然后将该参数提供给$in目标集合中的相关字段
如果您真的想要"加入"并且可以使用MongoDB 3.2,那么您可以$lookup像这样使用
collectionOne.aggregate([
{ "$match": query },
{ "$limit": limit },
{ "$lookup": {
"from": "collectionTwo",
"localField": "_id",
"foreignField": "id",
"as": "twoItems"
}}
])
Run Code Online (Sandbox Code Playgroud)
这是一个真正的"加盟"的结果,这虽然能够可能用它来只返回从匹配的结果collectionTwo,那么我个人不会.即使在服务器上也是昂贵的练习,并且进一步过滤实际返回该格式所需的操作将最终花费更多.
您也可以.populate()在mongoose中阅读,这实际上是此类查询的"反向".相反,它的过程是存储ObjectId指向相关集合中对象主键的数组(或常规字段,但在这种情况下为数组).因此,如果存在"很多"值collectionTwo,则这些值将存储在collectionOne文档中的数组中.
同样,这是一个"加入模拟"而不是真正的连接.结果将类似于$lookup,并且再次不是真正的"仅仅"结果collectionTwo,而是"加入"版本,您同样需要过滤.
所有真正发生的事情.populate()是它$in无论如何都会运行查询.因此,即使在父项中存储子引用的所有工作(恕我直言,在大多数情况下,如果你可以这样做,那么你也可以只是嵌入数据),与数据库的实际交互保持不变,因为它仍然执行$in查询.
| 归档时间: |
|
| 查看次数: |
3604 次 |
| 最近记录: |