How to change order of array with MongoDB?

2019-01-15 19:53发布

问题:

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.

回答1:

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.