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

Ele*_*onk 25 mongodb

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

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

class Kitten {
  int id;
}
Run Code Online (Sandbox Code Playgroud)

我想阻止用户使用相同ID创建一只有多只小猫的猫.我已经尝试创建索引如下:

db.Cats.ensureIndex({'id': 1, 'kittens.id': 1}, {unique:true})
Run Code Online (Sandbox Code Playgroud)

但是当我尝试插入格式错误的猫时,Mongo会接受它.

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

Chr*_*tow 32

据我所知,唯一索引仅强制执行不同文档的唯一性,因此会产生重复的键错误:

db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )
db.cats.insert( { id: 123, kittens: [ { id: 456 } ] } )
Run Code Online (Sandbox Code Playgroud)

但这是允许的:

db.cats.insert( { id: 123, kittens: [ { id: 456 }, { id: 456 } ] } )
Run Code Online (Sandbox Code Playgroud)

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

  • 好难过!:(.应该有一个选项来确保文档数组的唯一性. (7认同)
  • 不幸的是,你似乎是对的 - 我必须在代码中执行此操作.那好吧. (2认同)

dou*_*lix 26

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

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

因此,如果您有一个如下所示的文档:

{ _id: 123, kittens: [456] }
Run Code Online (Sandbox Code Playgroud)

这将是允许的:

db.cats.update({_id:123}, {$push: {kittens:456}})
Run Code Online (Sandbox Code Playgroud)

导致

{ _id: 123, kittens: [456, 456] }
Run Code Online (Sandbox Code Playgroud)

但是使用$ addToSet函数(而不是$ push)将在添加之前检查该值是否已存在.所以,从:

{ _id: 123, kittens: [456] }
Run Code Online (Sandbox Code Playgroud)

然后执行:

db.cats.update({_id:123}, {$addToSet: {kittens:456}})
Run Code Online (Sandbox Code Playgroud)

不会有任何影响.

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