MongoDB:'$ redact'仅用于匹配嵌入对象

时间:2022-09-11 16:10:35

I have the following style Collection:

我有以下风格的集合:

{ 
    "_id" : "5548d5ebb8157a53e9ceb9a4",
    "layers" : [
        { "_id" : "5548c97eb8157a53e9ceb9a0", "name" : "layer1"},
        { "_id" : "5548c97eb8157a53e9ceb9a1", "name" : "layer2"}
    ]
}
{ 
    "_id" : "5548d5ebb8157a778899b9a5",
    "layers" : [
        { "_id" : "5548c97eb8157a53e9ceb9a2", "name" : "layer1"},
        { "_id" : "5548c97eb8157a53e9ceb9a3", "name" : "layer2"}
    ]
}
...

I now want to query for layers with certain _id. What I want is only an array of matching layer objects. Here is what I tried:

我现在想要查询具有特定_id的图层。我想要的只是一个匹配的图层对象数组。这是我尝试过的:

db.graphs.aggregate([
{ $match: { "layers._id": { $in: ["5548c97eb8157a53e9ceb9a1"] } } },
{ $redact : { $cond: 
    { if: 
        { $or : [
            { $eq: ["$_id","5548c97eb8157a53e9ceb9a1"] },
            { $not : "$_id" }]
        },
        then: "$$DESCEND",
        else: "$$PRUNE" 
    } 
} }]);

Doesn't work - I get an empty result. Any hints?

不起作用 - 我得到一个空的结果。任何提示?

1 个解决方案

#1


Ok I found the solution, short version:

好的我找到了解决方案,简短版本:

db.test.aggregate([ 
    { $match: { "layers._id": { $in: ["5548c97eb8157a53e9ceb9a1"] } } }, 
    { $redact : { $cond:
        { if:
            { $or : [
                { $eq: ["$_id","5548c97eb8157a53e9ceb9a1"] },
                { $or : "$layers" }]
            },
            then: "$$DESCEND",
            else: "$$PRUNE"
        }
} }]);

Explanation: first understand that the $redact operator walks the matched documents level wise downwards, like a tree / graph. The problem here was that the top level document already contains an _id field. Therefore the { $not: "_id" } expression evaluates to false. On the same, top level, so does the { $eq: ["$_id","5548c97eb8157a53e9ceb9a1"] } expression since that id would only be found on the nested, next level. As a result the top level evaluates to false and "$$PRUNE" is done instead of "$$DESCEND".

说明:首先要了解$ redact操作符向下向下移动匹配的文档,如树/图。这里的问题是*文档已经包含一个_id字段。因此,{$ not:“_ id”}表达式的计算结果为false。在同一顶层,{$ eq:[“$ _id”,“5548c97eb8157a53e9ceb9a1”]}表达式也是如此,因为该id只能在嵌套的下一级找到。结果,*评估为false并且“$$ PRUNE”完成而不是“$$ DESCEND”。

The provided solution makes the top level pass by letting the test be true if the checked level has a layers property - which the top level, and only the top level, does have.

如果检查的级别具有图层属性(*,只有*级别)具有图层属性,则提供的解决方案会使测试成为正确。

#1


Ok I found the solution, short version:

好的我找到了解决方案,简短版本:

db.test.aggregate([ 
    { $match: { "layers._id": { $in: ["5548c97eb8157a53e9ceb9a1"] } } }, 
    { $redact : { $cond:
        { if:
            { $or : [
                { $eq: ["$_id","5548c97eb8157a53e9ceb9a1"] },
                { $or : "$layers" }]
            },
            then: "$$DESCEND",
            else: "$$PRUNE"
        }
} }]);

Explanation: first understand that the $redact operator walks the matched documents level wise downwards, like a tree / graph. The problem here was that the top level document already contains an _id field. Therefore the { $not: "_id" } expression evaluates to false. On the same, top level, so does the { $eq: ["$_id","5548c97eb8157a53e9ceb9a1"] } expression since that id would only be found on the nested, next level. As a result the top level evaluates to false and "$$PRUNE" is done instead of "$$DESCEND".

说明:首先要了解$ redact操作符向下向下移动匹配的文档,如树/图。这里的问题是*文档已经包含一个_id字段。因此,{$ not:“_ id”}表达式的计算结果为false。在同一顶层,{$ eq:[“$ _id”,“5548c97eb8157a53e9ceb9a1”]}表达式也是如此,因为该id只能在嵌套的下一级找到。结果,*评估为false并且“$$ PRUNE”完成而不是“$$ DESCEND”。

The provided solution makes the top level pass by letting the test be true if the checked level has a layers property - which the top level, and only the top level, does have.

如果检查的级别具有图层属性(*,只有*级别)具有图层属性,则提供的解决方案会使测试成为正确。