2012-08-04 46 views
5

Tôi đang cố gắng có một db nhất quán trong đó tên người dùng và email là duy nhất.MongoDB Morphia - Độc đáo

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

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

lớp người sử dụng tôi trông như thế này:

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

tôi đã sử dụng @Indexed (unique = true) chú thích nhưng nó không hoạt động. Vẫn còn các bản sao trong db của tôi.

Bất kỳ ý tưởng nào về cách khắc phục sự cố này?

Edit:

Tôi đọc về ensureIndexes nhưng điều này có vẻ như một cách tiếp cận sai, tôi không muốn tải lên dữ liệu trùng lặp, chỉ để thấy rằng nó thực sự là một trùng lặp.

Tôi muốn chặn ngay lập tức.

somthing như

try{ 

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

Trả lời

1

Có lời giải thích tốt về hạn chế duy nhất ngay tại đây Unique constraint with JPA and Bean Validation, làm điều này giúp bạn ở tất cả? Vì vậy, những gì tôi sẽ làm là chỉ để xác nhận dữ liệu của bạn ở cấp độ điều khiển (hoặc bean validate()) khi kiểm tra các lỗi khác là tốt. Điều đó sẽ làm công việc, nhưng nó không phải là mát mẻ hơn nó sẽ được với chú thích.

Sửa

Ngoài ra xem bài đăng này Inserting data to MongoDB - no error, no insert trong đó mô tả rõ ràng MongoDB mà không gây lỗi bằng cách mặc định các chỉ số duy nhất nếu bạn không nói với nó vậy, hãy thử cấu hình MongoDB của bạn để ném những lỗi quá và xem bạn có thể làm việc trên bằng dung dịch :(

chỉnh sửa 2

Nó cũng vượt qua tâm trí của tôi mà chơi 2 có một bắt đầu lên lớp toàn cầu, nơi bạn có thể thử truy cập vào cơ sở dữ liệu của bạn và chạy các lệnh cột được lập chỉ mục của bạn như db.things.ensureIndex này ({email: 1}, {unique: true}); ?? xem thêm tại http://www.playframework.org/documentation/2.0/JavaGlobal

+1

hm, tôi không hiểu. Chắc chắn tôi có thể kiểm tra nó, nhưng nếu hai người dùng sẽ đăng ký với cùng một tên người dùng trong cùng một thời điểm thì sao? Tôi sẽ cần cái gì đó là nguyên tử. –

+0

Cơ sở dữ liệu có xây dựng riêng của họ trong các hệ thống khóa (đọc, viết khóa vv), vì vậy tôi tin rằng nếu có những hạn chế duy nhất ở cấp cơ sở dữ liệu - lưu dữ liệu trùng lặp cùng một lúc sẽ không thể? –

+0

Có lẽ tôi đã sai nhưng tôi nghĩ bạn có ý nghĩa như thế này. 'if (user.not_in_db) ds.save (người dùng);' Và nếu tôi không có ràng buộc ở cấp db thì sẽ có dữ liệu trùng lặp. –

5

Không thể tạo unique index nếu đã có bản sao trong cột bạn đang cố lập chỉ mục.

tôi sẽ cố gắng chạy ensureIndex lệnh của bạn từ mongo shell:

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

.. và cũng có thể kiểm tra xem các chỉ số được thiết lập:

db.user.getIndexes() 

nha phiến nên đã WriteConcern.SAFE thiết lập theo mặc định, mà sẽ ném một ngoại lệ khi cố gắng chèn tài liệu vi phạm một chỉ mục duy nhất.

+0

Nhờ cả hai bạn, đó là những gì tôi đang tìm kiếm. –

+0

Đây phải là câu trả lời đúng. –

0

Tôi gặp vấn đề tương tự, với khung chơi 1.2.6 và morphia 1.2.12.

Giải pháp cho chú thích @Indexed (unique = true) là để cho phép morpha tạo lại bộ sưu tập. Vì vậy, nếu tôi đã có bộ sưu tập "Tài khoản" ở mongo và chú thích cột email và bắt đầu lại ứng dụng phát, không có gì thay đổi trong chỉ mục Tài khoản.

Nếu tôi bỏ ollection tài khoản, nha phiến tái crated nó, và bây giờ cột email là duy nhất:

> db.Account.drop() 
true 

Sau khi chơi khởi động lại: (Tôi có một công việc để tạo tài khoản ban đầu ...)

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

Bây giờ, sau khi chèn bằng email hiện có, tôi nhận được một ngoại lệ MongoException.DuplicateKey.

0

Để tạo chỉ mục, phương pháp Datastore.ensureIndexes() cần phải được gọi để áp dụng các chỉ mục cho MongoDB. Phương pháp này nên được gọi sau khi bạn đã đăng ký các thực thể của bạn với Morphia. Sau đó nó sẽ đồng bộ tạo các chỉ mục của bạn. Điều này có lẽ nên được thực hiện mỗi khi bạn khởi động ứng dụng của mình.

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

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

Morphia sẽ tạo chỉ mục cho bộ sưu tập với tên lớp hoặc với giá trị chú thích @Entity.

Ví dụ, nếu tên lớp của bạn là Tác giả:

  • Hãy chắc chắn rằng bạn đã chú thích @Indexed trong bạn Entity lớp và bạn đã thực hiện hai bước sau:

    m.map(Author.class);

    ds.ensureIndexes();

  • Kiểm tra chỉ mục trên mongo db

    b.Author.getIndexes()

tôi thêm câu trả lời này, nhấn mạnh rằng bạn không thể tạo chỉ với một tên bộ sưu tập tùy chỉnh (Entity class là Tác giả, nhưng tên bộ sưu tập của bạn là khác nhau)

Kịch bản này là hiển nhiên trong nhiều trường hợp, nơi bạn muốn sử dụng lại lớp Thực thể nếu lược đồ giống nhau