Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change order of array with MongoDB?

I need to be able to increment and decrement the position of an element of an array in a MongoDB object.

I looked at the <update> API in the MongoDB API but could not find anything to let me do so.

I am trying to use findOneAndUpdate through Mongoose and I know the index of the element I am trying to shift up or down.

An example of the array item of base64 encoded images:

{ 
  images: [
    "img1",
    "img2",
    "img3"
  ]
}

And I would like to move, for example "img2", up or down (but "image" should not be able to pushed up since there is nowhere to go).

If I wanted to push "img2" up then the result would be:

{ 
  images: [
    "img2",
    "img1",
    "img3"
  ]
}

It doesn't matter if I achieve this through changing the index, swapping, or pushing up/down.

like image 540
Adam Thompson Avatar asked Mar 05 '16 06:03

Adam Thompson


People also ask

Is MongoDB array ordered?

yep MongoDB keeps the order of the array.. just like Javascript engines..

How do I sort an array field in MongoDB aggregate?

To sort the whole array by value, or to sort by array elements that are not documents, identify the input array and specify 1 for an ascending sort or -1 for descending sort in the sortBy parameter.

How do I edit an array in MongoDB?

Learn how to update array fields in documents in MongoDB collections. You can use the updateOne() or updateMany() methods to add, update, or remove array elements based on the specified criteria. It is recommended to use the updateMany() method to update multiple arrays in a collection.


1 Answers

Like @blakes-seven said, you have two ways to do it:

Grabing, updating and pushing

db.images.find({ _id: '' }, { images : 1 })
.then(function(img) {
  var tmpImg = img.images[0];
  img.images[0] = img.images[1];
  img.images[1] = tmpImg;

  db.images.update({ _id: img._id }, { $set: { images: img.images } });
})

Updating directly (if you have the image on the client and know the indexes), using $position

db.images.update({ _id: '' }, { $push: { images: { $each: ['img2'] }, $position: 0 } } } )
.then(function() {
  db.images.update({ _id: '' }, {$unset: {'images.2': 1}})
});

https://docs.mongodb.org/manual/reference/operator/update/position/

However, I think you should redesign the way you stores your images, using by example a virtual ordering:

{
  images: [
    { base64: 'img1', order: 0, _id: 'img1' },
    { base64: 'img2', order: 1, _id: 'img2' },
    { base64: 'img3', order: 2, _id: 'img3' }
  ]
}

This way, you could order your images using a virtual order index, updating them using only the _id, or updating the whole collection by changing order of all img2, dropping or replacing an image, etc.

like image 58
Jonathan Muller Avatar answered Sep 18 '22 23:09

Jonathan Muller