4

I'm very new to mongodb and i'm a little lost.

I have mongo db collection that looks like this :

  ({
    _id:id ,
    createdAt: new Date(),
    name:name,
    friends : [{name:1,children:[{name:sarah,age:12}]}],
    dogs : [{}]
  });

I would like to be able to insert a new element in the friends array if the name doesnt exist and a children element to that new array.

Pseudo code would be

If Directory.find id.friends.name = true

update and add a new children document {name:"sarah",age:5}

else

make a new friend element with a new children subdocument

After alot of research it seems that people are recommending the use of $exist but i can't find a way to use it in a sub document'

I've come up with this but it's not really working and i'm wondering how could i use that for my if else stament:

db.Directory.find({_id:id},{friends.name:"foo", {"$exists": True}})

For the actual query

db.Directory.update(
    { _id: id, 'friends.name': "foo" },
    {$push: {'friends.$.children':  {name:"x",age:"yy"}}}
)

And if it doesn't exist :

db.Directory.insert(
    { _id: id, 'friends.name': "foo" },
    {$push: {'friends.$.children':  {name:"x",age:"yy"}}}
)

But it's not really working , i'm not sure if there is something wrong in my formulas as it's a lot of trials and errors from research. I also don't really know if that the proper way to do it as i couldn't find anything on a value existing on sub documents and was planning on trying to do a Find() search store the value and then test for true or false on the result in JS to make either of the update/insert calls.

Hope someone can help

Edit : Let's say i want to add {name:john,age:15} to that friend name:1

friends : [{name:1,children:[{name:sarah,age:12}]}]

I'd like the output to be

friends : [{name:1,children:[{name:sarah,age:12},{name:john,age:15}]}]

or if name 1 doesnt exist

friends : []

make it so that it output

friends : [{name:1,children:[{name:john,age:15}]}]

Updated example :

case one :

friends : []

i add a new friend name "josh" with one child sarah , age 12 i get:

friends : [{name:"josh",children:[{name:sarah,age:12}]}]

This is perfect.

Now i add a new friend name 2 with children tom 15.

Nothing happens.

after , I want to add a new child to josh , timmy age 15

I get :

friends : [{name:"josh",children:[{name:timmy,age:12}]}]

And sarah disapeared.

user697
  • 233
  • 1
  • 7

1 Answers1

5

Please try to do it through Bulk operation, add one new friend through $addToSet operator and update friend through $set operator, update it after you making your question more clearly.

var bulk = db.Directory.initializeOrderedBulkOp();

// if `friends` is `[]`, push the empty children firstly through addToSet
bulk.find({_id: id, 'friends.name': {$exists: false}}).updateOne(
     {$addToSet: {friends: {name: 1, children: []}});

// if we find the match friend, update this one through `$set`
bulk.find({_id: id, 'friends.children.name': 'john'}).updateOne(
    {$set: {'friends.$.children': {name: 'john', age: 22}}});

// if we cannot find match friend, insert the new one through `$addToSet`
bulk.find({_id: id, 'friends.children.name': {$ne: "john"}}).updateOne( 
    {$addToSet: {'friends.0.children': {name: 'john', age: 12}}});

bulk.execute();
zangw
  • 43,869
  • 19
  • 177
  • 214
  • Thanks for the help. So, "nameinput" can be a js(string)variable right? Also,Does the first expression push the new element{name:x,age:yy} to the friends.name=name childrens input array ( user can have multiple childrens) ? – user697 Mar 01 '16 at 07:29
  • @user697, yes, the "nameinput" could be a js(string)variable. the `$set` just update the old friend of name is 'nameinput'. whereas the `addToSet` will add new friend to `friends` array, only the value inserted does NOT exists in the `friends` array. – zangw Mar 01 '16 at 07:36
  • hey , i've suceeded in implementing bulk on meteor after alot of hardship but it's seems there is an issue with the mongo formula that i can't find because it's actually adding a new "friends" array at the end of my main element instead of updating the children.. would oyu know why ? ( i've updated the post in case i wasn't clear) – user697 Mar 04 '16 at 02:33
  • @user697, you mean `{$addToSet: {'friends.0.children': {name: 'john', age: 12}}}` does not work? could you please give me some examples ? because I test it work well in my test data. – zangw Mar 04 '16 at 09:16
  • @user697, wow, you make me so confused, which you describe now is different with what you said in you question... so sad... or you did not give all information in your question. – zangw Mar 04 '16 at 09:21
  • @user697, please attention, one question of SO is for one issue only, if you have multiple questions please ask different questions. – zangw Mar 04 '16 at 09:22
  • I've updated my question answer. Sorry maybe i explain myself poorly english not my main language. It's the same question from the beginning that's why i was thinking of using " $push" but i thought addtoset was the same. – user697 Mar 04 '16 at 09:28
  • @user697, $push will push the element into array anyway. whereas, $addToSet will push element to array only if there is no duplicate element in this array. I highly recommend you to read the doc https://docs.mongodb.org/manual/reference/operator/update/addToSet/ carefully – zangw Mar 04 '16 at 09:43
  • but add to set is not really what i want then, i guess i will look for other methods. If friends.name $exist , then push new children to children array. so user can have multiple children. – user697 Mar 04 '16 at 09:54