MongoDB elemmatch 数组中的多个元素
MongoDB elemmatch multiple elements in array
我有一个 mongodb 文档,例如
{
"_id" : ObjectId("54e66b2da7b5f3a92e09dc6c"),
"SomeMetric" : [
{
//some object
}
{
//some object
}
],
"FilterMetric" : [
{
"min" : "0.00",
"max" : "16.83",
"avg" : "0.00",
"class" : "s1"
},
{
"min" : "0.00",
"max" : "16.83",
"avg" : "0.00",
"class" : "s2"
},
{
"min" : "0.00",
"max" : "16.83",
"avg" : "0.00",
"class" : "s1"
},
{
"min" : "0.00",
"max" : "16.83",
"avg" : "0.00",
"class" : "s2"
}
]
}
通常它包含许多这样的嵌套数组。我想单独投影一个指标,只有符合我的搜索条件的数组。
我有查询
db.sample.find(
{"filtermetric.class" : "s2"},{"filtermetric" : { $elemMatch : {class: "s2"}}}
)
这只给了我数组中的第一个对象。 class 的第二个对象:s2 未返回。
如果我尝试
db.sample.find(
{"filtermetric" : { $elemMatch : {class: "s2"}}}
)
它给了我数组中的所有 4 个对象。
在这种情况下,如何获取所有符合条件的对象?
您不能 return 以任何形式的基本 .find()
查询匹配您的条件的数组的多个元素。要匹配多个元素,您需要使用 .aggregate()
方法。
这里的主要区别在于 "query" 完全按照预期的方式执行并匹配满足您条件的 "documents"。您可以尝试在投影参数中使用 positional $
运算符,但那里的规则是它只会匹配符合查询条件的 "first" 数组元素。
为了"filter"多个数组元素,进行如下操作:
db.sample.aggregate([
// Filter possible documents
{ "$match": { "filtermetric.class": "s2" } },
// Unwind the array to denormalize
{ "$unwind": "$filtermetric" },
// Match specific array elements
{ "$match": { "filtermetric.class": "s2" } },
// Group back to array form
{ "$group": {
"_id": "$_id",
"filtermetric": { "$push": "$filtermetric" }
}}
])
在 2.6 或更高版本的 MongoDB 的现代版本中,您可以使用 $redact
执行此操作:
db.sample.aggregate([
// Filter possible documents
{ "$match": { "filtermetric.class": "s2" } },
// Redact the entries that do not match
{ "$redact": {
"$cond": [
{ "$eq": [ { "$ifNull": [ "$class", "s2" ] }, "s2" ] },
"$$DESCEND",
"$$PRUNE"
]
}}
])
这可能是您最有效的选择,但它是递归的,因此请首先考虑您的文档结构,因为同名字段不能在任何级别存在任何其他条件。
可能更安全,但仅在数组中的结果为 "truly unique" 时才有用 $map
and $setDifference
:
db.sample.aggregate([
{ "$project": {
"filtermetric": { "$setDifference": [
{ "$map": [
"input": "$filtermetric",
"as": "el",
"in": {"$cond": [
{ "$eq": [ "$$el.class", "s2" ] },
"$$el",
false
]}
]},
[false]
]}
}}
])
还注意到,在两个 $group
and $project
操作管道阶段中,您 需要 指定您打算 return 在您的结果文档中的所有字段那个阶段。
最后要注意的是,当只访问数组的单个键时,$elemMatch
is not required when you are only querying the value of a single key within an array. "Dot notation" 是首选和推荐的。 $elemMatch
仅当数组 "element" 中文档中的 "multiple" 键需要匹配查询条件时才需要。
我有一个 mongodb 文档,例如
{
"_id" : ObjectId("54e66b2da7b5f3a92e09dc6c"),
"SomeMetric" : [
{
//some object
}
{
//some object
}
],
"FilterMetric" : [
{
"min" : "0.00",
"max" : "16.83",
"avg" : "0.00",
"class" : "s1"
},
{
"min" : "0.00",
"max" : "16.83",
"avg" : "0.00",
"class" : "s2"
},
{
"min" : "0.00",
"max" : "16.83",
"avg" : "0.00",
"class" : "s1"
},
{
"min" : "0.00",
"max" : "16.83",
"avg" : "0.00",
"class" : "s2"
}
]
}
通常它包含许多这样的嵌套数组。我想单独投影一个指标,只有符合我的搜索条件的数组。 我有查询
db.sample.find(
{"filtermetric.class" : "s2"},{"filtermetric" : { $elemMatch : {class: "s2"}}}
)
这只给了我数组中的第一个对象。 class 的第二个对象:s2 未返回。
如果我尝试
db.sample.find(
{"filtermetric" : { $elemMatch : {class: "s2"}}}
)
它给了我数组中的所有 4 个对象。
在这种情况下,如何获取所有符合条件的对象?
您不能 return 以任何形式的基本 .find()
查询匹配您的条件的数组的多个元素。要匹配多个元素,您需要使用 .aggregate()
方法。
这里的主要区别在于 "query" 完全按照预期的方式执行并匹配满足您条件的 "documents"。您可以尝试在投影参数中使用 positional $
运算符,但那里的规则是它只会匹配符合查询条件的 "first" 数组元素。
为了"filter"多个数组元素,进行如下操作:
db.sample.aggregate([
// Filter possible documents
{ "$match": { "filtermetric.class": "s2" } },
// Unwind the array to denormalize
{ "$unwind": "$filtermetric" },
// Match specific array elements
{ "$match": { "filtermetric.class": "s2" } },
// Group back to array form
{ "$group": {
"_id": "$_id",
"filtermetric": { "$push": "$filtermetric" }
}}
])
在 2.6 或更高版本的 MongoDB 的现代版本中,您可以使用 $redact
执行此操作:
db.sample.aggregate([
// Filter possible documents
{ "$match": { "filtermetric.class": "s2" } },
// Redact the entries that do not match
{ "$redact": {
"$cond": [
{ "$eq": [ { "$ifNull": [ "$class", "s2" ] }, "s2" ] },
"$$DESCEND",
"$$PRUNE"
]
}}
])
这可能是您最有效的选择,但它是递归的,因此请首先考虑您的文档结构,因为同名字段不能在任何级别存在任何其他条件。
可能更安全,但仅在数组中的结果为 "truly unique" 时才有用 $map
and $setDifference
:
db.sample.aggregate([
{ "$project": {
"filtermetric": { "$setDifference": [
{ "$map": [
"input": "$filtermetric",
"as": "el",
"in": {"$cond": [
{ "$eq": [ "$$el.class", "s2" ] },
"$$el",
false
]}
]},
[false]
]}
}}
])
还注意到,在两个 $group
and $project
操作管道阶段中,您 需要 指定您打算 return 在您的结果文档中的所有字段那个阶段。
最后要注意的是,当只访问数组的单个键时,$elemMatch
is not required when you are only querying the value of a single key within an array. "Dot notation" 是首选和推荐的。 $elemMatch
仅当数组 "element" 中文档中的 "multiple" 键需要匹配查询条件时才需要。