2012-09-19 32 views
7

I Have a schema như vậy:schema tài liệu Mongoose và xác nhận

class Schemas 

    constructor: -> 
    @mongoose = require 'mongoose' 
    @schema = @mongoose.Schema 

    @EmployeeSchema = new @schema 
     'firstname': { type: String, required: true }, 
     'lastname': { type: String, required: true }, 
     'email': { type: String, required: true, index: { unique: true }, validate: /\b[a-zA-Z0-9._%+-][email protected][a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}\b/ }, 
     'departmentId': { type: @schema.ObjectId, required: true } 
     'enddate': String, 
     'active': { type: Boolean, default: true } 

    @EmployeeSchemaModel = @mongoose.model 'employees', @EmployeeSchema 

    @DepartmentSchema = new @schema 
     'name': { type: String, required: true, index: { unique: true } } 
     'employees' : [ @EmployeeSchema ] 

    @DepartmentSchemaModel = @mongoose.model 'departments', @DepartmentSchema 

Vì vậy mà tôi employees sống trong một mảng của employee tài liệu bên trong một department

Tôi có một vài department tài liệu có một số employee tài liệu được lưu trữ trong mảng employees.

Sau đó, tôi đã thêm department mới nhưng không chứa employees. Nếu sau đó tôi cố thêm một số khác department mà không cần employees, Mongoose sẽ tạo ra một trường hợp Duplicate key error cho trường employee.email là trường bắt buộc. Trường employee.email là bắt buộc và duy nhất và cần phải có.

Dù sao có làm tròn cái này?

Trả lời

6

Nếu bạn kích hoạt Mongoose debug logging với tương đương coffeescript của mongoose.set('debug', true); bạn có thể xem những gì đang xảy ra:

DEBUG: Mongoose: employees.ensureIndex({ email: 1 }) { safe: true, background: true, unique: true }  
DEBUG: Mongoose: departments.ensureIndex({ name: 1 }) { safe: true, background: true, unique: true }  
DEBUG: Mongoose: departments.ensureIndex({ 'employees.email': 1 }) { safe: true, background: true, unique: true } 

Bằng cách nhúng toàn bộ EmployeeSchema trong employees mảng của DepartmentSchema (chứ không phải chỉ là một ObjectId tham chiếu đến nó), bạn sẽ tạo các chỉ mục duy nhất trên cả hai employees.emaildepartment.employees.email.

Vì vậy, khi bạn tạo một department mới mà không có bất kỳ nhân viên nào, bạn 'đang sử dụng' trường hợp email chưa được xác định trong chỉ mục department.employees.email càng độc đáo. Vì vậy, khi bạn thử và làm điều đó lần thứ hai, giá trị duy nhất đã được sử dụng và bạn nhận được Duplicate key error.

Khắc phục tốt nhất cho việc này có thể thay đổi DepartmentSchema.employees thành một mảng tham chiếu ObjectId cho nhân viên thay vì đối tượng đầy đủ. Sau đó, chỉ mục nằm trong bộ sưu tập employees nơi nó thuộc về và bạn không sao chép dữ liệu và tạo cơ hội cho sự không thống nhất.

+0

Cảm ơn Johhny, tôi đã không nhận thức được lệnh _debug_, đó là tiện dụng để biết để gỡ lỗi trong tương lai. Tôi cũng không biết rằng Mongoose đã tạo ra 2 chỉ mục (thực sự khi tôi chỉ yêu cầu một chỉ mục.) Tôi biết tôi có thể tạo 2 bộ sưu tập khác nhau và có một bộ sưu tập _refer_ bằng một 'ObjectId', nhưng sau đó tôi quay lại một mô hình quan hệ. Đã sử dụng RDMS trong nhiều năm, tôi muốn sử dụng một cấu trúc nhúng có vẻ phù hợp với mô hình này. Như một sự thỏa hiệp, tôi cho rằng tôi có thể tham khảo một bộ sưu tập _email-address_ từ bên trong đối tượng nhân viên được nhúng và tạo một chỉ mục duy nhất. –

0

Dường như bạn không thể tạo một chỉ mục duy nhất trên một trường riêng lẻ của một tài liệu phụ. Mặc dù hàm db.collection.ensureIndex trong vỏ Mongo xuất hiện để cho phép bạn làm điều đó, nó kiểm tra tài liệu phụ như một toàn bộ cho tính duy nhất của nó và không phải là trường riêng lẻ.

Bạn có thể tạo chỉ mục trên một trường riêng lẻ của một tài liệu phụ, bạn chỉ không thể làm cho nó unique.

+2

Bạn có thể tạo một chỉ số duy nhất trên một lĩnh vực phụ tài liệu, nhưng sự độc đáo được thi hành trên toàn bộ bộ sưu tập và 'không có giá trị' được coi là một trong những giá trị độc đáo. Xem câu trả lời của tôi. – JohnnyHK

1

Kiểm tra các tài liệu tham khảo:

http://docs.mongodb.org/manual/core/indexes/#sparse-indexes

mongoDB/mongoose: unique if not null (đặc biệt câu trả lời JohnnyHK của)

Các ngắn của nó là vì Mongo 1.8, bạn có thể xác định những gì được gọi là chỉ số sparse, mà chỉ đá trong kiểm tra duy nhất nếu giá trị không phải là null.

Trong trường hợp của bạn, bạn sẽ muốn:

@EmployeeSchema = new @schema 
    'firstname': { type: String, required: true }, 
    'lastname': { type: String, required: true }, 
    'email': { type: String, required: true, index: { unique: true, sparse: true }, validate: /\b[a-zA-Z0-9._%+-][email protected][a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}\b/ }, 
    'departmentId': { type: @schema.ObjectId, required: true } 
    'enddate': String, 
    'active': { type: Boolean, default: true } 

Thông báo các sparse: true thêm vào chỉ mục của bạn trên thuộc tính email EmployeeSchema của.

https://gist.github.com/juanpaco/5124144

Các vấn đề liên quan