6

Below is my data structure.

{
    "_id" : "room1",
    "members" : [ 
        {
            "_id" : "member1",
            "name" : "Michael",
            "payments" : [
                {
                    "month": "2018/09"
                    "amount": "20"
                }
            ]
        }, 
    ]
}

I want to push below object to Michael's payments

{ 
  "month": "2018/09", 
  "amount": "5000" 
}

In this case, What I want to is overwrite object, because month: "2018/09" already exist. Like below :

{
    "_id" : "room1",
    "members" : [ 
        {
            "_id" : "member1",
            "name" : "Michale",
            "payments" : [
                {
                    "month": "2018/09"
                    "amount": "5000"
                }
            ]
        }, 
    ]
}

And, In case when I want to push object that not exist same month in payments, I want to add this object to payments.

{ 
  "month": "2018/10", 
  "amount": "2000" 
}

So the expected result is

{
    "_id" : "room1",
    "members" : [ 
        {
            "_id" : "member1",
            "payments" : [
                {
                    "month": "2018/09"
                    "amount": "5000"
                },
                {
                    "month": "2018/10"
                    "amount": "2000"
                }
            ]
        }, 
    ]
}

I tried like below, but it's not working. My code generate duplicated new month object every time I tried. How can I do this properly?

Rooms.update(
    {
        _id: "room1",
        "members._id": "member1",
        "members.$.payments": {
            $not: {
                $elemMatch: {
                    month: req.body.month
                }
            }
        }
    },
    {
        $addToSet: {
            "members.$.payments": {
                month: req.body.month,
                amount: req.body.value
            }
        }
    },
    { multi: true }, function (err, result) {
        console.log(result)
    }
)
8
  • use $ne instead of $not here... "members.$.payments": { $elemMatch: { month: { $ne: req.body.month } } } Commented Sep 12, 2018 at 12:24
  • Get rid of $ in the members.$.payments in query part. Commented Sep 12, 2018 at 12:27
  • @AnthonyWinzlet I plused you guys's suggetion but still not working... It is not generated duplicated object anymore, but it's not overwrite. Commented Sep 12, 2018 at 13:02
  • @Veeram Thanks, I removed it. but it's still not working -- no more duplicated object, but not overwrited Commented Sep 12, 2018 at 13:03
  • That is working as expected. $addToSet doesn't overwrite the element. Commented Sep 12, 2018 at 13:07

3 Answers 3

3

You can use below command to add without duplicity either in months or amount

Rooms.update(
    {
        _id: "room1",
        "members._id": "member1"
    },
    {
        $addToSet: {
            "members.$.payments": {
                month: req.body.month,
                amount: req.body.value
            }
        }
    },function (err, result) {
        console.log(result)
    }
)
Sign up to request clarification or add additional context in comments.

3 Comments

Have you red my question... your answer will generate duplicated object.
No it's not i was checked it locally
This is the same as what Juntae wrote in his original post. This results in the error 'The positional operator did not find the match needed from the query'.
1

So I heard I have to determine duplication myself, so below is my code... it's writing now.,,


So Finally this is my code

  Clubs.findOne({ 
        uid: req.params.club_id,
        "members._id": mongoose.Types.ObjectId(req.params.member_uid)
    }, function(err, club){

        let member = club.members.filter(el => {
            if(el._id.equals(req.params.member_uid)) return el
        })

        let duplicated = false; 
        member[0].payments.map(el => {
            if(el.month === req.body.month) duplicated = true
        })

       if(duplicated){

        Clubs.update(
            {
                uid: req.params.club_id,
                "members._id": mongoose.Types.ObjectId(req.params.member_uid),
            },
            {
                $set: {
                    ["members.$.payments."+index+".amount"] : req.body.value
                }
            },
            function (err, result, third) {
                if (err) throw err
                console.log('result')
                console.log(result)
                res.json({})
            }
        )


    } else {

        Clubs.update(
            {
                uid: req.params.club_id,
                "members._id": mongoose.Types.ObjectId(req.params.member_uid),
            },
            {
                $push: {
                    "members.$.payments" : { 
                        month : req.body.month, 
                        amount: req.body.value 
                    }
                }
            },
            function (err, result, third) {
                if (err) throw err
                console.log('result')
                console.log(result)
                res.json({})
            }
        )
    }

    })

Comments

0

Perhaps consider changing the structure of your nested array to an object? So change this

{
  "payments": [{
      "month": "2018/09"
      "amount": "5000"
    },
    {
      "month": "2018/10"
      "amount": "2000"
    }
  ]
}

to this:

{
  "payments": {
    "2018/09": "5000",
    "2018/10": "2000"
  }
}

Then you can do a simple update:

Rooms.update({
    _id: "room1",
    "members._id": "member1",
    "members.payments": {
      $exists: true
    }
  }, {
    $set: {
      "members.payments." + req.body.month: req.body.value
    }
  },

)

Comments

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.