2012-04-30 8 views
17

En mi escenerio, hay autores en una colección, cada autor tiene messages y cada mensaje de autor puede tener events. Cada actor permitió realizar solo un tipo de acción una vez.Cómo garantizar un elemento único en una matriz basada en campos específicos - mongoDB?

db.people.ensureIndex({messages.messageEvents.eventName: 1, messages.messageEvents.actorId: 1}, {unique: true}); 

He añadido el índice pero no tiene ningún efecto. Como puede ver a continuación, mi documento tiene tres elementos que tienen "eventName":"vote" y "actorId":"1234" que deberían estar en contra de mi restricción.

Cómo asegurar un elemento único en messageEvents matriz basada en eventName y actorId campos?

En realidad, necesito actualizar el elemento existente sin un segundo evento de búsqueda y actualización en lugar de rechazarlo.

{ 
    "_id": "1234567", 
    "authorPoint": 0, 
    "messages": [ 
    { 
     "messageId": "112", 
     "messageType": "Q", 
     "messagePoint": 0, 
     "messageEvents": [ 
     { 
      "eventName": "Add", 
      "actorId": "1234", 
      "detail": "" 
     }, 
     { 
      "eventName": "Vote", 
      "actorId": "1234", 
      "detail": "up" 
     }, 
     { 
      "eventName": "Vote", 
      "actorId": "1234", 
      "detail": "down" 
     }, 
     { 
      "eventName": "Vote", 
      "actorId": "1234", 
      "detail": "cork" 
     } 
     ] 
    } 
    ] 
} 

Respuesta

19

Mustafa, restricciones únicas no se aplican en una sola agrupación, a pesar de que están aplicadas entre los documentos en una colección. Esto es un error conocido que no se fija por un tiempo:

https://jira.mongodb.org/browse/SERVER-1068

Hay una solución, sin embargo. Mantenga su índice único en su lugar, y:

1) Asegúrese de que su aplicación no inserte documentos nuevos con valores duplicados en la matriz. Puede verificar la exclusividad en el código de su aplicación antes de insertarla.

2) Al actualizar documentos existentes, use $ addToSet en lugar de $ push.

+0

Gracias por su respuesta. Tienes razón. Ya he cambiado la representación de mi documento y la solución aplicada después de algunas investigaciones. Ojalá hubiera una manera fácil. Ha costado y puede causar complejidad de código :( – yuceel

+1

Incluso con $ addToSet, digamos que teníamos algo insertado como {userId: 1234, vote: obama}, $ addToSet no pararía {userId: 1234, vote: romney }, ¿cómo se aseguraría de que el conjunto de objetos imponga la exclusividad solo en userId? –

+0

@OuwenHuang Creo que esa es una pregunta aparte, la pediría por separado en lugar de comentar esta respuesta aceptada. –

Cuestiones relacionadas