MongoDB - 简单的子查询示例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40304211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:50:23  来源:igfitidea点击:

MongoDB - simple sub query example

mongodbnestedsubquerypymongo

提问by Tony Sepia

Given the data:

鉴于数据:

> db.parameters.find({})
{ "_id" : ObjectId("56cac0cd0b5a1ffab1bd6c12"), "name" : "Speed", "groups" : [ "
123", "234" ] }
> db.groups.find({})
{ "_id" : "123", "name" : "Group01" }
{ "_id" : "234", "name" : "Group02" }
{ "_id" : "567", "name" : "Group03" }

I would like to supply a parameter_id an make a query return all groups that are within the groupsarray of the given document in parameterstable.

我想提供一个参数_id 使查询返回参数表中给定文档的数组内的所有组。

The straightforward solution seems to make several DB calls in PyMongo:

简单的解决方案似乎在 PyMongo 中进行了几次数据库调用:

  1. Get parameter from parameterstable based on the supplied _id
  2. For each element of groupsarray select a document from groupscollection
  1. 根据提供的 _id从参数表中获取参数
  2. 对于数组的每个元素从集合中选择一个文档

But this will have so much unnecessary overhead. I feel there must be a better, faster way to do this within MongoDB (without running custom JS in the DB). Or should I re-structure my data by normalising it a little bit (like a table of relationships), neglecting the document-based approach?

但这会有很多不必要的开销。我觉得在 MongoDB 中必须有更好、更快的方法来做到这一点(无需在 DB 中运行自定义 JS)。或者我应该通过稍微规范化数据(如关系表)来重新构建我的数据,而忽略基于文档的方法?

Again, please help me find a solution that would work from PyMongo DB interface

再次,请帮我找到一个可以从 PyMongo DB 接口工作的解决方案

回答by chridam

You can do this within a single query using the aggregation framework. In particular you'd need to run an aggregation pipeline that uses the $lookupoperator to do a left join from the parameterscollection to the groupscollection.

您可以使用聚合框架在单个查询中执行此操作。特别是,您需要运行一个聚合管道,该管道使用$lookup运算符执行从parameters集合到groups集合的左连接。

Consider running the following pipeline:

考虑运行以下管道:

db.parameters.aggregate([
    { "$unwind": "$groups" },
    {
        "$lookup": {
            "from": "groups",
            "localField": "groups",
            "foreignField": "_id",
            "as": "grp"
        }
    },
    { "$unwind": "$grp" }
])

Sample Output

样本输出

/* 1 */
{
    "_id" : ObjectId("56cac0cd0b5a1ffab1bd6c12"),
    "name" : "Speed",
    "groups" : "123",
    "grp" : {
        "_id" : "123",
        "name" : "Group01"
    }
}

/* 2 */
{
    "_id" : ObjectId("56cac0cd0b5a1ffab1bd6c12"),
    "name" : "Speed",
    "groups" : "234",
    "grp" : {
        "_id" : "234",
        "name" : "Group02"
    }
}


If your MongoDB server version does not support the $lookuppipeline operator, then you'd need execute two queries as follows:

如果您的 MongoDB 服务器版本不支持$lookup管道运算符,那么您需要执行以下两个查询:

# get the group ids
ids = db.parameters.find_one({ "_id": ObjectId("56cac0cd0b5a1ffab1bd6c12") })["groups"]

# query the groups collection with the ids from previous query
db.groups.find({ "_id": { "$in": ids } })

EDIT: matched the field name in the aggregation query to the field name in example dataset (within the question)

编辑:将聚合查询中的字段名称与示例数据集中的字段名称匹配(在问题内)