1

Suppose I have a document collection

{ "id":1, "arr":[{"a":1, "b":2, "c":3}, {"a":6, "b":0, "c":8},....]}
{ "id":2, "arr":[{"a":7, "b":1, "c":4}, {"a":5, "b":2, "c":6},....]}

Now the user will provide me with an array of unknown size like this

let user_id: 2;
let user_arr = [{"a":7, "b":1, "c":9}, {"a":1, "b":6, "c":3},.....]

Now I want to push user provided arr documents in user's arr for user_id given by user such that (a,b) combination of both values will not be duplicated for him/her.

For e.g - for above case as (a:7, b:1) already exist in arr so It won't get inserted, but for (a:1, b:6) no record contains both of them that's why it {"a":1, "b":6, "c":3} gets inserted in the arr.

Please help me, anyone.

2
  • Hey, just to clarify: "such that (a,b) combination of both values will not be duplicated" - you mean duplicated inside an array or duplicated in your collection ? Commented Nov 19, 2018 at 17:03
  • @mickl duplicated inside that array only, Thanks. Commented Nov 19, 2018 at 17:04

1 Answer 1

1

You can use $elemMatch combined with $not to check if the document you're trying to $push will not duplicate any other subdocument in that array. Try:

db.col.update({ id: user_id, arr: { $not: { $elemMatch: { a: 7, b: 1 } } } }, { $push: { arr: { a:7, b:1, c:9} } })

Additional condition for id will force this operation to modify one or zero documents.

To perform multiple updates you can use bulkWrite (MongoDB 3.2+):

db.col.bulkWrite(
    [
        { 
            updateOne : {
                    "filter" : { id: 2, arr: { $not: { $elemMatch: { a: 7, b: 1 } } } },
                    "update" : { $push: { arr: { a:7, b:1, c:9} } }
                }
        },
        { 
            updateOne : {
                    "filter" : { id: 2, arr: { $not: { $elemMatch: { a: 1, b: 6 } } } },
                    "update" : { $push: { arr: { a:1, b:6, c:3} } }
                }
        }
    ]
);

As a response you'll get:

{
    "acknowledged" : true,
    "deletedCount" : 0,
    "insertedCount" : 0,
    "matchedCount" : 1,
    "upsertedCount" : 0,
    "insertedIds" : {

    },
    "upsertedIds" : {

    }
}

which means that only one of two conditions matched the document with id: 2

Sign up to request clarification or add additional context in comments.

9 Comments

How can second item conflict with document 2? as it is not present it will simply get created. Also is there no workaround to write this in one single query instead of writing update for user_arr size. Thanks for helping :)
Also from every document, for $elemmatch I would have to first omit c from them?
@SudhanshuGaur sorry, modified my answer, I think I misunderstood your initial question, the best way would be to use bulkWrite and you can build that command dynamically based on user_arr
I don't think so and the reason for that is simply because the document can or cannot match the condition, there's nothing like document "partially" matching the condition, that's why you have to split that array into separate operations
Yes, but aggregate is used to retrieve the data (mostly) or to replace existing collection (entire) and that's not what you're trying to achieve here :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.