MongoDB - 简单的子查询示例

Ton*_*pia 5 nested subquery mongodb pymongo

鉴于数据:

> 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" }
Run Code Online (Sandbox Code Playgroud)

我想提供一个参数 _id和一个查询返回参数表中给定文档的groups数组中的所有组.

直截了当的解决方案似乎在PyMongo中进行了几次DB调用:

  1. 根据提供的_id 从参数表中获取参数
  2. 对于groups数组的每个元素,从groups集合中选择一个文档

但这将带来如此多的不必要开销.我觉得必须有更好,更快的方法在MongoDB中执行此操作(不在DB中运行自定义JS).或者我应该通过将其归一化(如关系表)来重新构建我的数据,忽略基于文档的方法?

再次,请帮我找到一个可以从PyMongo数据库界面工作的解决方案

chr*_*dam 7

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

考虑运行以下管道:

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

样本输出

/* 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"
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您的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 } })
Run Code Online (Sandbox Code Playgroud)

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