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