减少mongoDB查询的响应

col*_*ore 1 mongodb mongodb-query aggregation-framework

我有这样的文件:

{
    "_id" : ObjectId("53340d07d6429d27e1284c77"),
    "worktypes" : [ 
        {
            "name" : "Pompas",
            "works" : [ 
                {
                    "name" : "work 1",
                    "code" : "0001"
                }
            ]
        },
        {
            "name" : "Pompas "",
            "works" : [ 
                {
                    "name" : "work 2",
                    "code" : "0002"
                }
            ]
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

我做了一个查询,只获取本文档的工作类型之一的作品,这是查询:

db.categories.find({$and: [
        { "_id": ObjectId('53340d07d6429d27e1284c77')},
        {"worktypes.name": "Pompas"}
    ]},{"worktypes.works.$":1})
Run Code Online (Sandbox Code Playgroud)

但我得到了

    {
    "_id" : ObjectId("53340d07d6429d27e1284c77"),
    "worktypes" : [ 
        {
            "name" : "Pompas",
            "works" : [ 
                {
                    "name" : "work 1",
                    "code" : "0001"
                }
            ]
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

但我只需要:

"works" : [ 
                    {
                        "name" : "work 1",
                        "code" : "0001"
                    }
                ]
Run Code Online (Sandbox Code Playgroud)

我怎样才能减少这个?

Ana*_*lan 12

我认为Neil Lunn的回答大多是正确的,但在我看来,需要进行一些调整才能得到预期的结果:

  1. 匹配"worktypes.name"而不是"worktypes.works.name"
  2. 在这个$group阶段,使用$first而不是$push单独获得第一个元素
  3. 添加一个$project阶段来获取"works"
db.categories.aggregate([
    { "$unwind": "$worktypes" },
    { "$unwind": "$worktypes.works" },
    { "$match": {
        "worktypes.name": "Pompas"
    }},
    { "$group": {
        "_id": "$_id",
        "works": { "$first": "$worktypes.works" }
    }},
    { "$project": {"_id":0, "works":1} }
])
Run Code Online (Sandbox Code Playgroud)

输出:

{
        "result" : [
                {
                        "works" : {
                                "name" : "work 1",
                                "code" : "0001"
                        }
                }
        ],
        "ok" : 1
}
Run Code Online (Sandbox Code Playgroud)