在 mongo 查询中,如何在数组中仅显示与过滤器匹配的元素?
in a mongo query, how to display in an array only the elements that match a filter?
这里是 table 个对象:
[
{
field0: value0,
field1: value1,
field2: {
field3: value3,
field4 : [
{ sfield1: svalue110, sfield2: svalue210 },
{ sfield1: svalue111, sfield2: svalue211 },
]
}
},
{
field0: value0,
field1: value1,
field2: {
field3: value3,
field4 : [
{ sfield1: svalue120, sfield2: svalue220 },
{ sfield1: svalue111, sfield2: svalue211 },
{ sfield1: svalue122, sfield2: svalue222 },
]
}
},
{
field0: value0,
field1: value1,
field2: {
field3: value3,
field4 : [
{ sfield1: svalue130, sfield2: svalue230 },
{ sfield1: svalue131, sfield2: svalue231 },
{ sfield1: svalue132, sfield2: svalue232 },
{ sfield1: svalue133, sfield2: svalue233 },
]
}
}
]
我想在 sfield1 和 sfield2 上应用过滤器,并仅显示 field4 的大小 > 0 的对象。在 field4 内,仅显示与过滤器匹配的对象。
例如,我只想显示 sfield1 = svalue111 和 sfield2 = svalue211 的对象
我必须得到这个结果:
[
{
field0: value0,
field1: value1,
field2: {
field3: value3,
field4 : [
{ sfield1: svalue111, sfield2: svalue211 },
]
}
},
{
field0: value0,
field1: value1,
field2: {
field3: value3,
field4 : [
{ sfield1: svalue111, sfield2: svalue211 },
]
}
}
]
我尝试了 addFields 并以这种方式减少:
{
$addFields: {
"field2.field4": {
$reduce: {
input: '$field2.field4',
initialValue: [],
in: {
$let: {
vars: {
ee: {
$filter: {
input: '$$this.field4',
as: 'z',
cond: {
$and: [
{
$eq: [
'$$z.sfield1',
"svalue111"
]
},
{ $eq: ['$$z.sfield2', "svalue211"] }
]
}
}
}
},
in: {
$cond: [
{ $ne: [0, { $size: '$$ee' }] },
{
$concatArrays: [
'$$value',
[
{
$mergeObjects: [
'$$this',
{ "field2.field4": '$$ee' }
]
}
]
]
},
'$$value'
]
}
}
}
}
}
}
}
但是我有这个错误:
Error: command failed: {
"ok" : 0,
"errmsg" : "Invalid $addFields :: caused by :: FieldPath field names may not contain '.'.",
"code" : 16412,
"codeName" : "Location16412"
} : aggregate failed :....
感谢您的帮助
您可以在 $project
中使用 $filter
从 field4
数组中过滤掉。之后你会得到 field4: []
那些过滤元素为 0 的。要删除这些可以使用 $match
来测试 $field4
是否在索引 0 处有一个元素(如果索引 0 处没有元素为空)。
db.collection.aggregate([
{
$project: {
"field0": 1, //show field0 in final result
"field1": 1, //show field1 in final result
"field2.field3": 1, //show field2.field3 in final result
"_id": 0, //hide _id in final result
"field2.field4": {
$filter: {
input: "$field2.field4",
as: "d", //can put any alias here
cond: { //filtering condition
$and: [
{
$eq: [
"$$d.sfield1",
"svalue111"
]
},
{
$eq: [
"$$d.sfield2",
"svalue211"
]
}
]
}
}
}
}
},
{
"$match": { //to remove the empty field4 array part
"field2.field4.0": { //testing if field4 array has an element
"$exists": true
}
}
}
])
过滤子数组中元素的最佳方法是使用 $match
和 $project
的聚合。
示例:
[{
$match: {
field2.field4.sfield1: 'svalue1',
field2.field4.sfield2: 'svalue2'
}
}, {
$project: {
'field2.field4': {
$filter: {
input: '$field2.field4',
as: 'item',
cond: { $and: [
{$eq: ["$$item.sfield1","svalue1"]},
{$eq: ["$$item.sfield2","svalue2"]}
]}
}
}
}
}]
这里是 table 个对象:
[
{
field0: value0,
field1: value1,
field2: {
field3: value3,
field4 : [
{ sfield1: svalue110, sfield2: svalue210 },
{ sfield1: svalue111, sfield2: svalue211 },
]
}
},
{
field0: value0,
field1: value1,
field2: {
field3: value3,
field4 : [
{ sfield1: svalue120, sfield2: svalue220 },
{ sfield1: svalue111, sfield2: svalue211 },
{ sfield1: svalue122, sfield2: svalue222 },
]
}
},
{
field0: value0,
field1: value1,
field2: {
field3: value3,
field4 : [
{ sfield1: svalue130, sfield2: svalue230 },
{ sfield1: svalue131, sfield2: svalue231 },
{ sfield1: svalue132, sfield2: svalue232 },
{ sfield1: svalue133, sfield2: svalue233 },
]
}
}
]
我想在 sfield1 和 sfield2 上应用过滤器,并仅显示 field4 的大小 > 0 的对象。在 field4 内,仅显示与过滤器匹配的对象。
例如,我只想显示 sfield1 = svalue111 和 sfield2 = svalue211 的对象
我必须得到这个结果:
[
{
field0: value0,
field1: value1,
field2: {
field3: value3,
field4 : [
{ sfield1: svalue111, sfield2: svalue211 },
]
}
},
{
field0: value0,
field1: value1,
field2: {
field3: value3,
field4 : [
{ sfield1: svalue111, sfield2: svalue211 },
]
}
}
]
我尝试了 addFields 并以这种方式减少:
{
$addFields: {
"field2.field4": {
$reduce: {
input: '$field2.field4',
initialValue: [],
in: {
$let: {
vars: {
ee: {
$filter: {
input: '$$this.field4',
as: 'z',
cond: {
$and: [
{
$eq: [
'$$z.sfield1',
"svalue111"
]
},
{ $eq: ['$$z.sfield2', "svalue211"] }
]
}
}
}
},
in: {
$cond: [
{ $ne: [0, { $size: '$$ee' }] },
{
$concatArrays: [
'$$value',
[
{
$mergeObjects: [
'$$this',
{ "field2.field4": '$$ee' }
]
}
]
]
},
'$$value'
]
}
}
}
}
}
}
}
但是我有这个错误:
Error: command failed: {
"ok" : 0,
"errmsg" : "Invalid $addFields :: caused by :: FieldPath field names may not contain '.'.",
"code" : 16412,
"codeName" : "Location16412"
} : aggregate failed :....
感谢您的帮助
您可以在 $project
中使用 $filter
从 field4
数组中过滤掉。之后你会得到 field4: []
那些过滤元素为 0 的。要删除这些可以使用 $match
来测试 $field4
是否在索引 0 处有一个元素(如果索引 0 处没有元素为空)。
db.collection.aggregate([
{
$project: {
"field0": 1, //show field0 in final result
"field1": 1, //show field1 in final result
"field2.field3": 1, //show field2.field3 in final result
"_id": 0, //hide _id in final result
"field2.field4": {
$filter: {
input: "$field2.field4",
as: "d", //can put any alias here
cond: { //filtering condition
$and: [
{
$eq: [
"$$d.sfield1",
"svalue111"
]
},
{
$eq: [
"$$d.sfield2",
"svalue211"
]
}
]
}
}
}
}
},
{
"$match": { //to remove the empty field4 array part
"field2.field4.0": { //testing if field4 array has an element
"$exists": true
}
}
}
])
过滤子数组中元素的最佳方法是使用 $match
和 $project
的聚合。
示例:
[{
$match: {
field2.field4.sfield1: 'svalue1',
field2.field4.sfield2: 'svalue2'
}
}, {
$project: {
'field2.field4': {
$filter: {
input: '$field2.field4',
as: 'item',
cond: { $and: [
{$eq: ["$$item.sfield1","svalue1"]},
{$eq: ["$$item.sfield2","svalue2"]}
]}
}
}
}
}]