3

I have document

 {
    "_id" : ObjectId("5aebf141a805cd28433c414c"),
    "forumId" : ObjectId("5ae9f82989f7834df037cc90"),
    "userName" : "Name",
    "usersLike" : [ 
        "1","2"
    ],
    "comment" : "Comment",
}

I want to remove value from usersLike array if the value exists, or add if the value does not exist.

Eg:

If I try to push 1 into usersLike, it should return

{
    "_id" : ObjectId("5aebf141a805cd28433c414c"),
    "forumId" : ObjectId("5ae9f82989f7834df037cc90"),
    "userName" : "Name",
    "usersLike" : [ 
        "2"
    ],
    "comment" : "Comment",
}

How can I query it..??

sudhin
  • 35
  • 1
  • 6
  • Value exists as in? The array `usersLike` exists or a particular value should exist in `usersLike`? – Sivaprasanna Sethuraman May 04 '18 at 07:04
  • Can you please give a more concrete example? – dnickless May 04 '18 at 07:08
  • If the value 1 exists in the array usersLike it should be removed. Otherwise, the value 1 should be added to the array usersLike. – sudhin May 04 '18 at 07:45
  • I think more to the point here is why would you not know it exists? If you are trying to build something like "this site" or "likes" on facebook for example, then the data in the page actually knows the current user already has a vote. So if I "upvote" this question, and then come back to this page later, part of the page data includes the record of "my vote", so before I even send a request to vote again I can already tell I have voted, hence no need to send the request. – Neil Lunn May 04 '18 at 07:51
  • I think you're trying to "blind toggle" such values under just those circumstances, but it's not really the correct approach. As stated, your "client" **should** already know if a user has voted/liked. For a bit more detail, see [How to Model a “likes” voting system with MongoDB](https://stackoverflow.com/questions/28006521/how-to-model-a-likes-voting-system-with-mongodb). – Neil Lunn May 04 '18 at 07:52
  • @NeilLunn. Thank you.! – sudhin May 04 '18 at 09:37
  • You can't do this... Mongodb doesn't support compating fields, conditionals etc. in the update statement. – Ashh May 04 '18 at 09:42

4 Answers4

5

MongoDB version 4.2+ introduces pipelined update. Which means we can now use aggregation operators while updating. this gives us a lot of power.

db.collection.updateOne(
    {
        _id: ObjectId("597afd8200758504d314b534")
    },
    [
        {
            $set: {
                usersLike: {
                    $cond: [
                        {
                            $in: ["1", "$usersLike"]
                        },
                        {
                            $setDifference: ["$usersLike", ["1"]]
                        },
                        {
                            $concatArrays: ["$usersLike", ["1"]]
                        }
                    ]
                }
            }
        }
    ]
)
Tom Slabbaert
  • 21,288
  • 10
  • 30
  • 43
0

Try this :

db.collectionName.update({_id:ObjectId("597afd8200758504d314b534")},{$pull:{'usersLike':"1"}}, {multi: true})
whoami - fakeFaceTrueSoul
  • 17,086
  • 6
  • 32
  • 46
  • Can't be done using this query... This query will only extract(`$pull`) the id, can't add(`$push`) and as the question says `$push` and `$pull` should be done simultaneously... – Ashh May 04 '18 at 16:57
  • Mongodb doesn't support conditional push or pull update. However you can still do it by using find (db.collectionName.find({_id:ObjectId("597afd8200758504d314b534"),usersLike:{$in:["1"]}}).pretty()) , if id exist in usersLike than pull else push. – Bhagyashree Sarkar May 05 '18 at 06:50
  • 1
    yes it can be done... but he wants it in a single query, which is not possible – Ashh May 05 '18 at 06:53
0

Mongodb doesn't support conditional push or pull update. However you can still do it by using find:

 db.collectionName.find({_id:ObjectId("597afd8200758504d314b534"),usersLike:{$in:["1"]}}).pretty()

if id exist in usersLike than pull else push.

Or you use the update query to pull as:

db.collectionName.update({
    _id: ObjectId("597afd8200758504d314b534"),
    usersLike: {
        $in: ["1"]
    }
    }, {
        $pull: { 'usersLike': "1" }
    }, { multi: true })

And to push you can use:

db.collectionName.update({
   _id:ObjectId("597afd8200758504d314b534"), 
   usersLike:{$nin:["1"]
}},{
   $push:{'usersLike':"1"}
}, {multi: true})
whoami - fakeFaceTrueSoul
  • 17,086
  • 6
  • 32
  • 46
0

Try this

if db.collectionName.find({'_id':ObjectId("5aebf141a805cd28433c414c"),'usersLike:{'$in:['1']}}).count() > 0:

    db.collectionName.update({'_id':ObjectId("5aebf141a805cd28433c414c")},{'$pull':{'usersLike':'1'}})

else:
    db.collectionName.update({'_id':ObjectId("5aebf141a805cd28433c414c")},{'$addToSet':{'usersLike':'1'}})
keikai
  • 14,085
  • 9
  • 49
  • 68