2012-08-04 74 views
5

我想要一個一致的數據庫,用戶名和電子郵件是唯一的。MongoDB Morphia - 唯一

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

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

我的用戶類看起來是這樣的:

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

我用@Indexed(唯一=真)註解,但是它不工作。在我的數據庫中仍然有重複。

任何想法我怎麼能解決這個問題?

編輯:

我讀到ensureIndexes但是這似乎是一個錯誤的做法,我不想上傳重複的數據,只看到其真正的副本。

我想立即封鎖它。

財產以後像

try{ 

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

回答

1

有一個關於唯一的約束很好的解釋在這裏Unique constraint with JPA and Bean Validation,這是否幫助你呢?所以我要做的只是在檢查其他錯誤時驗證控制器級別的數據(或者bean validate())。這樣做可以完成這項工作,但它不像標註那樣酷。

編輯

或者看到這個帖子Inserting data to MongoDB - no error, no insert這清楚地描述了MongoDB中通過唯一索引的默認值,如果你不告訴它,不會引發錯誤,請嘗試配置您的MongoDB拋出這些錯誤也和看看你能不能用解決方案:(

編輯2

還越過我的腦海裏打2的啓動全局類,你可以嘗試訪問數據庫,並在工作像這樣運行你的索引列命令db.things.ensureIndex({email:1},{unique:true}); ??請參閱http://www.playframework.org/documentation/2.0/JavaGlobal

+1

嗯,我不明白。當然,我可以檢查它,但如果兩個用戶在同一時間使用相同的用戶名註冊,該怎麼辦?我需要一些原子。 – 2012-08-04 22:24:22

+0

數據庫在鎖定系統(讀取,寫入鎖定等)中有其自己的構建,所以我相信如果在數據庫級別有獨特的約束 - 同時保存重複數據是不可能的? – 2012-08-04 22:26:14

+0

也許我錯了,但我認爲你的意思是這樣的。 'if(user.not_in_db)ds.save(user);'如果我在db級別沒有約束,將會有重複的數據。 – 2012-08-04 22:35:09

5

如果您嘗試索引的列中已有重複項,則無法創建A unique index

我會嘗試從mongo shell中運行你的ensureIndex命令:

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

..而且也檢查索引設置:

db.user.getIndexes() 

嗎啡應該是默認,已經設置WriteConcern.SAFE這在嘗試插入違反唯一索引的文檔時會引發異常。

+0

感謝你們倆,那就是我一直在尋找的東西。 – 2012-08-05 08:53:38

+0

這應該是正確的答案。 – 2017-02-19 14:34:23

0

我有同樣的問題,與播放框架1.2.6和嗎啡1.2.12。

@Indexed(unique = true)註釋的解決方案是,讓morpha重新創建集合。 因此,如果我已經有了mongo中的「Account」集合,並且註釋了電子郵件列,並重新啓動了Play應用程序,則帳戶索引中沒有任何更改。

如果我放棄了帳戶ollection,嗎啡重新裝箱它,現在的電子郵件柱是獨一無二的:

> db.Account.drop() 
true 

發揮重啓後:(我有工作來創建初始帳戶...)

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

現在,在插入已經存在的電子郵件之後,我得到一個MongoException.DuplicateKey異常。

0

要創建索引,需要調用Datastore.ensureIndexes()方法將索引應用於MongoDB。該方法應該在您使用Morphia註冊實體後調用。它會同步創建你的索引。這可能應該在每次啓動應用程序時完成。

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

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

Morphia將使用類名或@Entity註釋值爲集合創建索引。

例如,如果你的類名是作者:

  • 請確保您已@Indexed標註在你的實體類和你做了這兩個步驟:

    m.map(Author.class);

    ds.ensureIndexes();

  • 檢查mongo db上的索引

    b.Author.getIndexes()

我加入了這個答案,要強調的是,你不能創建一個自定義的集合名稱索引(實體類是作者,但您的收藏名稱不同)

此方案在很多情況下很明顯,如果模式相同,您想要重複使用實體類