我使用旧的MongoDB,其中一个集合中的对象的结构如此。
{
"_id": ObjectId("57fdfcc7a7c81fde38b79a3d"),
"parameters": [
{
"key": "key1",
"value": "value1"
},
{
"key": "key2",
"value": "value2"
}
]
}
问题是参数是一个对象数组,这使得高效的查询变得困难。可以有大约50个不同的对象,它们都具有"key"
和"value"
属性。是否可以进行查询,查询在一个对象中定位"key"
和"value"
?我试过了
db.collection.find({$and:[{"parameters.key":"value"}, {"parameters.value":"another value"}]})
但此查询会命中parameters
数组中的所有对象。
编辑。 Nikhil Jagtiani找到solution我的原始问题,但实际上我应该能够查询目标数组中的多个对象。例如。检查参数数组中两个不同对象的键和值。
答案 0 :(得分:1)
请参考下面的mongo shell聚合查询:
db.collection.aggregate([
{
$unwind:"$parameters"
},
{
$match:
{
"parameters.key":"key1",
"parameters.value":"value1"
}
}
])
1)第1阶段 - Unwind:从输入文档解构数组字段,为每个元素输出文档。每个输出文档都是输入文档,数组字段的值由元素替换。
2)阶段2 - Match:过滤文档以仅将符合指定条件的文档传递到下一个管道阶段。
如果没有聚合,即使一个子文档匹配,查询也会返回整个文档。 此管道只返回所需的子文档。
编辑:如果您需要指定多个键值对,我们需要的是$ in for parameters字段。
db.collection.aggregate([{$unwind:"$parameters"},{$match:{"parameters":{$in:[{ "key" : "key1", "value" : "value1"},{ "key" : "key2", "value" : "value2" }]}}}])
将以下两对键值作为子文档进行匹配:
1){" key" :" key1"," value" :" value1" }
2){" key" :" key2"," value" :" value2" }
答案 1 :(得分:1)
聚合框架中有一个 $filter
运算符,非常适合此类查询。有点冗长但非常有效,您可以按如下方式使用它:
db.surveys.aggregate([
{ "$match": {
"$and": [
{
"parameters.key": "key1",
"parameters.value": "val1"
},
{
"parameters.key": "key2",
"parameters.value": "val2"
}
]
}},
{
"$project": {
"parameters": {
"$filter": {
"input": "$parameters",
"as": "item",
"cond": {
"$or": [
{
"$and" : [
{ "$eq": ["$$item.key", "key1"] },
{ "$eq": ["$$item.value", "val1"] }
]
},
{
"$and" : [
{ "$eq": ["$$item.key", "key2"] },
{ "$eq": ["$$item.value", "val2"] }
]
}
]
}
}
}
}
}
])
您也可以在MongoDB 2.6中使用更多set operators而不使用 $unwind
执行此操作:
db.surveys.aggregate([
{ "$match": {
"$and": [
{
"parameters.key": "key1",
"parameters.value": "val1"
},
{
"parameters.key": "key2",
"parameters.value": "val2"
}
]
}},
{
"$project": {
"parameters": {
"$setDifference": [
{ "$map": {
"input": "$parameters",
"as": "item",
"in": {
"$cond": [
{ "$or": [
{
"$and" : [
{ "$eq": ["$$item.key", "key1"] },
{ "$eq": ["$$item.value", "val1"] }
]
},
{
"$and" : [
{ "$eq": ["$$item.key", "key2"] },
{ "$eq": ["$$item.value", "val2"] }
]
}
]},
"$$item",
false
]
}
}},
[false]
]
}
}
}
])
对于使用MongoDB 2.4的解决方案,您需要使用 $unwind
运算符:
db.surveys.aggregate([
{ "$match": {
"$and": [
{
"parameters.key": "key1",
"parameters.value": "val1"
},
{
"parameters.key": "key2",
"parameters.value": "val2"
}
]
}},
{ "$unwind": "$parameters" },
{ "$match": {
"$and": [
{
"parameters.key": "key1",
"parameters.value": "val1"
},
{
"parameters.key": "key2",
"parameters.value": "val2"
}
]
}},
{
"$group": {
"_id": "$_id",
"parameters": { "$push": "$parameters" }
}
}
]);
答案 2 :(得分:0)
是否可以进行查询,查询的目标是“key”和 一个物体内的“价值”?
如果您知道要预先查询哪个对象(id)(在查询查询中作为输入参数给出),则可以执行此操作。如果那是不可能的,那么我们可以尝试以下方法进行有效的查询。
在parameters.key上构建索引,如果需要也在parameters.value上构建索引。这将大大提高查询性能。
请参阅