Pulling only one item in an array

Hello, so I basically want to only remove one item from an array in my inventory. I read that $pull would technically do the job but it will remove all other same value items in the array. Is there any other way I can approach on how to remove one item only?

Pictures for example

Thank you in advance!

Unfortunately the operator to change the first match only ā€˜$ā€™ does not let you remove an array element, if you use it with $unset you can make it null but not remove in one operation.

What you want to do can be done but needs you to use the expressive update syntax and $set the new value of inventory to new value computed using $cond and $reduce. You just stepped over the line from basic to expert mode with this one Iā€™m afraid.

db.a.drop()
db.a.insertOne({ player: 2, coins: 50, inventory: ["sword","helmet","borgor","borgor","sword"]})

    twofewercoins = {$subtract:["$coins",2]}
    onefewerborgor = { $reduce : { input: "$inventory", 
         initialValue: {stilllooking:true, i:[] } , 
         in :{ $cond  :{  if: {$and : [{$eq : ["$$this","borgor"]},"$$value.stilllooking"]} , 
                          then: {stilllooking:false, i:"$$value.i"},
                          else : { stilllooking:"$$value.stilllooking", i: {$concatArrays:["$$value.i",["$$this"]]}}}}}}


changes = [{$set : { coins: twofewercoins , inventory: onefewerborgor }},{$set: {inventory:"$inventory.i"}}]
db.a.updateOne({player:2},changes)
1 Like

I will try my best to grasp this concept. It does look pretty complex but thanks for your help!

If you look at the twofewercount you get the idea - you express the new value compared to the existing value using aggregation expressions so a simple $subtract makes sense.

with $reduce you say start with a $$value (what it will resolve to) equal to "initialValueā€™ Iterate over the array ā€œinputā€ and for each value ā€œinā€ the array make $$value equal to an expression.

The ā€œinā€ expression here says if $$this (current array item) == ā€œborgorā€ and $$value.stilllooking is true (the value we set at the start) then - set stilllooking to false (we found it) and donā€™t add $$this it to the array in $$value . otherwise add the current element to the array and keep $$value.stilllooking as it is.

Thanks! I managed to get it working on my app.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.