如何为嵌套在数组中的文档中的字段设置唯一约束?

问题描述 投票:1回答:1

我在MongoDB中有一个文档集合,看起来像。

{"_id": 1, "array": [{"id": 1, "content": "..."}, {"id": 2, "content": "..."}]}
{"_id": 2, "array": [{"id": 1, "content": "..."}, {"id": 2, "content": "..."}, {"a_id": 3, "content": "..."}]}

我想确保没有重复的文件。array.id 在每个文档中。因此,所提供的例子是可以的,但下面的例子就不行了。

{"_id": 1, "array": [{"id": 1, "content": "..."}, {"id": 1, "content": "..."}]}

我的问题是如何做到这一点(最好是在以下情况下) PyMongo).

编辑

我尝试的是下面的代码,我认为可以创建键上。(_id, array.id) 但如果你运行它就不会发生这种情况。

from pymongo import MongoClient, ASCENDING

client = MongoClient(host="localhost", port=27017)
database = client["test_db"]
collection = database["test_collection"]
collection.drop()

collection.create_index(keys=[("_id", ASCENDING),
                              ("array.id", ASCENDING)],
                        unique=True,
                        name="new_key")

document = {"array": [{"id": 1}, {"id": 2}]}
collection.insert_one(document)

collection.find_one_and_update({"_id": document["_id"]},
                               {"$push": {"array": {"id": 1}}})

updated_document = collection.find_one({"_id": document["_id"]})

print(updated_document)

它的输出(注意,有两个对象带有 id = 1array). 我希望得到一个异常。

{'_id': ObjectId('5eb51270d6d70fbba739e3b2'), 'array': [{'id': 1}, {'id': 2}, {'id': 1}]}
arrays mongodb indexing pymongo
1个回答
1
投票

所以,如果我理解正确的话,没有办法设置索引(或一些条件)来强制文档的唯一性,对吗?(除了在创建文档或插入文档时明确地检查这个之外。)

是的。请看下面两个关于在嵌入文档的数组字段上使用唯一索引的场景。

唯一的多键索引 (数组内嵌入文档字段的索引)。

对于唯一的索引,唯一的约束适用于集合中的不同文档,而不是在单个文档中。

因为唯一约束适用于不同的文档,所以对于唯一的多键索引,只要该文档的索引键值不与另一个文档的索引键值重复,该文档的数组元素可能会导致重复的索引键值。

第一种情况。

db.arrays.createIndex( { _id: 1, "array.id": 1}, { unique: true } )

db.arrays.insertOne( { "_id": 1, "array": [ { "id": 1, "content": "11"}, { "id": 2, "content": "22"} ] } )

db.arrays.insertOne( { "_id": 2, "array": [ { "id": 1, "content": "1100"}, { "id": 5, "content": "55"} ] } )

db.arrays.insertOne( {"_id": 3, "array": [ {"id": 3, "content": "33"}, {"id": 3, "content": "3300"} ] } )

所有三个文档都被插入,没有任何错误。

根据关于 獨特的多鍵索引上文中,该文件有 _id : 3 在数组内有两个内嵌的文件,它们具有相同的 "array.id"价值。3.

同时,在复合索引的两个键上也强制执行唯一性。{ _id: 1, "array.id": 1} 而且有重复的 "array.id" 的值,也是跨文件的值( _id 价值观 12).

第二种情况。

db.arrays2.createIndex( { "array.id": 1 }, { unique: true } )

db.arrays2.insertOne( { "_id": 3, "array": [ { "id": 3, "content": "33" }, { "id": 3, "content": "330"} ] } )
db.arrays2.insertOne( { "_id": 4, "array": [ { "id": 3, "content": "331" }, { "id": 30, "content": "3300" } ] } )

第一份文件有: _id : 3 被成功插入。第二个有一个错误。"errmsg" : "E11000 duplicate key error collection: test.arrays2 index: array.id_1 dup key: { array.id: 3.0 } ". 这种行为是根据注释中的预期 獨特的多鍵索引.

© www.soinside.com 2019 - 2024. All rights reserved.