Mongodb-从数组、匹配项属性或子数组项属性聚合项
我有以下结构的文件:Mongodb-从数组、匹配项属性或子数组项属性聚合项,mongodb,aggregation-framework,Mongodb,Aggregation Framework,我有以下结构的文件: { _id: "UNIQUE_ID", myarray: [ { mykey: '12345', // other fields }, { // other fields nestedarray: [ { mykey: '67890', // other fields } ] } ] } 我需要返回
{
_id: "UNIQUE_ID",
myarray: [
{
mykey: '12345',
// other fields
},
{
// other fields
nestedarray: [
{
mykey: '67890',
// other fields
}
]
}
]
}
我需要返回myarray
中mykey
(在myarray
或nestedarray
的项目上)属于一组值的所有项目。例如,对于上面的文档,如果值集是['12345,'67890']
,则应返回myarray
中的两个项目
我使用以下代码来实现这一点:
collection.aggregate([
{
$match: {
"_id": documentId,
$or: [
{ "myarray": {$elemMatch: {"mykey": { $in: ['12345, '67890'] } } } },
{ "myarray.$.nestedarray": {$elemMatch: {"mykey": { $in: ['12345, '67890'] } }} }
]
}
},
{
$project: {
myarray: {
$filter: {
input: '$myarray',
as: 'arrayitem',
cond: {
$or: [
{ $eq: ["$$arrayitem.mykey", '12345'] },
{ $eq: ["$$arrayitem.nestedarray.[$].mykey", '12345'] }
]
}
}
}
}
}
]);
但这只返回mykey
在myarray
级别匹配的项目(在nestedarray
中不匹配)
我做错了什么
另外,如何在$filter函数中使用set['12345',67890']
而不是单值'12345'
澄清:
- 如果
匹配在mykey
中的项目上:包括此项目(此项目将没有myarray
字段)nestedarray
- 如果
匹配在mykey
中的项目上:包括nestedarray
中包含myarray
的项目(也包括nestedarray
的全部内容)。nestedarray
中的此项将没有myarray
字段mykey
['11111','22222']
预期查询结果:
{
_id: "UNIQUE_ID",
myarray: [
{
mykey: '11111',
// other fields
},
{
// other fields
nestedarray: [
{
mykey: '22222',
// other fields
},
{
mykey: '84325',
// other fields
}
]
}
]
}
您可以使用下面的聚合
db.collection.aggregate([
{ "$match": { "_id": documentId }},
{ "$project": {
"myarray": {
"$filter": {
"input": {
"$map": {
"input": "$myarray",
"as": "arrayitem",
"in": {
"mykey": "$$arrayitem.mykey",
"nestedarray": "$$arrayitem.nestedarray",
"aaaa": {
"$filter": {
"input": "$$arrayitem.nestedarray",
"as": "vv",
"cond": { "$in": ["$$vv.mykey", ["12345", "67890"]] }
}
}
}
}
},
"as": "ff",
"cond": {
"$or": [
{ "$in": ["$$ff.mykey", ["12345", "67890"]] },
{ "$gte": [{ "$size": { "$ifNull": ["$$ff.aaaa", []] }}, 1] }
]
}
}
}
}},
{ "$project": { "myarray.aaaa": 0 }}
])
这是工作模式您可以使用single,然后作为cond
您可以直接检查mykey
或用于数组
db.col.aggregate([
{
$project: {
myarray: {
$filter: {
input: "$myarray",
cond: {
$or: [
{ $in: [ "$$this.mykey", ["11111", "22222"] ] },
{ $anyElementTrue: [
{
$map: {
input: { $ifNull: [ "$$this.nestedarray", [] ] },
as: "na",
in: { $in: [ "$$na.mykey", ["11111", "22222"] ] }
}
}
]
}
]
}
}
}
}
}
])
如果
mykey
存在于nestedarray
中,但不存在于myArray
中,该怎么办?那么应该包括myArray
中包含nestedarray
的项,并且只包括匹配项从nestedarray
应该包括在内OK,那么下面的答案对你有用。@AnthonyWinzlet实际上需要从nestedarray
中选择所有项目(即使只有一个匹配)。所以基本上你不想筛选nestedarray
数组?谢谢你的回答!在这种情况下,我应该保持$match
与我在问题上发布的完全一致,还是应该放弃它(在这种情况下,如何匹配文档_id)?使用单个$match
和\u id
。剩下的事情,$filter
可以。尝试了,但我得到了以下错误errmsg:“$size的参数必须是数组,但类型为:null”
再次更新了我的答案。唯一的问题是它没有为myarray
项带来其他属性(仅mykey
或nestedarray
)。我正在想办法。谢谢你的回答!尝试过了,但这只返回了带有非嵌套的mykey
@GCSDC的项目,这对我来说有点不清楚,修改(并简化)了我的答案,适用于您的示例这就是我要找的!非常感谢你!
db.col.aggregate([
{
$project: {
myarray: {
$filter: {
input: "$myarray",
cond: {
$or: [
{ $in: [ "$$this.mykey", ["11111", "22222"] ] },
{ $anyElementTrue: [
{
$map: {
input: { $ifNull: [ "$$this.nestedarray", [] ] },
as: "na",
in: { $in: [ "$$na.mykey", ["11111", "22222"] ] }
}
}
]
}
]
}
}
}
}
}
])