2012-02-22 9 views
6

Supongamos que se trata de un documento que representa a un cliente.mongodb indización de campos incrustados (notación de puntos)

{ 
    company_name: 'corporate ltd.', 
    pocs: [ 
     {name: 'Paul', email: '[email protected]'}, 
     {name: 'Jessica', email: '[email protected]'} 
    ] 
} 

yo quería definir un índice único para pocs.email Así que emitió el siguiente comando:

db.things.ensureIndex({"pocs.email": 1}, {unique: true}) 

Lo extraño es que cuando se trata de añadir otra compañía con un poc tener un correo electrónico ya existe en otra empresa, mongo lo rechaza, respetando la restricción de índice única.

que es, lo siguiente no puede existe:

{ 
    company_name: 'corporate ltd.', 
    pocs: [ 
     {name: 'Paul', email: '[email protected]'}, 
     {name: 'Jessica', email: '[email protected]'} 
    ] 
}, 
{ 
    company_name: 'contoso llc', 
    pocs: [ 
     {name: 'Paul', email: '[email protected]'}, 
    ] 
} 

Lo cual está bien. Sin embargo, es posible tener duplicado de poc dentro del mismo documento, p.

{ 
    company_name: 'corporate ltd.', 
    pocs: [ 
     {name: 'Paul', email: '[email protected]'}, 
     {name: 'Paul', email: '[email protected]'}, 
     {name: 'Jessica', email: '[email protected]'} 
    ] 
}, 

ver los comandos CLI mi siguiente secuencia:

> version() 
version: 2.0.2 
> 
> use test 
switched to db test 
> db.test.ensureIndex({"poc.email": 1}, {unique: true}) 
> 
> db.test.insert({company: "contoso", poc: [{email: '[email protected]'}]}) 
> db.test.insert({company: "contoso", poc: [{email: '[email protected]'}]}) 
E11000 duplicate key error index: test.test.$poc.email_1 dup key: { : "[email protected]" } 
> ({company: "contoso", poc: [{email: '[email protected]'}, {email: '[email protected]'}]}) 
> 
> 
> db.test.find() 
{ "_id" : ObjectId("4f44949685926af0ecf9295d"), "company" : "contoso", "poc" : [ { "email" : "[email protected]" } ] } 
{ "_id" : ObjectId("4f4494b885926af0ecf9295f"), "company" : "contoso", "poc" : [ { "email" : "[email protected]" }, { "email" : "[email protected]" } ] } 

Por otra parte, esto sucede ya sea en insert o al update.

> db.test.update({"_id" : ObjectId("4f44949685926af0ecf9295d")}, {$push: { poc: {email: '[email protected]'}}}) 
> db.test.find() 
{ "_id" : ObjectId("4f4494b885926af0ecf9295f"), "company" : "contoso", "poc" : [ { "email" : "[email protected]" }, { "email" : "[email protected]" } ] } 
{ "_id" : ObjectId("4f44949685926af0ecf9295d"), "company" : "contoso", "poc" : [  {  "email" : "[email protected]" }, {  "email" : "[email protected]" }, {  "email" : "[email protected]" } ] } 
> 

¿Es esto un error o una por diseño-función echaba de menos manchas en la documentación?

Respuesta

7

Hay un problema abierto con respecto al mismo problema unique indexes not enforced within array of single document. Puedes votar por eso

También hay una bonita solución sugerida por Kyle banquero en este puesto similar Unique indexes on embedded documents

actualización

Esto no sólo está relacionada con los campos incrustados, podemos reproducir el mismo para los campos de matriz también.

>db.uniqqueTest.insert({a:[1],x:1}) 
>db.uniqqueTest.createIndex({a:1}, {unique: true}) 
> db.uniqqueTest.find() 
{ "_id" : ObjectId("4f44c6252434860b44986b02"), "a" : [ 1 ],"x":1 } 

y se emite un error si se intenta crear un nuevo documento con el mismo valor (comportamiento correcto)

> db.uniqqueTest.insert({a:[1],x:3}) 
E11000 duplicate key error index: stack.uniqqueTest.$a_1 dup key: { : 1.0 } 

Pero esto funciona bien si ponemos el mismo valor dentro de la gama (sin errores, en silencio acepta el valor duplicado dentro de la matriz)

> db.uniqqueTest.insert({a:[2],x:2}) 
> db.uniqqueTest.update({x:2},{$push:{a:2}}) 
{ "_id" : ObjectId("4f44c65f2434860b44986b05"), "a" : [ 2, 2 ], "x" : 2 } 

pero no para este

> db.uniqqueTest.update({x:2},{$push:{a:1}]) 
E11000 duplicate key error index: stack.uniqqueTest.$a_1 dup key: { : 1.0 } 
+2

+1. Se lo considera un error, pero bastante raro. "Los índices únicos están diseñados para hacer cumplir solo 1 documento tiene esa clave. Técnicamente, eso es cierto para este caso, pero en la forma en que la mayoría de la gente usa la característica, quieren incluir los subdos únicos". Me pregunto si pueden arreglarlo, porque es un cambio semántico muy grande que podría morder a algunas personas. – Thilo

+0

@Thilo, estoy totalmente de acuerdo contigo. Va a ser un gran cambio si lo aceptan y contradicen totalmente la naturaleza de lo que se supone que son los índices únicos. La mayoría de la gente entendió mal el concepto de documento integrado/secundario como un documento real. Ese es el verdadero problema.Pero 'el doc incrustado es solo otro campo (con propiedades anidadas) y solo tiene las mismas características que los campos normales'. Si ellos entienden esto, estas preguntas no ocurrirán. – RameshVel

+0

@RameshVel quizás sea una cuestión de punto de vista en lugar de conceptos [erróneos]. ver, en caso de que la matriz anidada tenga N elementos, ahora hay N entradas en la tabla de índice, una por artículo. a diferencia de "la naturaleza del índice único" que crea una sola entrada por definición de índice por registro. Más que eso, si vamos a sacar los documentos secundarios y colocarlos en una colección separada, entonces volvemos al infierno que conocemos de los RDBMS clásicos. –

Cuestiones relacionadas