对于以下文档,我需要输出
1. image arrays which are hsl:1
2. dim.hsl embedded document
主要文件
{
"_id" : ObjectId("564b17873b91989fcb4e9707"),
"type" : "article",
"image" : [
{
"name" : "i3",
"hsl" : 1
},
{
"name" : "i1",
"hsl" : 1
},
{
"name" : "i2",
"hsl" : 0,
"ai" : 1
}
],
"dim" : {
"hsl" : {
"path" : "blah"
},
"ai" : {
"path" : "blah"
}
}
我的预期输出如下所示,从图像数组和dim.hsl嵌入文档中返回2个文档
{
"result" : [
{
"_id" : ObjectId("564b17873b91989fcb4e9707"),
"type" : "article",
"image" : [
{
"name" : "i3",
"hsl" : 1
},
{
"name" : "i1",
"hsl" : 1
}
],
"dim" : {
"hsl" : {
"path" : "blah"
}
}
}
],
"ok" : 1.0000000000000000
}
下面尝试的代码是不返回dim.hsl 嵌入式文档。 逻辑以内联方式包含在代码中。 我不确定mongodb表达式检查节点存在。所以我使用了{$ not:{$ not:'$ hsl'}}。 (我希望有更好的方法) 建议请。
db.survey.aggregate([
{ $match: {
image: { $elemMatch: {hsl: 1}}, // docs which have image.hsl
'dim.hsl': { $exists: true} // docs which have dim.hsl
}},
{ $redact : {
$cond: {
if: { $or : [
{$eq: ['$hsl',1]}, // for image array document with hsl:1
{$eq : ['$type' ,'article']},// for main document node
{$not : {$not : '$hsl'}} // for dim -- NOT WORKING
]},
then: "$$DESCEND",
else: "$$PRUNE"
}
}}]);
答案 0 :(得分:2)
$redact
无法正常工作的问题是因为$$DESCEND
及其作用。表达式基本上意味着“在每个级别”检查文档以确定是否满足条件。因此,即使您对存在的"hsl"
密钥进行了正确的测试,它仍然会“下降”到"path"
,其中该条件不会成立,因此没有内容是有效返回树上。
这里唯一真正的选择是完全“忽略”该密钥,基本上在所有级别提供$$ROOT
检查,而不是触及文档的嵌入部分。当然,您可以稍后使用$project
删除不需要的值:
db.doc.aggregate([
{ "$match": {
"image.hsl": 1,
"dim.hsl": { "$exists": true }
}},
{ "$redact": {
"$cond": {
"if": {
"$or": [
{ "$eq": ['$hsl',1]},
{ "$eq": ['$type' ,'article']},
{ "$ifNull": [ "$$ROOT.dim.hsl", false ] }
]
},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}},
{ "$project": {
"type": 1,
"image": 1,
"dim": {
"hsl": "$dim.hsl"
}
}}
])
但当然,由于$ROOT
条件始终为真,因此并未真正删除任何内容,这会否定操作点。
因此,请使用$map
和$setDifference
来过滤掉元素:
db.doc.aggregate([
{ "$match": {
"image.hsl": 1,
"dim.hsl": { "$exists": true }
}},
{ "$project": {
"type": 1,
"image": {
"$setDifference": [
{ "$map": {
"input": "$image",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.hsl", 1 ] },
{
"name": "$$el.name",
"hsl": "$$el.hsl"
},
false
]
}
}},
[false]
]
},
"dim": {
"hsl": "$dim.hsl"
}
}}
])
实际上,通过使用$map
检查每个元素,然后仅在正true
条件上返回所需字段来“过滤”数组内容,或者返回false
值,而不是数组元素。然后,通过与另一个具有false
的数组/集进行比较,从数组中删除所有[false]
值,结果只是返回的匹配。
其他子键投影保持不变,现在当然所有删除操作仅在一个$project
阶段完成。
然后返回你想要的结果:
{
"_id" : ObjectId("564b17873b91989fcb4e9707"),
"type" : "article",
"image" : [
{
"name" : "i3",
"hsl" : 1
},
{
"name" : "i1",
"hsl" : 1
}
],
"dim" : {
"hsl" : {
"path" : "blah"
}
}
}
答案 1 :(得分:2)
使用redact解决上述问题。
db.survey.aggregate([
{ "$match": {
"image.hsl": 1,
"dim.hsl": { "$exists": true }
}},
{ "$redact": {
"$cond": {
"if": {
"$or": [
{ "$eq": ['$hsl',1]},
{ "$eq": ['$type' ,'article']},
{ "$ifNull": [ "$hsl", false] },
{ "$ifNull": [ "$$CURRENT.path", false] }
]
},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}},
{ "$project": {
"type": 1,
"image": 1,
"dim": {
"hsl": "$dim.hsl"
}
}}
])