虽然 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
})
})
就是这样。
您所做的只是将_id 值的第一个查询结果作为“列表”返回,然后将该参数提供给目标集合中相关字段的$in
如果你真的想要一个“加入”并且有可用的 MongoDB 3.2,那么你可以像这样使用$lookup
collectionOne.aggregate([
{ "$match": query },
{ "$limit": limit },
{ "$lookup": {
"from": "collectionTwo",
"localField": "_id",
"foreignField": "id",
"as": "twoItems"
}}
])
这是一个实际的“加入”结果,虽然您可以可能使用它从collectionTwo 返回匹配的结果,但我个人不会。即使在服务器上,这也是一项昂贵的练习,并且进一步过滤实际返回该格式所需的操作最终会花费更多。
您还可能会在 mongoose 中读到有关 .populate() 的信息,这实际上是此类查询的“反向”。相反,它的过程是存储ObjectId 值的数组(或常规字段,在这种情况下为数组),指向相关集合中对象的主键。因此,如果 collectionTwo 有“许多”值,那么这些值将存储在 collectionOne 文档中的数组中。
同样,这是一个“连接仿真”,而不是真正的连接。结果与$lookup 相似,而且不是真正“只是”来自collectionTwo 的结果,而是“加入”版本,您同样需要过滤。
.populate() 真正发生的所有事情是它无论如何都会运行$in 查询。因此,即使在完成了将子引用存储在父级中的所有工作(恕我直言,在大多数情况下,如果你能做到这一点,那么你也可以只嵌入数据),与数据库的实际交互仍然保持不变,因为它仍然执行$in 查询。