在MongoDB中搜索嵌入对象的数组

时间:2012-10-18 15:12:11

标签: mongodb

给定学校对象的这种结构:

{ 
  "grade_spans" : 
  {
       "0": { 
         "grade_span_key" : "K_5",
         "name":  "Elementary School"
       }, 
       "1": { 
         "grade_span_key" : "6_8",
         "name":  "Junior High-School"
       }
  }
}

如何找到给定grade_span_key的学校?

db.schools.find({ "grade_span_key": "K_5" }) 

返回空。

更新:抱歉,我错误地复制了结构。它实际上是一个嵌入式对象而不是集合。

更新#2 :我错误地使用了doctrine2注释:@MongoDB \ EmbedMany(strategy =“set”)。我将策略更改为pushAll(这是默认值)

3 个答案:

答案 0 :(得分:0)

您应该使用点缀符号表示该属性的完整路径。

> db.schools.find({"grade_spans.grade_span_key": "K_5"})
{
    "_id" : ObjectId("50801cc5ab582e310adc0e41"),
    "grade_spans" : [
        {
            "grade_span_key" : "K_5",
            "name" : "Elementary School"
        },
        {
            "grade_span_key" : "6_8",
            "name" : "Junior High-School"
        }
    ]
}

答案 1 :(得分:0)

如果这个字段刚刚嵌入到主文档中,@ sergios的答案就可以正常工作,并且不清楚为什么他的查询不起作用,因为你没有提供只有嵌入式结构的文档结构的例子。

同样@JohnnyHK说,将该对象重建为数组,因为在这种情况下动态键会更难。

如果您要从嵌入文档中挑选匹配的行而不是整个文档。这有点困难但是可能:

db.schools.aggregate({
    {$unwind: "$grade_spans"}, 
    {$match: {"grade_spans.grade_span_key": "K_5"}}, 
    {$group: {_id: "$_id", grade_spans: {$push: "$grade_spans"}}}
})

上述内容应返回结构文档:

{
    _id: {},
    grade_spans:[{
        "grade_span_key" : "K_5",
        "name" : "Elementary School"        
    }]
}

答案 2 :(得分:0)

鉴于这种结构:

{ 
    "grade_spans" : {
        "0": {  "grade_span_key" : "K_5",
                "name":  "Elementary School" }, 
        "1": {  "grade_span_key" : "6_8",
                "name":  "Junior High-School" }
    }
}

您可以尝试使用map / reduce功能:

var mapFunction = function() {
    for (var i in this.grade_spans) {
        // Add the name of the school in a list
        var schools = [];
        schools[0] = this.grade_spans[i].name;

        // Create out object : { schools : ["Elementary School"] } or { schools : ["Junior High-School"] }
        var out = {};
        out.schools = schools;

        // Create key (K_5 or 6_8)
        var key = this.grade_spans[i].grade_span_key;
        emit(key, out);
    }
};


var reduceFunction = function(key, values) {
    var schools = [];
    for (var i = 0; i < values.length; i++) {
        schools.push.apply(schools, values[i].schools);
    }
    return {schools:schools};
}

db.schools.mapReduce(
    mapFunction,
    reduceFunction,
    { out: "map_reduce_grade_spans", sort: {_id:1} }
)

然后:

db.map_reduce_grade_spans.find({_id:"K_5"});