0

Building a Nodejs app, I'm trying to pull all doubly nested records from a Mongo Database. Attempts that I've made only removed one doubly nested record or all nested records. As in the example data below I've been trying to remove all tickets that has the same keyId. I've reduced the example but tickets as an array there might be other elements with the same structure with different "keyIds" that shouldn't be removed. I've looked this question but it only refrains to removing one record of a doubly nested array, not all of them at once.

[
    {
        "_id": "59fe54098448d822f89a7e62",
        "ownerId": "59b23449b20b7c1838eee1a3",
        "name": "Home",
        "keys": [
            {
                "id": "6d7435625564594f4a563554796c6a77",
                "name": "Front Door"
            }
        ],
        "grants": [
            {
                "id": "307658775634774a556b677650347072",
                "userId": "59b23449b20b7c1838eee1a3",
                "tickets": [
                    {
                        "keyId": "6d7435625564594f4a563554796c6a77",
                        "iv": "b7090268bdaf9ab55270e133b5629e28"
                    }
                ]
            },
            {
                "id": "37703369365765485763484a4358774d",
                "userId": "59b23449b20b7c1838eee1a3",
                "tickets": [
                    {
                        "keyId": "6d7435625564594f4a563554796c6a77",
                        "iv": "d2e2de0f9387c5d9b16424e8ac66a3c1"
                    }
                ]
            },
            {
                "id": "3451483977564d755278397939593633",
                "userId": "59b23449b20b7c1838eee1a3",
                "tickets": [
                    {
                        "keyId": "6d7435625564594f4a563554796c6a77",
                        "iv": "582ff50ac3d337c62eb53094470e3161"
                    }
                ]
            },
            {
                "id": "7059684f4e42754d55456e726b35664e",
                "userId": "59b23449b20b7c1838eee1a3",
                "tickets": [
                    {
                        "keyId": "6d7435625564594f4a563554796c6a77",
                        "iv": "b110ee5cb5da8941cc8ad6e1c3fe501c"
                    }
                ]
            }
        ]
    }
]

After removing all tickets with keyId=6d7435625564594f4a563554796c6a77 the intended data should look like this:

[
    {
        "_id": "59fe54098448d822f89a7e62",
        "ownerId": "59b23449b20b7c1838eee1a3",
        "name": "Home",
        "keys": [
            {
                "id": "6d7435625564594f4a563554796c6a77",
                "name": "Front Door"
            }
        ],
        "grants": [
            {
                "id": "307658775634774a556b677650347072",
                "userId": "59b23449b20b7c1838eee1a3",
                "tickets": []
            },
            {
                "id": "37703369365765485763484a4358774d",
                "userId": "59b23449b20b7c1838eee1a3",
                "tickets": []
            },
            {
                "id": "3451483977564d755278397939593633",
                "userId": "59b23449b20b7c1838eee1a3",
                "tickets": []
            },
            {
                "id": "7059684f4e42754d55456e726b35664e",
                "userId": "59b23449b20b7c1838eee1a3",
                "tickets": []
            }
        ]
    }
]

This code remove all grants at once:

db.places.update({}, {
    $pull: {
        "grants": {
            "tickets": {
                $elemMatch: { "keyId": keyID }
            }
        }
    }
}, { multi: true });

This pull out just the first ticket and with "$pullAll" doesn't do anything:

db.places.findAndModify(
    {
        ownerId: ownerID, "grants.tickets.keyId": keyID
    },
    [ ],
    { $pull: { "grants.$.tickets": { keyId: keyID } } },
    { multi: true },
    next
);

And this throws me an error saying: cannot use the part (grants of grants.tickets.$*.keyId) to traverse the element

db.places.update({ "grants.tickets.keyId": keyID }, {
    $pull: {
        "grants.tickets.$*.keyId": keyID
    }
}, { multi: true });
Rinaldi Segecin
  • 449
  • 8
  • 23
  • The second attempt is the only valid one, but as noted you get **one** match only by the outer "grants" array. You simply cannot "yet" update multiple array elements in a single request. You really should also be reading into this that "nested arrays" are not a good idea. The only real support for manipulation is in what will be the next release of MongoDB. But even so they are still a pain to query, and what you "think" you want nested arrays for, you actually want "attributes" on array items or external collection items representing the "nesting" instead. – Neil Lunn Nov 05 '17 at 02:10
  • `$pull: { "grants.$[].tickets.$[].keyId": keyID }` has thrown the "transverse" error as well. So I'm not able to do what I want in one query? That's a shame. This's my first mongodb implementation and goggling "attributes" and "external collection" for mongo came back results not much relevant straight to what I want to do with nested arrays, could you show me where or what tags should I use to look for? Thank you for the quick reply btw. – Rinaldi Segecin Nov 05 '17 at 02:46
  • You might try actually reading all of what the answers actually say instead of selectively going straight to copying code. What you are trying is syntax that is "not available in this version". The lesson here "first timer" is **don't nest arrays**, and if you're still intent on doing it then actually read what the "current" approaches to doing this are. – Neil Lunn Nov 05 '17 at 02:52
  • Well I have looked not only the answers you marked as duplicate of this question but others as well and couldn't find a solution. I didn't asked straight to some code but anything related to the topics you mentioned. But thanks anyway. – Rinaldi Segecin Nov 05 '17 at 03:20

0 Answers0