第一次在Mongodb上使用查找运算符,我发现了一些奇怪的东西。我有两个看起来或多或少的简单集合:
Book
{
"_id": 1,
"Title": "Some book name",
"AuthorId": 1,
}
Author
{
"_id": 1,
"Name": "Some Author",
"Location": "US"
}
enter code here
Book.AuthorId上还有一个索引。
所以,我想要的是查询在美国拥有Books
的所有Authors
。所以在阅读完文档之后......我想出了这个问题:
db.Book.aggregate([
{
$lookup: {
from: "Author",
localField: "AuthorId",
foreignField: "_id",
as: "author"
}
},
{
$unwind: "$author"
},
{
$match:{ "author.Location": {$eq: "US"}}
}
])
哪个效果很好。但是,出于好奇,我打开了剖析图,看看当我执行上面的查询时Mongo做了什么。令我惊讶的是,我看到它为它阅读的每本书做了一次作者查找。使用$lookup
运算符的重点是不必事先查看所有作者,所以我有点迷失在这里。我不打算把任何东西分组......在查找之前找$group
对我没有帮助(至少我是这么认为的......如果我错了就启发我)
答案 0 :(得分:0)
嗯..我找到了实现这个目标的方法..因为没有人回答它我会给出我自己的答案。
所以我必须“反转”查询的顺序。由于我需要对作者进行过滤,因此我从它开始并使用$match
运算符对其进行过滤。这将减少记录。然后,我只是$unwind
和$replaceRoot
来显示图书文档。所以:
db.Author.aggregate([
{
$lookup: {
from: "Book",
localField: "_id",
foreignField: "AuthorId",
as: "books"
}
},
{
$unwind: "$books"
},
{
$replaceRoot: { newRoot: "$books" }
}
])
在分析器上,我只看到一个查询:
/* 1 */
{
"op" : "command",
"ns" : "Test.Book",
"command" : {
"aggregate" : "Author",
"pipeline" : [
{
"$lookup" : {
"from" : "Book",
"localField" : "_id",
"foreignField" : "AuthorId",
"as" : "books"
}
},
{
"$unwind" : "$books"
},
{
"$replaceRoot" : {
"newRoot" : "$books"
}
}
],
"cursor" : {}
},
"keysExamined" : 0,
"docsExamined" : 2,
"cursorExhausted" : true,
"numYield" : 0,
"locks" : {
"Global" : {
"acquireCount" : {
"r" : NumberLong(26)
}
},
"Database" : {
"acquireCount" : {
"r" : NumberLong(13)
}
},
"Collection" : {
"acquireCount" : {
"r" : NumberLong(12)
}
}
},
"nreturned" : 4,
"responseLength" : 312,
"protocol" : "op_command",
"millis" : 1,
"planSummary" : "COLLSCAN",
"ts" : ISODate("2017-12-27T09:39:28.958Z"),
"client" : "127.0.0.1",
"allUsers" : [],
"user" : ""
}