MongoDB:嵌入式文档中的唯一键

Abe*_*Abe 17 mongodb

是否可以为嵌入文档中的键设置唯一键?

我有一个Users集合,其中包含以下示例文档:

 {
       Name: "Bob",
       Items: [
           {
               Name: "Milk"
           },
           {
               Name: "Bread"
           }
       ]
    },
    {
       Name: "Jim"
    },
Run Code Online (Sandbox Code Playgroud)

有没有办法在属性Items.Name上创建索引?

我尝试创建索引时出现以下错误:

> db.Users.ensureIndex({"Items.Name": 1}, {unique:true});
E11000 duplicate key error index: GroceryGuruApp.Users.$Items.Name_1  dup key: {
 : null }
Run Code Online (Sandbox Code Playgroud)

有什么建议?谢谢!

pin*_*33n 23

唯一索引仅存在于集合中.要在文档中强制实施唯一性和其他约束,您必须在客户端代码中执行此操作.(可能虚拟馆藏允许这样做,你可以投票支持它.)

在你的情况下,你想要做的是在key上创建索引,Items.Name这在任何文档中都不存在(它不引用数组中的嵌入文档Items),因此它null违反了集合中的唯一约束.

  • 谢谢!我最终不得不查询对象,检查客户端的重复项,然后在Items数组上使用$ set运算符 (2认同)

小智 7

您可以创建一个唯一的复合稀疏索引来完成您希望的内容.它可能不是最好的选择(客户端可能仍然可能更好),但它可以根据具体要求做你要求的.

要做到这一点,你需要创建Name: Bob与每个顶级记录唯一相同级别的另一个字段(可以执行FirstName + LastName + Address,我们将调用此密钥Identifier).

然后创建一个这样的索引:

ensureIndex({'Identifier':1, 'Items.name':1},{'unique':1, 'sparse':1})
Run Code Online (Sandbox Code Playgroud)

稀疏索引将忽略没有该字段的项目,因此应该解决您的NULL密钥问题.将您的唯一标识符和Items.name作为复合唯一索引组合在一起,应确保每个人不能拥有两次相同的项目名称.

虽然我应该补充一点,我只和Mongo一起工作了几个月,而我的科学可能会被淘汰.这不是基于经验证据,而是基于观察到的行为.

有关MongoDB索引的更多信息

  • 它不适用于Mongo 2.2.唯一索引确保文档之间的唯一性而不是子文档,因此唯一的`Identifier`使得这个建议完全无用(因为`Identifier`对于每个文档都是唯一的,整个`Identifier` +`Items.name`也总是唯一的).更多细节[这里](http://joegornick.com/2012/10/25/mongodb-unique-indexes-on-single-embedded-documents/). (3认同)