I have a document:
{ 'profile_set' :
[
{ 'name' : 'nick', 'options' : 0 },
{ 'name' : 'joe', 'options' : 2 },
{ 'name' : 'burt', 'options' : 1 }
]
}
and would like to add a new document to the profile_set
set if the name doesn't already exist (regardless of the option).
So in this example if I tried to add:
{'name' : 'matt', 'options' : 0}
it should add it, but adding
{'name' : 'nick', 'options' : 2}
should do nothing because a document already exists with name nick
even though the option
is different.
Mongo seems to match against the whole element and I end up with to check if it's the same and I end up with
profile_set containing [{'name' : 'nick', 'options' : 0}, {'name' : 'nick', 'options' : 2}]
Is there a way to do this with $addToSet
or do I have to push another command?
The $addToSet operator adds a value to an array unless the value is already present, in which case $addToSet does nothing to that array. The $addToSet operator has the form: { $addToSet: { <field1>: <value1>, ... } } To specify a <field> in an embedded document or in an array, use dot notation.
If the value is an array, $push appends the whole array as a single element. To add each element of the value separately, use the $each modifier with $push . For an example, see Append a Value to Arrays in Multiple Documents. For a list of modifiers available for $push , see Modifiers.
To remove an element, update, and use $pull in MongoDB. The $pull operator removes from an existing array all instances of a value or values that match a specified condition.
Learn how to update array fields in documents in MongoDB collections. You can use the updateOne() or updateMany() methods to add, update, or remove array elements based on the specified criteria. It is recommended to use the updateMany() method to update multiple arrays in a collection.
You can qualify your update
with a query object that prevents the update if the name
is already present in profile_set
. In the shell:
db.coll.update(
{_id: id, 'profile_set.name': {$ne: 'nick'}},
{$push: {profile_set: {'name': 'nick', 'options': 2}}})
So this will only perform the $push
for a doc with a matching _id
and where there isn't a profile_set
element where name
is 'nick'
.
As of MongoDB 4.2 there is a way to do this using aggregation expressions in update.
For your example case, you would do this:
newSubDocs = [ {'name' : 'matt', 'options' : 0}, {'name' : 'nick', 'options' : 2} ];
db.coll.update( { _id:1 },
[
{$set: { profile_set: {$concatArrays: [
"$profile_set",
{$filter: {
input:newSubDocs,
cond: {$not: {$in: [ "$$this.name", "$profile_set.name" ]}}
}}
]}}}
])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With