MongoDB 聚合:如何判断一个数组是否包含多个元素
MongoDB aggregation: how to find out if an array contains multiple elements
我有以下数据。
[
{
"_id": 1,
"array": [
{
"name": "name1",
"nestedArray": [
{
"key": "key1",
"value": "value1"
},
{
"key": "key2",
"value": "value2"
}
]
},
{
"name": "name2",
"nestedArray": [
{
"key": "key1",
"value": "abc"
},
{
"key": "key2",
"value": "value2"
}
]
}
]
}
]
playground
我想保留其 nestedArray 包含 2 个匹配元素的条目并删除其他元素。 2个元素如下
{
"key": "key1",
"value": "abc"
},
{
"key": "key2",
"value": "value2"
}
所以结果会低于
[
{
"_id": 1,
"array": [
{
"name": "name2",
"nestedArray": [
{
"key": "key1",
"value": "abc"
},
{
"key": "key2",
"value": "value2"
}
]
}
]
}
]
删除了 name
="name1" 的那个,因为它只有一个匹配元素。
感觉我们可以使用 $elemMatch
但无法弄清楚。
您并没有真正指定输入的外观,但无论如何策略都将保持不变,我们将使用 $filter 遍历数组并仅匹配其 subarray
大小的文档等于基于给定输入的过滤子数组,如下所示:
// the current input structure.
inputArray = [
{
"key": "key1",
"value": "abc"
},
{
"key": "key2",
"value": "value2"
}
];
db.collection.aggregate([
{
$project: {
array: {
$filter: {
input: "$array",
as: "element",
cond: {
$and: [
{
$eq: [
{
$size: {
$filter: {
input: "$$element.nestedArray",
as: "nested",
cond: {
"$setIsSubset": [
[
"$$nested"
],
inputArray
]
}
}
},
},
{
$size: "$$element.nestedArray"
}
]
},
{ // this is required for an exact match otherwise subsets are possible, if you wan't to allow it delete this equality completly.
$eq: [
{
$size: "$$element.nestedArray"
},
{
$size: inputArray
}
]
}
]
}
}
}
}
}
])
同样,如果输入采用不同的结构,您将必须更改 $eq
条件
首先,展开 array
以便您可以轻松访问 nestedArray
.
其次,在 nestedArray
上使用 $all 和 $elementMatch
db.collection.aggregate([
{
$unwind: "$array"
},
{
$match: {
"array.nestedArray": {
$all: [
{
"$elemMatch": {
key: "key1",
value: "abc"
}
},
{
"$elemMatch": {
key: "key2",
value: "value2"
}
}
]
}
}
},
{
$group: {
_id: "$_id",
array: {
"$push": "$array"
}
}
}
])
我有以下数据。
[
{
"_id": 1,
"array": [
{
"name": "name1",
"nestedArray": [
{
"key": "key1",
"value": "value1"
},
{
"key": "key2",
"value": "value2"
}
]
},
{
"name": "name2",
"nestedArray": [
{
"key": "key1",
"value": "abc"
},
{
"key": "key2",
"value": "value2"
}
]
}
]
}
]
playground 我想保留其 nestedArray 包含 2 个匹配元素的条目并删除其他元素。 2个元素如下
{
"key": "key1",
"value": "abc"
},
{
"key": "key2",
"value": "value2"
}
所以结果会低于
[
{
"_id": 1,
"array": [
{
"name": "name2",
"nestedArray": [
{
"key": "key1",
"value": "abc"
},
{
"key": "key2",
"value": "value2"
}
]
}
]
}
]
删除了 name
="name1" 的那个,因为它只有一个匹配元素。
感觉我们可以使用 $elemMatch
但无法弄清楚。
您并没有真正指定输入的外观,但无论如何策略都将保持不变,我们将使用 $filter 遍历数组并仅匹配其 subarray
大小的文档等于基于给定输入的过滤子数组,如下所示:
// the current input structure.
inputArray = [
{
"key": "key1",
"value": "abc"
},
{
"key": "key2",
"value": "value2"
}
];
db.collection.aggregate([
{
$project: {
array: {
$filter: {
input: "$array",
as: "element",
cond: {
$and: [
{
$eq: [
{
$size: {
$filter: {
input: "$$element.nestedArray",
as: "nested",
cond: {
"$setIsSubset": [
[
"$$nested"
],
inputArray
]
}
}
},
},
{
$size: "$$element.nestedArray"
}
]
},
{ // this is required for an exact match otherwise subsets are possible, if you wan't to allow it delete this equality completly.
$eq: [
{
$size: "$$element.nestedArray"
},
{
$size: inputArray
}
]
}
]
}
}
}
}
}
])
同样,如果输入采用不同的结构,您将必须更改 $eq
条件
首先,展开 array
以便您可以轻松访问 nestedArray
.
其次,在 nestedArray
db.collection.aggregate([
{
$unwind: "$array"
},
{
$match: {
"array.nestedArray": {
$all: [
{
"$elemMatch": {
key: "key1",
value: "abc"
}
},
{
"$elemMatch": {
key: "key2",
value: "value2"
}
}
]
}
}
},
{
$group: {
_id: "$_id",
array: {
"$push": "$array"
}
}
}
])