如何在MongoDB查询中过滤和映射文档数组?

时间:2017-07-04 21:48:54

标签: mongodb aggregation-framework

所以我在我的人物收藏中收到了这些文件:

{
        "_id" : ObjectId("595c0630939a8ae59053a9c3"),
        "name" : "John Smith",
        "age" : 37,
        "location" : "San Francisco, CA",
        "hobbies" : [
                {
                        "name" : "Cooking",
                        "type" : "Indoor",
                        "regular" : true
                },
                {
                        "name" : "Baseball",
                        "type" : "Outdoor",
                        "regular" : false
                }
        ]
}
{
        "_id" : ObjectId("595c06b7939a8ae59053a9c4"),
        "name" : "Miranda Thompson",
        "age" : 26,
        "location" : "Modesto, CA",
        "hobbies" : [
                {
                        "name" : "Lego building",
                        "type" : "Indoor",
                        "regular" : false
                },
                {
                        "name" : "Yoga",
                        "type" : "Indoor",
                        "regular" : false
                }
        ]
}
{
        "_id" : ObjectId("595c078e939a8ae59053a9c5"),
        "name" : "Shelly Simon",
        "age" : 26,
        "location" : "Salt Lake City, UT",
        "hobbies" : [
                {
                        "name" : "Hunting",
                        "type" : "Outdoor",
                        "regular" : false
                },
                {
                        "name" : "Soccer",
                        "type" : "Outdoor",
                        "regular" : true
                }
        ]
}

我正试图过滤我的爱好"数组仅限于常规爱好并投影字段_id,姓名,年龄和爱好的名称和类型。

我希望我的输出是这样的:

{
        "_id" : ObjectId("595c0630939a8ae59053a9c3"),
        "name" : "John Smith",
        "age" : 37,
        "hobbies" : [
                {
                        "name" : "Cooking",
                        "type" : "Indoor"
                }
        ]
}
{
        "_id" : ObjectId("595c06b7939a8ae59053a9c4"),
        "name" : "Miranda Thompson",
        "age" : 26,
        "hobbies" : []
}
{
        "_id" : ObjectId("595c078e939a8ae59053a9c5"),
        "name" : "Shelly Simon",
        "age" : 26,
        "hobbies" : [
                {
                        "name" : "Soccer",
                        "type" : "Outdoor"
                }
        ]
}

嗯......我可以在mongo shell中使用这个命令来实现这个输出:

db.people.aggregate([
    { 
        $project: { 
            hobbies: { 
                $filter: { 
                    input: "$hobbies", 
                    as: "hobby", 
                    cond: { $eq: ["$$hobby.regular", true] } 
                }
            },
            name: 1,
            age: 1
        }
    }, 
    { 
        $project: { 
            "hobbies.name": 1, 
            "hobbies.type": 1, 
            name: 1,
            age: 1
        } 
    }
])

正如你所看到的,我必须按顺序使用两个$ project操作符,我认为这闻起来很糟糕。

有没有办法用另一个查询来实现相同的结果,该查询没有按顺序使用同一个运算符两次?

1 个答案:

答案 0 :(得分:7)

您可以将$filter表达式包装在$map中以映射输出值。

db.people.aggregate([
  {
    "$project": {
      "name": 1,
      "age": 1,
      "hobbies": {
        "$map": {
          "input": {
            "$filter": {
              "input": "$hobbies",
              "as": "hobbyf",
              "cond": "$$hobbyf.regular"
            }
          },
          "as": "hobbym",
          "in": {
            "name": "$$hobbym.name",
            "type": "$$hobbym.type"
          }
        }
      }
    }
  }
])