MongoDB 嵌套的唯一索引 objects
MongoDB Unique Index on nested objects
这是我的 MongoDB collection :
{
"_id": "0",
"profiles": {
"A123": {
"name": "Mike"
},
"B456": {
"name": "John"
}
}
我想确保“名称”字段不能具有相同的值。如果有人叫迈克,就没有人可以叫迈克
如果我尝试在“配置文件”中的此 collection 中创建一个新的 object 且名称已被使用,我该如何创建一个会引发错误的索引?
以你目前的结构你做不到。 unique index 这种方式,您可以使用某个嵌套值作为参考,因为唯一索引的要点是区分文档而不是在单个文档中。
您可以执行以下两项操作之一:
- 更改文档结构。将您的文档更改为:
[
{
"_id": "0",
"profile": {
"name": "Mike",
"key": "A123"
}
},
{
"_id": "1",
"profile": {
"name": "John",
"key": "B456"
}
}
]
使用这样的结构,您可以在 profile.name
上创建一个唯一索引,如下所示:
db.collection.createIndex({"profile.name" : 1}, { unique: true } );
- 有另一个名为 names 的集合,并将其用作您的参考。请注意,如果您经常更新名称,这可能会导致大量开销操作。如果不是,这将是解决您的问题的一种快速简便的方法,因为您只需要在插入/删除操作时更新它。
//code from output of windows mongo shell client CLI(command line interface)
//create a collection for profiles with objects shown
db.test5.insertMany(
[
{
"_id": "0",
"profiles": {
"A123": {
"name": "Mike"
},
"B456": {
"name": "John"
}
}
}
]);
> db.test5.find().pretty();
{
"_id" : "0",
"profiles" : {
"A123" : {
"name" : "Mike"
},
"B456" : {
"name" : "John"
}
}
}
>
> db.test5.find().pretty();
{
"_id" : "0",
"profiles" : {
"A123" : {
"name" : "Mike"
},
"B456" : {
"name" : "John"
}
}
}
>//create index with the path leading to name,
//"*" is used as its not unique within the object path
//check index is created
> db.test5.getIndexes();
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.test5"
},
{
"v" : 2,
"key" : {
"profiles.*.name" : 1
},
"name" : "profiles.*.name_1",
"ns" : "test.test5"
}
]
//test duplicate document insertion for "Mike" as document exists for "Mike"
> db.test5.insertOne(
... {
... "_id": "0",
... "profiles": {
... "A123": {
... "name": "Mike"
... }
... }
... }
... );
2020-09-13T13:23:04.908+0530 E QUERY [js] WriteError({
"index" : 0,
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.test5 index: _id_ dup key: { _id: \"0\" }",
"op" : {
"_id" : "0",
"profiles" : {
"A123" : {
"name" : "Mike"
}
}
}
}) :
WriteError({
"index" : 0,
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.test5 index: _id_ dup key: { _id: \"0\" }",
"op" : {
"_id" : "0",
"profiles" : {
"A123" : {
"name" : "Mike"
}
}
}
})
WriteError@src/mongo/shell/bulk_api.js:458:48
mergeBatchResults@src/mongo/shell/bulk_api.js:855:49
executeBatch@src/mongo/shell/bulk_api.js:919:13
Bulk/this.execute@src/mongo/shell/bulk_api.js:1163:21
DBCollection.prototype.insertOne@src/mongo/shell/crud_api.js:264:9
@(shell):1:1
//re-check the collection, no duplicates are inserted
> db.test5.find().pretty();
{
"_id" : "0",
"profiles" : {
"A123" : {
"name" : "Mike"
},
"B456" : {
"name" : "John"
}
}
}
>
这是我的 MongoDB collection :
{
"_id": "0",
"profiles": {
"A123": {
"name": "Mike"
},
"B456": {
"name": "John"
}
}
我想确保“名称”字段不能具有相同的值。如果有人叫迈克,就没有人可以叫迈克
如果我尝试在“配置文件”中的此 collection 中创建一个新的 object 且名称已被使用,我该如何创建一个会引发错误的索引?
以你目前的结构你做不到。 unique index 这种方式,您可以使用某个嵌套值作为参考,因为唯一索引的要点是区分文档而不是在单个文档中。
您可以执行以下两项操作之一:
- 更改文档结构。将您的文档更改为:
[
{
"_id": "0",
"profile": {
"name": "Mike",
"key": "A123"
}
},
{
"_id": "1",
"profile": {
"name": "John",
"key": "B456"
}
}
]
使用这样的结构,您可以在 profile.name
上创建一个唯一索引,如下所示:
db.collection.createIndex({"profile.name" : 1}, { unique: true } );
- 有另一个名为 names 的集合,并将其用作您的参考。请注意,如果您经常更新名称,这可能会导致大量开销操作。如果不是,这将是解决您的问题的一种快速简便的方法,因为您只需要在插入/删除操作时更新它。
//code from output of windows mongo shell client CLI(command line interface)
//create a collection for profiles with objects shown
db.test5.insertMany(
[
{
"_id": "0",
"profiles": {
"A123": {
"name": "Mike"
},
"B456": {
"name": "John"
}
}
}
]);
> db.test5.find().pretty();
{
"_id" : "0",
"profiles" : {
"A123" : {
"name" : "Mike"
},
"B456" : {
"name" : "John"
}
}
}
>
> db.test5.find().pretty();
{
"_id" : "0",
"profiles" : {
"A123" : {
"name" : "Mike"
},
"B456" : {
"name" : "John"
}
}
}
>//create index with the path leading to name,
//"*" is used as its not unique within the object path
//check index is created
> db.test5.getIndexes();
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.test5"
},
{
"v" : 2,
"key" : {
"profiles.*.name" : 1
},
"name" : "profiles.*.name_1",
"ns" : "test.test5"
}
]
//test duplicate document insertion for "Mike" as document exists for "Mike"
> db.test5.insertOne(
... {
... "_id": "0",
... "profiles": {
... "A123": {
... "name": "Mike"
... }
... }
... }
... );
2020-09-13T13:23:04.908+0530 E QUERY [js] WriteError({
"index" : 0,
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.test5 index: _id_ dup key: { _id: \"0\" }",
"op" : {
"_id" : "0",
"profiles" : {
"A123" : {
"name" : "Mike"
}
}
}
}) :
WriteError({
"index" : 0,
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.test5 index: _id_ dup key: { _id: \"0\" }",
"op" : {
"_id" : "0",
"profiles" : {
"A123" : {
"name" : "Mike"
}
}
}
})
WriteError@src/mongo/shell/bulk_api.js:458:48
mergeBatchResults@src/mongo/shell/bulk_api.js:855:49
executeBatch@src/mongo/shell/bulk_api.js:919:13
Bulk/this.execute@src/mongo/shell/bulk_api.js:1163:21
DBCollection.prototype.insertOne@src/mongo/shell/crud_api.js:264:9
@(shell):1:1
//re-check the collection, no duplicates are inserted
> db.test5.find().pretty();
{
"_id" : "0",
"profiles" : {
"A123" : {
"name" : "Mike"
},
"B456" : {
"name" : "John"
}
}
}
>