我有一个这样的架构:
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._%+-]+@[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
我的employees
位于employee
department
个文档数组中
我有几个department
个文档,其中employee
个数组中存储了多个employees
个文档。
然后我添加了新的department
,但它不包含employees
。如果我在没有department
的情况下尝试添加其他employees
,则Mongoose会为Duplicate key error
字段生成employee.email
,这是必填字段。 employee.email
字段是必需且唯一的,它必须是。
无论如何围绕这个?
答案 0 :(得分:6)
如果使用相当于mongoose.set('debug', true);
的coffeescript启用Mongoose调试日志记录,您可以看到发生了什么:
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 }
通过在EmployeeSchema
employees
数组DepartmentSchema
中嵌入完整的ObjectId
(而不仅仅是employees.email
对它的引用),最终会在department.employees.email
上创建唯一索引{1}}和department
。
因此,当您创建一个没有任何员工的新department.employees.email
时,您正在“使用”Duplicate key error
索引中未定义的电子邮件案例,这是唯一性。因此,当您尝试第二次执行此特定值时,您将获得DepartmentSchema.employees
。
最好的解决方法可能是将ObjectId
更改为employees
对员工的引用数组,而不是完整对象。然后索引保留在它所属的{{1}}集合中,并且您不会复制数据并创建不一致的机会。
答案 1 :(得分:1)
查看以下参考资料:
http://docs.mongodb.org/manual/core/indexes/#sparse-indexes
mongoDB/mongoose: unique if not null(特别是JohnnyHK的回答)
缺点是,自Mongo 1.8以来,您可以定义所谓的sparse
索引,只有在值不为空时才会在唯一检查中启动。
在您的情况下,您需要:
@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._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}\b/ },
'departmentId': { type: @schema.ObjectId, required: true }
'enddate': String,
'active': { type: Boolean, default: true }
请注意,sparse: true
已在EmployeeSchema的电子邮件属性中添加到您的索引中。
答案 2 :(得分:0)
您似乎无法在子文档的单个字段上创建唯一索引。虽然Mongo shell中的db.collection.ensureIndex
函数似乎允许您这样做,但它会测试子文档作为一个整体的唯一性,而不是单个字段。
您可以在子文档的单个字段上创建索引,但不能将其设置为唯一。