Let's assume this is a document representing a customer.
{
company_name: 'corporate ltd.',
pocs: [
{name: 'Paul', email: '[email protected]'},
{name: 'Jessica', email: '[email protected]'}
]
}
I wanted to define a unique index for pocs.email
So I issued the following command:
db.things.ensureIndex({"pocs.email": 1}, {unique: true})
The strange thing is that when trying to add another company with a poc having an email already exists in another company, mongo rejects that, respecting the unique index constraint.
that is, the following cannot exists:
{
company_name: 'corporate ltd.',
pocs: [
{name: 'Paul', email: '[email protected]'},
{name: 'Jessica', email: '[email protected]'}
]
},
{
company_name: 'contoso llc',
pocs: [
{name: 'Paul', email: '[email protected]'},
]
}
Which is fine. However, having duplicate poc within the same doc is possible, e.g.
{
company_name: 'corporate ltd.',
pocs: [
{name: 'Paul', email: '[email protected]'},
{name: 'Paul', email: '[email protected]'},
{name: 'Jessica', email: '[email protected]'}
]
},
see my cli commands sequence below:
> version()
version: 2.0.2
>
> use test
switched to db test
> db.test.ensureIndex({"poc.email": 1}, {unique: true})
>
> db.test.insert({company: "contoso", poc: [{email: '[email protected]'}]})
> db.test.insert({company: "contoso", poc: [{email: '[email protected]'}]})
E11000 duplicate key error index: test.test.$poc.email_1 dup key: { : "[email protected]" }
> ({company: "contoso", poc: [{email: '[email protected]'}, {email: '[email protected]'}]})
>
>
> db.test.find()
{ "_id" : ObjectId("4f44949685926af0ecf9295d"), "company" : "contoso", "poc" : [ { "email" : "[email protected]" } ] }
{ "_id" : ObjectId("4f4494b885926af0ecf9295f"), "company" : "contoso", "poc" : [ { "email" : "[email protected]" }, { "email" : "[email protected]" } ] }
Moreover, this happens either at insert
or at update
.
> db.test.update({"_id" : ObjectId("4f44949685926af0ecf9295d")}, {$push: { poc: {email: '[email protected]'}}})
> db.test.find()
{ "_id" : ObjectId("4f4494b885926af0ecf9295f"), "company" : "contoso", "poc" : [ { "email" : "[email protected]" }, { "email" : "[email protected]" } ] }
{ "_id" : ObjectId("4f44949685926af0ecf9295d"), "company" : "contoso", "poc" : [ { "email" : "[email protected]" }, { "email" : "[email protected]" }, { "email" : "[email protected]" } ] }
>
Is this a bug or a by-design-feature I missed spotting in the documentation?
MongoDB uses the dot notation to access the elements of an array and to access the fields of an embedded document.
Accessing embedded/nested documents – In MongoDB, you can access the fields of nested/embedded documents of the collection using dot notation and when you are using dot notation, then the field and the nested field must be inside the quotation marks.
Indexes can be created by using the createIndex method. Indexes can be created on just one field or multiple field values. Indexes can be found by using the getIndexes method. Indexes can be removed by using the dropIndex for single indexes or dropIndexes for dropping all indexes.
MongoDB provides text indexes to support text search queries on string content. Text indexes can include any field whose value is a string or an array of string elements. A collection can only have one text search index, but that index can cover multiple fields.
There is an open issue regarding the same problem unique indexes not enforced within array of single document . You can vote for it.
Also there is a nice workaround suggested by Kyle Banker in this similar post Unique indexes on embedded documents
Update
This is not only related to the embedded fields, we can reproduce the same for array fields too.
>db.uniqqueTest.insert({a:[1],x:1})
>db.uniqqueTest.createIndex({a:1}, {unique: true})
> db.uniqqueTest.find()
{ "_id" : ObjectId("4f44c6252434860b44986b02"), "a" : [ 1 ],"x":1 }
and it throws an error if we try to create a new document with the same value (correct behavior )
> db.uniqqueTest.insert({a:[1],x:3})
E11000 duplicate key error index: stack.uniqqueTest.$a_1 dup key: { : 1.0 }
But this works fine if we put the same value inside the array (no errors, silently accepts the duplicate value inside the array)
> db.uniqqueTest.insert({a:[2],x:2})
> db.uniqqueTest.update({x:2},{$push:{a:2}})
{ "_id" : ObjectId("4f44c65f2434860b44986b05"), "a" : [ 2, 2 ], "x" : 2 }
But not for this
> db.uniqqueTest.update({x:2},{$push:{a:1}])
E11000 duplicate key error index: stack.uniqqueTest.$a_1 dup key: { : 1.0 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With