Move value from a field to first index that equals null in a different field in the same document

I have a ‘characters’ collection that looks like this:

[
  {
    name: "foo",
    equipment: {
      hand: { name: "Broken Sword" }
      gloves: null,
      boots: null,
    }
    inventory: {
      { name: "some item" }, null, null, null,...
    }
  },
  ...
]

My question is how can I update this document to have equipment.hand moved to first available index of inventory (equal to null), and equipment.hand set to null afterwards?

I tried the following to update index 1, but it sets ALL inventory slots to equipment.hand item.
(I also need it to find the first available inventory slot automatically)

// unequip item
db.characters.updateOne(
  // an item is equipped in the hand slot, and there is at least one inventory space 
  { name: "foo", "equipment.hand": { $ne: null }, inventory: { $all: [null] } },
  [
    { $set: 
      {
         "inventory.1": "$equipment.hand",
         "equipment.hand": null
      } 
    }
  ]
)

That is overly complicated.

Get rid of all the nulls and just $push and $pull from inventory with $set and $unset from equipment.

It is a hard requirement that items in the inventory can be moved to any position, not just one after another.
So the inventory might look like this:
[ null, null, { name: “item 1” }, null, { name: “item 2” } ]

This hard requirement looks more like a presentation layer requirement than a data storage requirement.

If position is important, position should be a field and the same can be achieve with the following that would allows simpler code:

[
  { name : "item 1" , inventory : 2 } ,
  { name : "item 2" , inventory : 4 } ,
  { name : "Broken Sword" , equipment : "hand" }
]

And moving the Broken Sword from the hand to inventory gives:

[
  { name : "item 1" , inventory : 2 } ,
  { name : "item 2" , inventory : 4 } ,
  { name : "Broken Sword" , inventory : 1 }
]

If you limit your data storage model to what you want at the presentation layer you deprive your self of having the most efficient storage and processing.

1 Like