2012-08-04 13 views
5

Estoy tratando de tener un db consistente donde el nombre de usuario y el correo electrónico sean únicos.MongoDB Morphia - Unique

http://www.mongodb.org/display/DOCS/Indexes#Indexes-unique%3Atrue

http://code.google.com/p/morphia/wiki/EntityAnnotation

Mi clase de usuario tiene el siguiente aspecto:

public class User { 
    @Indexed(unique = true) 
    @Required 
    @MinLength(4) 
    public String username; 

    @Indexed(unique = true) 
    @Required 
    @Email 
    public String email; 

    @Required 
    @MinLength(6) 
    public String password; 

    @Valid 
    public Profile profile; 

    public User() { 
... 

he utilizado la @Indexed (singular = true) anotación pero no funciona. Todavía hay duplicados en mi db.

¿Alguna idea de cómo puedo solucionar esto?

Editar:

He leído sobre ensureIndexes pero esto parece un enfoque equivocado, no quiero cargar datos duplicados, sólo para ver que es realmente un duplicado.

Quiero bloquearlo de inmediato.

algo como

try{ 

ds.save(user); 
} 
catch(UniqueException e){ 
... 
} 

Respuesta

1

Hay una buena explicación acerca de restricción única aquí Unique constraint with JPA and Bean Validation, esto le ayuda en absoluto? Entonces, lo que haría es solo validar sus datos a nivel de controlador (o bean validate()) al verificar otros errores también. Eso hará el trabajo, pero no es tan genial como sería con la anotación.

Editar

Alternativamente ver este post Inserting data to MongoDB - no error, no insert que describe claramente que mongodb no plantea de error por defecto de los índices únicos si usted no dice que es así, trate de configurar el mongodb a poner a estos errores también y ver si se puede trabajar en la solución :(

Editar 2

también pasó por la cabeza que juegan 2 tiene una puesta en marcha de clase mundial donde se puede tratar de acceder a su base de datos y ejecute los comandos de columna indexada como este db.things.ensureIndex ({email: 1}, {unique: true}); ?? ver más en http://www.playframework.org/documentation/2.0/JavaGlobal

+1

hm, no lo entiendo. Claro que puedo verificarlo, pero ¿qué ocurre si dos usuarios se registran con el mismo nombre de usuario al mismo tiempo? Necesitaría algo que sea atómico. –

+0

Las bases de datos tienen su propia compilación en sistemas de bloqueo (cerraduras de lectura, escritura, etc.), por lo que creo que si existen restricciones únicas a nivel de base de datos, ¿no sería posible guardar datos duplicados al mismo tiempo? –

+0

Quizás estoy equivocado, pero pensé que querías decir algo como esto. 'if (user.not_in_db) ds.save (user);' Y si no tengo ninguna restricción en el nivel db, habrá datos duplicados. –

5

No se puede crear un unique index si ya hay duplicados en la columna que está tratando de indexar.

me gustaría probar el funcionamiento de su ensureIndex comandos de la shell mongo:

db.user.ensureIndex({'username':1},{unique:true}) 
db.user.ensureIndex({'email':1},{unique:true}) 

.. y también comprobar que los índices se establecen:

db.user.getIndexes() 

Morphia deberían haber WriteConcern.SAFE establecido por defecto, lo que lanzará una excepción cuando intente insertar documentos que violarían un índice único.

+0

Gracias a ustedes dos, eso es lo que estaba buscando. –

+0

Esta debería ser la respuesta correcta. –

0

Tuve el mismo problema, con play framework 1.2.6 y morphia 1.2.12.

La solución para la anotación @Indexed (unique = true) es para permitir que morpha vuelva a crear la colección. Entonces, si ya tenía la colección "Cuenta" en mongo, anoté la columna de correo electrónico y reinicié la aplicación de reproducción, nada cambió en los índices de la cuenta.

Si se me cayó el olecci cuenta, morfina re embalados, y ahora la columna de correo electrónico es único:

> db.Account.drop() 
true 

Después de reanudar el juego: (Tengo un trabajo para crear cuentas iniciales ...)

> db.Account.getIndexes() 
[ 
     { 
       "v" : 1, 
       "key" : { 
         "_id" : 1 
       }, 
       "ns" : "something.Account", 
       "name" : "_id_" 
     }, 
     { 
       "v" : 1, 
       "key" : { 
         "email" : 1 
       }, 
       "unique" : true, 
       "ns" : "something.Account", 
       "name" : "email_1" 
     } 
] 

Ahora, después de una inserción con un correo electrónico ya existente, recibo una excepción de MongoException.DuplicateKey.

0

Para crear índices, se debe llamar al método Datastore.ensureIndexes() para aplicar los índices a MongoDB. El método debe ser llamado después de que haya registrado sus entidades con Morphia. A continuación, creará de forma sincrónica tus índices. Esto probablemente debería hacerse cada vez que inicie su aplicación.

Morphia m = ... 
Datastore ds = ... 

m.map(Product.class); 
ds.ensureIndexes(); //creates all defined with @Indexed 
0

Morphia creará índices para la colección con el nombre de clase o con el valor de anotación @Entity.

Por ejemplo, si su nombre de la clase es Autor:

  • Por favor asegúrese de que haya anotación @Indexed en que la clase de entidad y que han hecho estos dos pasos:

    m.map(Author.class);

    ds.ensureIndexes();

  • Ver índices en mongo db

    b.Author.getIndexes()

Estoy añadiendo esta respuesta, al hacer hincapié en que no se puede crear índices con un nombre de colección personalizada (clase de entidad es autor, pero el nombre de la colección es diferente)

Este escenario es obvio en muchos casos, donde quiere reutilizar la clase Entity si el esquema es el mismo

Cuestiones relacionadas