2012-08-04 10 views
5

Sto cercando di avere un db coerente in cui il nome utente e l'email sono unici.MongoDB Morphia - Unique

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

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

mia classe utente si presenta così:

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() { 
... 

ho usato il @Indexed (unica = true) di annotazione, ma non funziona. Ci sono ancora duplicati nel mio db.

Qualche idea su come posso risolvere questo problema?

Edit:

ho letto di ensureIndexes ma questo mi sembra un approccio sbagliato, io non voglio caricare i dati duplicati, solo per vedere che la sua davvero un duplicato.

Voglio bloccarlo subito.

somthing come

try{ 

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

risposta

1

V'è una buona spiegazione sul vincolo univoco proprio qui Unique constraint with JPA and Bean Validation, fa questo aiuto a tutti? Quindi quello che farei è solo per convalidare i dati a livello di controller (o bean validate()) quando si controllano anche altri errori. Questo farà il lavoro, ma non è così bello come sarebbe con l'annotazione.

Modifica

alternativa vedere questo post Inserting data to MongoDB - no error, no insert che descrive chiaramente che MongoDB non solleva errore per difetto di indici univoci, se non dite così, provare a configurare il vostro MongoDB di gettare quegli errori troppo e vedere se è possibile lavorare su con la soluzione :(

Edit 2

e 'anche attraversato la mia mente che giocano 2 ha una start up di classe mondiale in cui si potrebbe tentare di accedere al database e esegui i comandi di colonna indicizzati come questo db.things.ensureIndex ({email: 1}, {unique: true}); ?? vedere di più su http://www.playframework.org/documentation/2.0/JavaGlobal

+1

hm, non capisco. Certo, posso verificarlo, ma cosa succederebbe se due utenti si registrassero con lo stesso nome utente nello stesso tempo? Avrei bisogno di qualcosa che sia atomico. –

+0

I database hanno una propria build nei sistemi di blocco (leggere, scrivere blocchi ecc.), Quindi credo che se ci sono vincoli unici a livello di database, non sarebbe possibile salvare contemporaneamente i dati duplicati? –

+0

Forse mi sbaglio, ma pensavo che intendessi qualcosa del genere. 'if (user.not_in_db) ds.save (utente);' E se non ho alcun vincolo a livello di db, ci saranno dati duplicati. –

5

Non è possibile creare un unique index se nella colonna che si sta tentando di indicizzare sono già presenti duplicati.

vorrei provare a eseguire i comandi ensureIndex dal mongo shell:

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

.. e controllare anche che gli indici siano impostati:

db.user.getIndexes() 

Morphia avrebbero dovuto WriteConcern.SAFE impostata di default, che genererà un'eccezione quando si tenta di inserire documenti che violerebbero un indice univoco.

+0

Grazie a tutti e due, questo è quello che stavo cercando. –

+0

Questa dovrebbe essere la risposta corretta. –

0

Ho avuto lo stesso problema, con il framework di gioco 1.2.6 e morphia 1.2.12.

La soluzione per l'annotazione @Indexed (unique = true) è per consentire a morpha di ricreare la raccolta. Quindi, se ho già avuto la raccolta "Account" in mongo e ho annotato la colonna email, e ho riavviato l'app di gioco, nulla è cambiato negli indici dell'account.

Se ho lasciato cadere l'ollezione account, morfina re ingabbiati, e ora la colonna email è unico:

> db.Account.drop() 
true 

Dopo il riavvio del gioco: (Ho un lavoro per creare account iniziali ...)

> 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" 
     } 
] 

Ora, dopo un inserto con un'e-mail già esistente, ottengo un'eccezione MongoException.DuplicateKey.

0

Per creare indici, è necessario chiamare il metodo Datastore.ensureIndexes() per applicare gli indici a MongoDB. Il metodo dovrebbe essere chiamato dopo aver registrato le tue entità con Morphia. Creerà quindi in modo sincrono i tuoi indici. Questo dovrebbe essere fatto ogni volta che avvii la tua applicazione.

0

Morphia creerà gli indici per la raccolta con il nome della classe o con il valore di annotazione @Entity.

Ad esempio se il vostro nome della classe è Autore:

  • Assicurati di annotazione che avete in voi @Indexed classe di entità e di aver fatto questi due passaggi:

    m.map(Author.class);

    ds.ensureIndexes();

  • Verifica indici su mongo db

    b.Author.getIndexes()

sto aggiungendo questa risposta, per sottolineare che non è possibile creare indici con un nome di raccolta personalizzato (classe Entity è autore, ma il tuo nome collezione è diverso)

questo scenario è ovvio in molti casi, in cui si desidera riutilizzare la classe Entity se lo schema è lo stesso

Problemi correlati