MongoDB:数组元素属性的唯一索引

我有一个类似于这样的结构:

class Cat { int id; List<Kitten> kittens; } class Kitten { int id; } 

我想阻止用户使用相同的ID创build一个以上的小猫的猫。 我试着创build一个索引如下:

 db.Cats.ensureIndex({'id': 1, 'kittens.id': 1}, {unique:true}) 

但是当我试图插入格式不正确的猫时,Mongo接受它。

我错过了什么吗? 这甚至可以做到?

据我所知,唯一的索引只强制执行跨不同文档的唯一性,所以这会抛出一个重复的键错误:

 db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } ) db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } ) 

但这是允许的:

 db.cats.insert( { id: 123, kittens: [ { id: 456 }, { id: 456 } ] } ) 

我不确定是否有任何方法可以在Mongo级别强制执行所需的约束,也许在插入更新时可以在应用程序逻辑中检查这些约束。

确保数组字段中各个值的唯一性

除了上面的例子之外,在MongoDB中还有一个函数来确保在向数组字段添加新的对象/值时,如果值/对象不存在,它将只执行更新。

所以,如果你有一个文件,看起来像这样:

 { _id: 123, kittens: [456] } 

这将被允许:

 db.cats.update({_id:123}, {$push: {kittens:456}}) 

导致

 { _id: 123, kittens: [456, 456] } 

然而使用$ addToSet函数(而不是$ push )会在添加之前检查该值是否已经存在。 所以,从以下开始:

 { _id: 123, kittens: [456] } 

然后执行:

 db.cats.update({_id:123}, {$addToSet: {kittens:456}}) 

不会有任何影响。

因此,长话短说,唯一约束不会validation数组字段的值项中的唯一性,只是两个文档在索引字段中不能具有相同的值。

在数组属性中有一个等价的具有唯一性的插入。 下面的命令本质上确实插入,同时确保小猫的唯一性(upsert为你创build它,如果123的对象不存在)。

 db.cats.update( { id: 123 }, { $addToSet: {kittens: { $each: [ 456, 456] }}, $set: {'otherfields': 'extraval', "field2": "value2"}}, { upsert: true} ) 

该对象的结果值将是

 { "id": 123, "kittens": [456], "otherfields": "extraval", "field2": "value2" }