如何将文档与Mongodb中对象属性的值进行匹配

时间:2015-07-30 10:04:05

标签: javascript mongodb meteor

我正在尝试匹配mongoDB中的某些文档:

我的文档模型:

profile: {
  languages: [
    {"name": "French", "level": 1},
    {"name": "English", "level": 2},
    {"name": "Spanish", "level": 4}
  ]
}

我(我)可以搜索我的结果集:

lang = ["French", "English"];
objLang = [
  {name: "French"},
  {name: "English"}
];

我需要的是db.find()所有匹配至少一种语言的文档,例如:

profile.languages.name = "French"

profile.languages.name = "English"

我的意思是,如果我在我的选项集中有法语或英语,我需要让所有拥有其语言数组元素的用户,其名称与我的选项之一匹配,无论语言的级别如何。

所以,除非我错了,否则我不能做

db.find({"profile.languages": {$in: [{name: "French"}, {name: "English"}]});

你会怎么做?

非常感谢。

大卫

3 个答案:

答案 0 :(得分:1)

您可以尝试使用 dot notation 访问数组的两个元素并访问嵌入文档的字段:

db.find({
    "profile.languages.name": {
        "$in": ["French", "English"]
    }
});

答案 1 :(得分:1)

实际上,你几乎是对的:

db.collection.find({"profile.languages.name":{$in: ["French","English"]} })

由于profile.languages是一个子文档数组,因此可以调用其中一个子文档的键,后续查询将映射到包含该键的所有子文档。

但是,如果没有正确的索引,添加的.explain()会显示一些非常难看的内容:

{
  "queryPlanner" : {
    "plannerVersion" : 1,
    "namespace" : "test.languages",
    "indexFilterSet" : false,
    "parsedQuery" : {
        "profile.languages.name" : {
            "$in" : [
                "English",
                "French"
            ]
        }
    },
    "winningPlan" : {
        "stage" : "COLLSCAN",
        "filter" : {
            "profile.languages.name" : {
                "$in" : [
                    "English",
                    "French"
                ]
            }
        },
        "direction" : "forward"
    },
    "rejectedPlans" : [ ]
  }
}

serverInfo被忽略了。)

因此,为了使此查询更有效,您需要在要查询的字段上创建索引:

db.languages.ensureIndex({"profile.languages.name":1})

现在增加的解释告诉我们,匹配的文件是通过索引识别的:

{
"queryPlanner" : {
    "plannerVersion" : 1,
    "namespace" : "test.languages",
    "indexFilterSet" : false,
    "parsedQuery" : {
        "profile.languages.name" : {
            "$in" : [
                "English",
                "French"
            ]
        }
    },
    "winningPlan" : {
        "stage" : "FETCH",
        "inputStage" : {
            "stage" : "IXSCAN",
            "keyPattern" : {
                "profile.languages.name" : 1
            },
            "indexName" : "profile.languages.name_1",
            "isMultiKey" : true,
            "direction" : "forward",
            "indexBounds" : {
                "profile.languages.name" : [
                    "[\"English\", \"English\"]",
                    "[\"French\", \"French\"]"
                ]
            }
        }
    },
    "rejectedPlans" : [ ]
  },
  "ok" : 1
}

答案 2 :(得分:1)

请尝试以下查询:

解决方案1:

db.collection.aggregate([
     {
       $unwind:"$profile.languages"
     },
     {
       $match:{"profile.languages.name":{"$in":["French", "English"]}}
     },
     {
       $group:{_id: "$_id", profile:{"$push":"$profile.languages"}}
     }
  ])

解决方案2:

db.collection.find(
   {
     "profile.languages.name": 
       {
        "$in": [ "English", "French"]
       }
   }
 );