3
votes

I want to create a unique index over two columns where the index should allow multiple null values for the second part of the index. But:

db.model.ensureIndex({userId : 1, name : 1},{unique : true, sparse : true});

Throws a duplicate key exception: E11000 duplicate key error index: devmongo.model.$userId_1_name_1 dup key: { : "-1", : null }. I thought because of the sparse=true option the index should allow this constellation? How can I achieve this? I use MongoDB 2.6.5

3

3 Answers

4
votes

Sparse compound indexes will create an index entry for a document if any of the fields exist, setting the value to null in the index for any fields that do not exist in the document. Put another way: a sparse compound index will only skip a document if all of the index fields are missing from the document.

As of v3.2, partial indexes can be used to accomplish what you're trying to do. You could use:

db.model.ensureIndex({userId : 1, name : 1}, { partialFilterExpression: { name: { $exists: true },  unique: true });

which will only index documents that have a name field.

NB: This index cannot be used by mongo to handle a query by userId as it will not contain all of the documents in the collection. Also, a null in the document is considered a value and a field that has a null value exists.

2
votes

The compound index should be considered as a whole one, so unique requires (userId, name) pair must be unique in the collection, and sparse means if both userId and name missed in a document, it is allowed. The error message shows that there are at least two documents whose (userId, name) pairs are equivalent (if a field missed, the value can be considered as null).

0
votes

In my case, it turns out field names are case sensitive.

So creating a compound index on {field1 : 1, field2 : 1} is not the same as {Field1 : 1, Field2 : 1}