使用空的子文档集合保存Mongoose文档会导致重复的键错误

我有两个mongoose模式:

var productSchema = new Schema({ name: { type: String, required: true, unique: true }, ... }); ... var categorySchema = new Schema({ ... products: [ProductSchema] }); 

当我尝试保存类别

 var categories = [ {..., products: []}, {..., products: []} ]; 

甚至没有产品

 var categories = [ {...}, {...} ]; 

我得到错误

 { [MongoError: E11000 duplicate key error index: test.categories.$products.name_1 dup key: { : undefined }] name: 'MongoError', err: 'E11000 duplicate key error index: test.categories.$products.name_1 dup key: { : undefined }', code: 11000, n: 0, lastOp: { _bsontype: 'Timestamp', low_: 6, high_: 1404282198 }, ok: 1 } 

似乎mongoose正试图用未定名称来保存产品。

获取错误之前的Mongoose日志:

 Mongoose: categories.insert({ __v: 0, products: [], _id: ObjectId("53b3c167d28a86102dec420a"), order: 1, description: 'Category 1', name: 'Cat 1' }) {} Mongoose: categories.insert({ __v: 0, products: [], _id: ObjectId("53b3c167d28a86102dec420b"), order: 2, description: 'Category 2', name: 'Cat 2' }) {} 

如果我从productSchemaname属性中删除unique:true ,则添加两个类别为empty products []集合的类别。

我究竟做错了什么?

谢谢!

这真的很正常。 空数组本质上被认为是“products.name”字段的“null”值,这当然违反了索引上的唯一约束。

你基本上可以“跳过”实际上未定义的“name”的任何值,并且通过将“sparse”属性添加到索引来做到这一点。 在当前的模式path中:

 var productSchema = new Schema({ name: { type: String, required: true, unique: true, sparse: true } }); var categorySchema = new Schema({ products: [productSchema] }); 

现在只要“名”没有价值,就没有问题,除非它真的存在于某个地方。 确保先删除已经创build的索引。

请注意,这样做的目的是确保“products.name”值对于“整个”集合是唯一的。 如果您只是试图确定它们对于给定类别是唯一的,那么索引不是您的解决scheme,您需要通过其他方式来确保。