0

The end goal is to add a new partner to the partners list per pathway object IF they don't already exist. AND if the pathway_name does not equal Engagement Team.

I would want to add the following partner for example:

{
                    "_id" : ObjectId("5dd5762be13e15a73f042ce5"), 
                    "partner" : ObjectId("5dd57633bf0cbbbb36bc112f")
}

 "pathways" : [
        {
            "_id" : ObjectId("5d837689b57cc711487f1cf0"), 
            "pathway_name" : "Electronics Technology with Advanced Manufacturing Mechatronics", 
            "partners" : [
                {
                    "_id" : ObjectId("5d837ab8b57cc711487f1d28"), 
                    "partner" : ObjectId("5d837426b57cc711487f1c96")
                }
            ]
        }, 
        {
            "_id" : ObjectId("5d837694b57cc711487f1cf1"), 
            "pathway_name" : "Pre-Mechanical Engineering", 
            "partners" : [
                {
                    "_id" : ObjectId("5d837acfb57cc711487f1d29"), 
                    "partner" : ObjectId("5d837421b57cc711487f1c92")
                }
            ]
        }, 
        {
            "_id" : ObjectId("5da6055da0eb361cc8da26dc"), 
            "pathway_name" : "Engagement Team", 
            "partners" : [
                {
                    "_id" : ObjectId("5da60711a0eb361cc8da26f0"), 
                    "partner" : ObjectId("5d83749fb57cc711487f1cc2")
                }
            ]
        }
    ], 

My current query is as follows, i'm not sure how to add the logic of only adding the partner if they don't exist based off the partner field itself and not the _id field of a partner object.

db.getCollection("schools").updateMany({}, $addToSet:{"pathways$[].partners"})

Expected Result:

 "pathways" : [
        {
            "_id" : ObjectId("5d837689b57cc711487f1cf0"), 
            "pathway_name" : "Electronics Technology with Advanced Manufacturing Mechatronics", 
            "partners" : [
                {
                    "_id" : ObjectId("5d837ab8b57cc711487f1d28"), 
                    "partner" : ObjectId("5d837426b57cc711487f1c96")
                },
                {
                    "_id" : ObjectId("5dd5762be13e15a73f042ce5"), 
                    "partner" : ObjectId("5dd57633bf0cbbbb36bc112f")
                }
            ]
        }, 
        {
            "_id" : ObjectId("5d837694b57cc711487f1cf1"), 
            "pathway_name" : "Pre-Mechanical Engineering", 
            "partners" : [
                {
                    "_id" : ObjectId("5d837acfb57cc711487f1d29"), 
                    "partner" : ObjectId("5d837421b57cc711487f1c92")
                },
                {
                    "_id" : ObjectId("5dd5762be13e15a73f042ce5"), 
                    "partner" : ObjectId("5dd57633bf0cbbbb36bc112f")
                }
            ]
        }, 
        {
            "_id" : ObjectId("5da6055da0eb361cc8da26dc"), 
            "pathway_name" : "Engagement Team", 
            "partners" : [
                {
                    "_id" : ObjectId("5da60711a0eb361cc8da26f0"), 
                    "partner" : ObjectId("5d83749fb57cc711487f1cc2")
                }
            ]
        }
    ], 


Snoopy
  • 1,257
  • 2
  • 19
  • 32

1 Answers1

1

Please try it and let me know :

db.getCollection("schools").update(
    {},
    {
        $push: {
            'pathways.$[eachPathway].partners': {
                "_id": ObjectId("5dd5762be13e15a73f042ce5"),
                "partner": ObjectId("5dd57633bf0cbbbb36bc112f")
            }
        }
    },
    { arrayFilters: [{ $and: [{ "eachPathway.pathway_name": { $ne: "Engagement Team" } },
    {"eachPathway.partners._id":{$ne: ObjectId("5dd5762be13e15a73f042ce5")}}]}], multi: true }
)

Note : Seems like $addToSet doesn't work on entire object comparison, So we need to compare at at least one field from the input object with the same field in objects from the array. Atlast we can use $push, as duplicate objects are already filtered out, but not sure how to achieve it if you need entire object comparison - I think it might not be needed though.

Might See this error or no docs being updated :

No array filter found for identifier 'eachPathway' in path 'pathways.$[eachPathway].partners'

In short, this is because robo3T or any-other mongoDB client which is being used is not able to process arrayFilters, So to test this query please directly test it using code.

Ref : No array filter issue

whoami - fakeFaceTrueSoul
  • 17,086
  • 6
  • 32
  • 46
  • Sorry for accepting this so late, this worked! How would I do the same, but generate a new `_id` field instead of the static `"_id": ObjectId("5dd5762be13e15a73f042ce5")`? – Snoopy Nov 22 '19 at 03:55
  • @Snoopy : are you using mongoose ? – whoami - fakeFaceTrueSoul Nov 22 '19 at 04:15
  • Yes I am using mongoose – Snoopy Nov 22 '19 at 04:28
  • @Snoopy : Please check these & let me know, if you've any issue generating :: https://stackoverflow.com/questions/17899750/how-can-i-generate-an-objectid-with-mongoose && https://stackoverflow.com/questions/11604928/is-there-a-way-to-auto-generate-objectid-when-a-mongoose-model-is-newed?rq=1 – whoami - fakeFaceTrueSoul Nov 22 '19 at 04:37
  • @Snoopy : Also as I stated above - entire object comparison might not work on `$addToSet`, but seems like it does, please check on that if it does then ignore the check `{"eachPathway.partners._id":{$ne: ObjectId("5dd5762be13e15a73f042ce5")}}` written on arrayFilters :-) – whoami - fakeFaceTrueSoul Nov 22 '19 at 05:07