Mongodb 使用mongo$redact在数组中包含嵌入文档和嵌入文档

Mongodb 使用mongo$redact在数组中包含嵌入文档和嵌入文档,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,对于下面的文档,我需要输出 1. image arrays which are hsl:1 2. dim.hsl embedded document 主文档 { "_id" : ObjectId("564b17873b91989fcb4e9707"), "type" : "article", "image" : [ { "name" : "i3", "hsl" : 1 }, { "name" : "i1",

对于下面的文档,我需要输出

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"
     }
}}]);
为什么不能像这样工作的问题在于它的原因和作用。该表达基本上意味着“在每个级别”检查文档,以确定是否满足条件。因此,即使您对存在的
“hsl”
键进行了正确的测试,它仍然会“下降”到
“path”
,而该条件将不成立,因此没有有效的内容返回树的更高位置

这里唯一真正的方法是完全“忽略”这个关键,基本上是在所有级别提供检查,而不是触及文档的嵌入部分。当然,您可以在以后的操作中删除不需要的值:

db.doc.aggregate([
{“$match”:{
“image.hsl”:1,
“dim.hsl”:{“$exists”:true}
}},
{“$redact”:{
“$cond”:{
“如果”:{
“$or”:[
{“$eq”:['$hsl',1]},
{“$eq”:['$type','article']},
{“$ifNull”:[“$$ROOT.dim.hsl”,false]}
]
},
“然后”:“$$down”,
“else”:“$$PRUNE”
}
}},
{“$project”:{
“类型”:1,
"形象":一,,
“昏暗”:{
“hsl”:“$dim.hsl”
}
}}
])
当然,这并不会真正删除任何内容,因为
$ROOT
条件始终为真,这否定了操作的要点

因此,使用和过滤掉元素:

db.doc.aggregate([
{“$match”:{
“image.hsl”:1,
“dim.hsl”:{“$exists”:true}
}},
{“$project”:{
“类型”:1,
“图像”:{
“$setDifference”:[
{“$map”:{
“输入”:“$image”,
“as”:“el”,
“在”:{
“$cond”:[
{“$eq”:[“$$el.hsl”,1]},
{
“名称”:“$$el.name”,
“hsl”:“$$el.hsl”
},
假的
]
}
}},
[错误]
]
},
“昏暗”:{
“hsl”:“$dim.hsl”
}
}}
])
实际上,它通过使用
$map
检查每个元素,然后在一个正向
true
条件下仅返回所需字段来“过滤”数组内容,或者返回一个
false
值,而不是数组元素。然后,通过与另一个具有
[false]
的数组/集合进行比较,从数组中删除所有
false
值,结果仅为返回的匹配项

另一个子键投影保持不变,现在当然所有的删除只在一个
$project
阶段中完成

这将返回您想要的结果:

{
“_id”:ObjectId(“564b17873b91989fcb4e9707”),
“类型”:“文章”,
“图像”:[
{
“名称”:“i3”,
“hsl”:1
},
{
“名称”:“i1”,
“hsl”:1
}
],
“昏暗”:{
“hsl”:{
“路径”:“废话”
}
}
}
为什么不能这样工作的问题在于它的原因和作用。该表达基本上意味着“在每个级别”检查文档,以确定是否满足条件。因此,即使您对存在的
“hsl”
键进行了正确的测试,它仍然会“下降”到
“path”
,而该条件将不成立,因此没有有效的内容返回树的更高位置

这里唯一真正的方法是完全“忽略”这个关键,基本上是在所有级别提供检查,而不是触及文档的嵌入部分。当然,您可以在以后的操作中删除不需要的值:

db.doc.aggregate([
{“$match”:{
“image.hsl”:1,
“dim.hsl”:{“$exists”:true}
}},
{“$redact”:{
“$cond”:{
“如果”:{
“$or”:[
{“$eq”:['$hsl',1]},
{“$eq”:['$type','article']},
{“$ifNull”:[“$$ROOT.dim.hsl”,false]}
]
},
“然后”:“$$down”,
“else”:“$$PRUNE”
}
}},
{“$project”:{
“类型”:1,
"形象":一,,
“昏暗”:{
“hsl”:“$dim.hsl”
}
}}
])
当然,这并不会真正删除任何内容,因为
$ROOT
条件始终为真,这否定了操作的要点

因此,使用和过滤掉元素:

db.doc.aggregate([
{“$match”:{
“image.hsl”:1,
“dim.hsl”:{“$exists”:true}
}},
{“$project”:{
“类型”:1,
“图像”:{
“$setDifference”:[
{“$map”:{
“输入”:“$image”,
“as”:“el”,
“在”:{
“$cond”:[
{“$eq”:[“$$el.hsl”,1]},
{
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"
        }
    }}
])