Home > Mobile >  Set and pop update in mongodb
Set and pop update in mongodb

Time:11-29

I have db sample as:

db={
  "sample": [
    {
      current_book: "Aurthor",
      upcomming_book: [
        "Sigma",
        "Rocky"
      ]
    }
  ]
}

I want to set current_book value to first element of upcomming_book and pop the first element out of upcomming_book.

Expected O/P:

[
  {
    "current_book": "Sigma",
    "upcomming_book": [
      "Rocky"
    ]
  }
]

For this I tried as:

db.sample.update({
  "upcomming_book.0": {
    $exists: true
  }
},
{
  "$set": {
    current_book: {
      $arrayElemAt: [
        "$upcomming_book",
        0
      ]
    }
  },
  "$pop": {
    "upcomming_book": -1
  }
})

But it sets the value of current_book to the query provided and pops the value out of upcomming_book.

O/P:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "current_book": {
      "$arrayElemAt": [
        "$upcomming_book",
        0
      ]
    },
    "upcomming_book": [
      "Rocky"
    ]
  }
]

Also I tried aggregation pipeline:

db.sample.update({
  "upcomming_book.0": {
    $exists: true
  }
},
[
  {
    $set: {
      current_book: {
        $arrayElemAt: [
          "$upcomming_book",
          0
        ]
      }
    }
  },
  {
    "$pop": {
      "upcomming_book": -1
    }
  }
])

But this throws the error as:

fail to run update: (Location40324) Unrecognized pipeline stage name: '$pop'.

https://mongoplayground.net/p/1j8DTlOHDV3

CodePudding user response:

Is this what you are looking for?

[
  {
    "$set": {
      current_book: {
        $arrayElemAt: [
          "$upcomming_book",
          0
        ]
      },
      "upcomming_book": {
        $slice: [
          "$upcomming_book",
          -1
        ]
      }
    }
  }
]

Playground example here yields:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "current_book": "Sigma",
    "upcomming_book": [
      "Rocky"
    ]
  }
]

A more complete (dynamic size) solution would be:

[
  {
    "$set": {
      current_book: {
        $arrayElemAt: [
          "$upcomming_book",
          0
        ]
      },
      "upcomming_book": {
        $slice: [
          "$upcomming_book",
          {
            $subtract: [
              1,
              {
                $size: "$upcomming_book"
              }
            ]
          }
        ]
      }
    }
  }
]

Playground example here.

Part of your problem (Unrecognized pipeline stage name: '$pop') I explain here.

  • Related