如何仅使用选定的几个嵌入对象返回对象?

时间:2016-04-07 18:52:49

标签: mongodb mapreduce aggregation-framework

我的结构如下:

{
    day: x,
    events:
    [
        {
            year: y,
            info: z
        }
    ]
}

到目前为止,我创建了以下查询,我没有返回错误但显示任何错误(这是错误的)。

db.days.aggregate([
{ 
    $match: 
    {
        $and:
        [ 
            {
                'day': 'March_13' 
            },
            {
                'events.year': '1870'
            },
            {
                'events.info': {$regex: "./French./"}
            }
        ]
    }
},
{
    $unwind: {path: "$events"},
},
{ 
    $match: 
    {
        'info': { $regex: '.*French.*'}
    }
}])

从我读到的内容我需要按_id进行分组,但我不知道如何使用满足第二个$ match的对象重新创建数组。

请您看一下,也许可以告诉我为什么初始查询不起作用并在群组块上告诉我?

这里有一些示例数据:

{ 
    "day" : "March_13", 
    "events" : 
         [
             { 
                 "year" : "1929", 
                 "info" : "Peter Breck, American actor (d. 2012)" 
             }, 
             { 
                 "year" : "1929", 
                 "info" : "Joseph Mascolo, American actor" 
             }, 
             { 
                 "year" : "1929", 
                 "info" : "Zbigniew Messner, Polish economist and politician, 9th Prime Minister of the Republic of Poland (d. 2014)" 
             }, 
             { 
                 "year" : "1929", 
                 "info" : "Bunny Yeager, American model and photographer (d. 2014)" 
             }
         ] 
}

如果我成功通过“美国人”这个词来查询,那就是这样:

{ 
    "day" : "March_13", 
    "events" : 
         [
             { 
                 "year" : "1929", 
                 "info" : "Peter Breck, American actor (d. 2012)" 
             }, 
             { 
                 "year" : "1929", 
                 "info" : "Joseph Mascolo, American actor" 
             }, 
             { 
                 "year" : "1929", 
                 "info" : "Bunny Yeager, American model and photographer (d. 2014)" 
             }
         ] 
}

基本上我想检查字段信息是否包含搜索到的单词,如果是,我将其保留在数组中。

2 个答案:

答案 0 :(得分:0)

您想尝试为上面的示例运行以下聚合管道以获得所需的结果:

db.days.aggregate([
    {
        "$match": {
            "day" : "March_13",
            "events.year": "1929",
            "events.info": /American/
        }
    },
    { "$unwind": "$events" },
    {
        "$match": {
            "day" : "March_13",
            "events.year": "1929",
            "events.info": /American/
        }
    },
    {
        "$group": {
            "_id": "$_id",
            "day": { "$first": "$day" },
            "events": { "$push": "$events" }
        }
    }

])

示例输出

/* 0 */
{
    "result" : [ 
        {
            "_id" : ObjectId("5706b38dcc578484faab815f"),
            "day" : "March_13",
            "events" : [ 
                {
                    "year" : "1929",
                    "info" : "Peter Breck, American actor (d. 2012)"
                }, 
                {
                    "year" : "1929",
                    "info" : "Joseph Mascolo, American actor"
                }, 
                {
                    "year" : "1929",
                    "info" : "Bunny Yeager, American model and photographer (d. 2014)"
                }
            ]
        }
    ],
    "ok" : 1
}

答案 1 :(得分:0)

如果我们可以将$regex$cond运算符或$filter运算符一起使用,那么这很简单。这就是说你有两个选择,第一个是使用聚合框架(如this answer中所述)和本地聚合管道运算符,它们在C ++中编码速度更快,但在管道中你需要使用$unwind运算符,如果您正在处理大型数组,则在去常规化后文档的大小可能会超过16MB,在这种情况下,聚合查询将失败。如果发生这种情况,您可以使用mapReduce

执行此操作
function map() { 
    var events =  this.events.filter(function(element) { 
        return (/American/i).test(element.info) && element.year === "1929";
        });
    emit(this.day, events);
}

db.collection.mapReduce(
    map, 
    function(key, value) {}, 
    { out: { inline: 1 } },
    { query: { "day": "March_13" } }
)

返回:

{
    "results" : [
            {
                "_id" : "March_13",
                "value" : [
                    {
                        "year" : "1929",
                        "info" : "Peter Breck, American actor (d. 2012)"
                    },
                    {
                        "year" : "1929",
                        "info" : "Joseph Mascolo, American actor"
                    },
                    {
                        "year" : "1929",
                        "info" : "Bunny Yeager, American model and photographer (d. 2014)"
                    }
                ]
            }
    ],
    "timeMillis" : 27,
    "counts" : {
        "input" : 1,
        "emit" : 1,
        "reduce" : 0,
        "output" : 1
    },
    "ok" : 1
}