子文档上的Mongoose唯一索引

Seb*_*wak 10 indexing mongoose mongodb

假设我有一个简单的架构:

var testSchema = new mongoose.Schema({
    map: { type: [ mongoose.Schema.Types.Mixed ], default: [] },
    ...possibly something else
});
Run Code Online (Sandbox Code Playgroud)

现在让我们确保对(_id,map._id)是唯一的.

testSchema.index({ _id: 1, 'map._id': 1 }, { unique: true });
Run Code Online (Sandbox Code Playgroud)

快速检查使用db.test.getIndexes()显示它已创建.

{
    "v" : 1,
    "unique" : true,
    "key" : {
        "_id" : 1,
        "map._id" : 1
    },
    "name" : "_id_1_map._id_1",
    "ns" : "test.test",
    "background" : true,
    "safe" : null
}
Run Code Online (Sandbox Code Playgroud)

问题是,这个索引被忽略了,我可以轻松地创建多个具有相同的子文档map._id.我可以轻松地多次执行以下查询:

db.maps.update({ _id: ObjectId("some valid id") }, { $push: { map: { '_id': 'asd' } } });
Run Code Online (Sandbox Code Playgroud)

并最终得到以下:

{
    "_id": ObjectId("some valid id"),
    "map": [
        {
            "_id": "asd" 
        },
        {
            "_id": "asd" 
        },
        {
            "_id": "asd" 
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?为什么我可以推送冲突的子文档?

Seb*_*wak 20

长话短说:Mongo不支持子文档的唯一索引,虽然它允许创建它们...

  • ...这意味着对于子文档的唯一索引不可能按照问题中解释的方式进行,这就是我写的内容. (4认同)

小智 11

这出现在谷歌所以我想我会添加一个替代使用索引来实现独特的键约束,如子文档中的功能,希望没关系.

我对Mongoose并不十分熟悉,所以它只是一个mongo控制台更新:

var foo = { _id: 'some value' }; //Your new subdoc here

db.yourCollection.update(
{ '_id': 'your query here', 'myArray._id': { '$ne': foo._id } },
{ '$push': { myArray: { foo } })
Run Code Online (Sandbox Code Playgroud)

文档看起来像:

{
  _id: '...',
  myArray: [{_id:'your schema here'}, {...}, ...]
}
Run Code Online (Sandbox Code Playgroud)

如果您的子文档密钥已经存在,那么确保更新的关键不会返回要更新的文档(即查找部分).