MongoDB AddToSet how to prevent duplicate by specific fields?

Viewed 597

I have an array of objects in an entity in a DB record. I want to push new object to that array, but I don't want to push the same object multiple times. I know I can use $addToSet, but the problem occurs that in each object I add timestamp, so this method doesn't distinguish that the object already in the array, it fully compare the objects and if the timestamp has changed it will add it twice so I will have:

[
  { a: 1, timestamp: X },
  { a: 1, timestamp: X+Y }
]

As you can see I already have a, but since timestamps has changed, for $addToSet it is okay to add this object once again.

How can I check agains specific fields, so I will check only against a property - ignoring the timestamp?

1 Answers

you can do it using a bulkWrite operation to issue 2 commands in one go. first one to remove the matching array document. and then to push a new one in to the array. so there will be no duplicates in the array.

say you have the following document:

{
    "_id" : ObjectId("606dc0a6a142af062c5ed9bc"),
    "array" : [
        {
            "a" : 1,
            "timestamp" : 12345
        },
        {
            "a" : 2,
            "timestamp" : 54321
        }
    ]
}

you can issue the following bulk write command to achieve your goal:

db.Collection.bulkWrite(
[
    {
        updateOne: {
            filter: {
                _id: ObjectId("606dc0a6a142af062c5ed9bc")
            },
            update: {
                "$pull": {
                    array: { a: 2 }
                }
            }
        }
    },
    {
        updateOne: {
            filter: {
                _id: ObjectId("606dc0a6a142af062c5ed9bc")
            },
            update: {
                "$push": {
                    array: {
                        a: 2,
                        timestamp: 99999
                    }
                }
            }
        }
    }
])

the above will replace the array object if it exists with the supplied one. if you need to only insert an object if it doesn't exist in the array and if it does exist, do nothing, then you can do this:

db.Collection.updateOne(
    {
        _id: ObjectId("606dc0a6a142af062c5ed9bc"),
        "array.a": { $ne: 3 }
    },
    {
        $push: {
            array: {
                a: 3,
                timestamp: 55555
            }
        }
    }
)
Related