7

我有这样的架构:

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字段是必需的且唯一的,并且必须如此。

反正有这个吗?

4

3 回答 3

6

如果您使用等效的咖啡脚本启用 Mongoose 调试日志记录,mongoose.set('debug', true);您可以看到发生了什么:

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

department因此,当您在没有任何员工的情况下创建新邮件时,您将“用尽”department.employees.email索引中未定义的电子邮件案例作为唯一性。因此,当您第二次尝试执行此操作时,该唯一值已被获取,您将获得Duplicate key error.

最好的解决方法可能是更改DepartmentSchema.employees为对员工的引用数组ObjectId而不是完整对象。然后索引保留在employees它所属的集合中,您不会复制数据并为不一致创造机会。

于 2012-09-20T12:47:23.340 回答
1

查看这些参考资料:

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

mongoDB/mongoose:如果不为空,则为唯一(特别是 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: trueEmployeeSchema 的 email 属性添加到您的索引中。

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

于 2013-03-09T13:18:48.920 回答
0

您似乎无法在子文档的单个字段上创建唯一索引。尽管db.collection.ensureIndexMongo shell 中的函数似乎允许您这样做,但它会测试整个子文档唯一性,而不是单个字段。

您可以在子文档的单个字段上创建索引,但不能使其唯一

于 2012-09-20T09:46:33.497 回答