[SERVER-17038] $$PARENT for $redact Aggregations Created: 25/Jan/15  Updated: 06/Dec/22

Status: Open
Project: Core Server
Component/s: Aggregation Framework
Affects Version/s: None
Fix Version/s: features we're not sure of

Type: Improvement Priority: Minor - P4
Reporter: Benjamin M Assignee: Backlog - Query Execution
Resolution: Unresolved Votes: 0
Labels: expression, usability
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Assigned Teams:
Query Execution
Participants:

 Description   

It would be nice, if it's possible to access the parent within a $redact Aggregation.

Example:

{
  id: ...,
  i18n: {
    en: {
      foo: "bar",
      _lang: "en"
    },
    jp: {
      foo: "baz",
      _lang: "jp"
    }
  }
}

Now I'd like to retrieve everything with i18n = jp, and keep a fallback to i18n = en. The code could look like this:

{ $redact: {
    $cond: {
        if: {
            $or: [
                { $not : "$_lang" },
                { $eq: [ "$_lang", "jp" ] },
                { $and: [
                    { $eq: [ "$_lang", "en" ] },
                    { $not: "$$PARENT.jp" }
                ]}
            ]
        },
        then: "$$DESCEND",
        else: "$$PRUNE"
    }
}}

Thank you!



 Comments   
Comment by Benjamin M [ 30/Jan/15 ]

The only question is: What happens, when the cursor is at $$ROOT level and I call $$PARENT ? I think it has to throw an exception, because it's always possible to avoid that call, i.e.:

$cond: {
        if: { $eq: [ "$$CURRENT", "$$ROOT" ] },
        then: "...",
        else: "..."
}

Comment by Andy Schwerin [ 30/Jan/15 ]

I'm not sure if a bound variable is sufficient generally, or if a $parent operator would be needed in general, but it seems like it could be useful.

Comment by Benjamin M [ 29/Jan/15 ]

I use $readct, because I want this functionality at all subdocuments. So using $$ROOT won't help at all.

Comment by Ramon Fernandez Marina [ 28/Jan/15 ]

benneq, if I understand correctly your use case I think can make it work using $$ROOT. For example, given the following documents:

> db.foo.find().pretty()
{
        "_id" : ObjectId("54c9119d20e365e24cb28be1"),
        "id" : 1,
        "i18n" : {
                "en" : {
                        "foo" : "english1",
                        "_lang" : "en"
                },
                "jp" : {
                        "foo" : "japanese1",
                        "_lang" : "jp"
                }
        }
}
{
        "_id" : ObjectId("54c9119d20e365e24cb28be2"),
        "id" : 2,
        "i18n" : {
                "en" : {
                        "foo" : "english1",
                        "_lang" : "en"
                }
        }
}

you can run the following:

> db.foo.aggregate([ { $redact: { $cond: { if: { $or: [ { $not : "$_lang" }, { $eq: [ "$_lang", "jp" ] }, { $and: [ { $eq: [ "$_lang", "en" ] },  { $not: "$$ROOT.i18n.jp" } ] }, ] }, then: "$$DESCEND", else: "$$PRUNE" } }}]).pretty()
{
        "_id" : ObjectId("54c9119d20e365e24cb28be1"),
        "id" : 1,
        "i18n" : {
                "jp" : {
                        "foo" : "japanese1",
                        "_lang" : "jp"
                }
        }
}
{
        "_id" : ObjectId("54c9119d20e365e24cb28be2"),
        "id" : 2,
        "i18n" : {
                "en" : {
                        "foo" : "english1",
                        "_lang" : "en"
                }
        }
}

Hope this helps.

Comment by Benjamin M [ 25/Jan/15 ]

Typo. It should be

{ $and: [
    { $eq: [ "$_lang", "en" ] },
    { $not: "$$PARENT.jp" }
]}

Generated at Thu Feb 08 03:43:06 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.