MongoDb $ lookup为每行读取外部集合

问题描述 投票:1回答:1

第一次在Mongodb上使用查找运算符,我发现了一些奇怪的东西。我有2个简单的集合,看起来或多或少像这样:

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对我没有帮助(至少我是这么认为的......如果我错了就启发我)

在这里,您可以在运行查询后查看分析:enter image description here

mongodb aggregation-framework
1个回答
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" : ""
}
© www.soinside.com 2019 - 2024. All rights reserved.