En mongoDb, ¿cómo se elimina un elemento de matriz por su índice

{ "_id" : ObjectId("4d1cb5de451600000000497a"), "name" : "dannie", "interests" : [ "guitar", "programming", "gadgets", "reading" ] } 

En el ejemplo anterior, suponga que el documento anterior se encuentra en la colección db.people . ¿Cómo eliminar el tercer elemento de la matriz de intereses por su índice ?

Editar:

Esta es mi solución actual:

 var interests = db.people.findOne({"name":"dannie"}).interests; interests.splice(2,1) db.people.update({"name":"dannie"}, {"$set" : {"interests" : interests}}); 

¿Hay una manera más directa?

No hay una forma directa de tirar / eliminar por índice de matriz. De hecho, este es un tema abierto http://jira.mongodb.org/browse/SERVER-1014 , puede votar por él.

La solución alternativa es usar $ unset y luego $ pull:

 db.lists.update({}, {$unset : {"interests.3" : 1 }}) db.lists.update({}, {$pull : {"interests" : null}}) 

Actualización: como se menciona en algunos de los comentarios, este enfoque no es atómico y puede causar algunas condiciones de carrera si otros clientes leen y / o escriben entre las dos operaciones. Si necesitamos que la operación sea atómica, podríamos:

  • Lee el documento de la base de datos
  • Actualice el documento y elimine el elemento en la matriz
  • Reemplace el documento en la base de datos. Para garantizar que el documento no ha cambiado desde que lo leímos, podemos usar la actualización si el patrón actual se describe en los documentos de mongo

Puede usar el modificador $pull de la operación de update para eliminar un elemento particular de una matriz. En caso de que haya proporcionado una consulta se verá así:

 db.people.update({"name":"dannie"}, {'$pull': {"interests": "guitar"}}) 

Además, puede considerar usar $pullAll para eliminar todas las ocurrencias. Más sobre esto en la página de documentación oficial – http://www.mongodb.org/display/DOCS/Updating#Updating-%24pull

Esto no usa el índice como criterio para eliminar un elemento, pero podría ayudar en casos similares a los tuyos. IMO, usar índices para direccionar elementos dentro de una matriz no es muy confiable ya que mongodb no es consistente en el orden de elementos tan rápido como yo sé.

Yo recomendaría usar un campo GUID (tiendo a usar Object ID) o un campo de incremento automático para cada subdocumento en la matriz.

Con este GUID, es fácil emitir un $ pull y asegurarse de extraer el correcto. Lo mismo ocurre con otras operaciones de matriz.

En lugar de usar el desarmado (como en la respuesta aceptada), resuelvo esto estableciendo el campo en un valor único (es decir, no NULO) y luego tirando de ese valor inmediatamente. Un poco más seguro desde una perspectiva asincrónica. Aquí está el código:

  var update = {}; var key = "ToBePulled_"+ new Date().toString(); update['feedback.'+index] = key; Venues.update(venueId, {$set: update}); return Venues.update(venueId, {$pull: {feedback: key}}); 

Esperemos que mongo aborde esto, tal vez extendiendo el modificador $ position para soportar $ pull y $ push.

En lugar de usar $ pull, podemos usar $ pop para eliminar elementos en una matriz por su índice. Pero debe restar 1 de la posición del índice para eliminar según el índice.

Por ejemplo, si desea eliminar el elemento en el índice 0, debe usar -1, para el índice 1 debe usar 0 y así sucesivamente …

Consulta para eliminar el 3er elemento (gadgets):

db.people.update({"name":"dannie"}, {'$pop': {"interests": 1}})

para referencia: https://docs.mongodb.com/manual/reference/operator/update/pop/