2012-09-19 13 views
7

Tengo un esquema de este modo:esquema de documento Mangosta y validació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 

Así que mi employees vivo en una variedad de employee documentos dentro de un department

Tengo varios department documentos que tienen un número de employee documentos almacenados en la matriz employees.

Luego añade un nuevo department pero no contenía employees. Si luego intento agregar otro department sin employees, Mongoose produce un Duplicate key error para el campo employee.email que es un campo obligatorio. El campo employee.email es obligatorio y único, y debe serlo.

¿Hay de todos modos alrededor de esto?

Respuesta

6

Si habilita Mangosta registro de depuración con el CoffeeScript equivalente de mongoose.set('debug', true); se puede ver lo que está pasando:

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 } 

Al incorporar la plena EmployeeSchema en el employees gama de DepartmentSchema (en lugar de sólo una referencia ObjectId a ella), terminas creando índices únicos tanto en employees.email como en department.employees.email.

Por lo tanto, cuando crea un nuevo department sin ningún empleado, está "agotando" el caso indefinido de correo electrónico en el índice department.employees.email en cuanto a exclusividad. Entonces, cuando tratas de hacer eso por segunda vez, ese valor único ya está tomado y obtienes el Duplicate key error.

La mejor solución para esto es probablemente para cambiar DepartmentSchema.employees a una matriz de ObjectId referencias a empleados en lugar de objetos completos. Luego, el índice permanece en la colección employees donde pertenece y no está duplicando datos y creando oportunidades para inconsistencias.

+0

Gracias Johhny, no tenía conocimiento del comando _debug_, que es útil saber para la depuración futura. Tampoco era consciente de que Mongoose estaba creando 2 índices (realmente cuando solo pedí uno). Sabía que podía crear 2 colecciones diferentes y tener una _refer_ con la otra por medio de 'ObjectId', pero luego volví a un modelo relacional. Después de haber usado RDMS durante muchos años, quería utilizar una estructura incrustada que parece ser una buena opción para este modelo. Como solución de compromiso, supongo que podría referirme a una colección _email-address_ dentro del objeto empleado incrustado y crear un índice único que. –

0

Parece que no puede crear un índice único en un campo individual de un subdocumento. Aunque la función db.collection.ensureIndex en el shell Mongo parece permitirte hacer eso, prueba el subdocumento como un todo por su singularidad y no por el campo individual.

Puede crear un índice en un campo individual de un subdocumento, simplemente no puede hacerlo único.

+2

Se puede crear un índice único en un campo sub-documento, pero la singularidad es forzada a través de toda la colección y 'sin valor' es considerado uno de los valores únicos. Ver mi respuesta – JohnnyHK

1

Salida estas referencias:

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

mongoDB/mongoose: unique if not null (específicamente la respuesta de JohnnyHK)

El corto de él es que desde Mongo 1.8, puede definir lo que se llama un índice sparse, que sólo inicia el control único si el valor no es nulo.

En su caso, usted podría desear:

@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 } 

Aviso del sparse: true añadido a su índice en el atributo de correo electrónico de EmployeeSchema.

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

Cuestiones relacionadas