-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathindex-unique.txt
404 lines (277 loc) · 12.3 KB
/
index-unique.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
.. _index-type-unique:
==============
Unique Indexes
==============
.. default-domain:: mongodb
.. facet::
:name: programming_language
:values: shell
.. facet::
:name: genre
:values: reference
.. meta::
:description: Use a unique index to ensure indexed fields do not store duplicate values.
.. contents:: On this page
:local:
:backlinks: none
:depth: 1
:class: singlecol
A unique index ensures that the indexed fields do not store duplicate
values. A unique index on a single field ensures that a value appears
at most once for a given field. A unique compound index ensures that
any given *combination* of the index key values only appears at most
once. By default, MongoDB creates a unique index on the :ref:`_id
<document-id-field>` field during the creation of a collection.
.. |page-topic| replace:: :atlas:`create and manage unique indexes in the UI </atlas-ui/indexes>`
.. cta-banner::
:url: https://www.mongodb.com/docs/atlas/atlas-ui/indexes/
:icon: Cloud
.. include:: /includes/fact-atlas-compatible.rst
.. _index-unique-create:
Create a Unique Index
---------------------
To create a unique index, use the :method:`db.collection.createIndex()`
method with the ``unique`` option set to ``true``.
.. code-block:: javascript
db.collection.createIndex( <key and index type specification>, { unique: true } )
.. _index-unique-index:
Unique Index on a Single Field
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For example, to create a unique index on the ``user_id`` field of the
``members`` collection, use the following operation in
:binary:`~bin.mongosh`:
.. code-block:: javascript
db.members.createIndex( { "user_id": 1 }, { unique: true } )
.. _index-unique-compound-index:
Unique Compound Index
~~~~~~~~~~~~~~~~~~~~~
You can also enforce a unique constraint on :ref:`compound indexes
<index-type-compound>`. A unique :ref:`compound index
<index-type-compound>` enforces uniqueness on the *combination* of the
index key values.
For example, to create a unique index on ``groupNumber``, ``lastname``,
and ``firstname`` fields of the ``members`` collection, use the
following operation in :binary:`~bin.mongosh`:
.. code-block:: javascript
db.members.createIndex( { groupNumber: 1, lastname: 1, firstname: 1 }, { unique: true } )
The created index enforces uniqueness for the *combination* of
``groupNumber``, ``lastname``, and ``firstname`` values.
For another example, consider a collection with the following document:
.. code-block:: javascript
{ _id: 1, a: [ { loc: "A", qty: 5 }, { qty: 10 } ] }
Create a unique compound :ref:`multikey <index-type-multikey>` index
on ``a.loc`` and ``a.qty``:
.. code-block:: javascript
db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )
The unique index permits the insertion of the following documents into
the collection since the index enforces uniqueness for the
*combination* of ``a.loc`` and ``a.qty`` values:
.. code-block:: javascript
db.collection.insertMany( [
{ _id: 2, a: [ { loc: "A" }, { qty: 5 } ] },
{ _id: 3, a: [ { loc: "A", qty: 10 } ] }
] )
.. seealso::
- :ref:`unique-separate-documents`
- :ref:`unique-index-and-missing-field`
Behavior
--------
.. _unique-index-restrictions:
Restrictions
~~~~~~~~~~~~~
MongoDB cannot create a :ref:`unique index <index-type-unique>` on the
specified index field(s) if the collection already contains data that
would violate the unique constraint for the index.
You may not specify a unique constraint on a :ref:`hashed
index <index-type-hashed>`.
Building Unique Index on Replica Sets and Sharded Clusters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For replica sets and sharded clusters, using a :ref:`rolling procedure
<index-build-on-replica-sets>` to create a unique index
requires that you stop all writes to the collection during the
procedure. If you cannot stop all writes to the collection during the
procedure, do not use the rolling procedure. Instead, to build your
unique index on the collection you must either:
- Run ``db.collection.createIndex()`` on the primary for a
replica set
- Run ``db.collection.createIndex()`` on the :binary:`~bin.mongos`
for a sharded cluster
.. _unique-separate-documents:
Unique Constraint Across Separate Documents
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The unique constraint applies to separate documents in the collection.
That is, the unique index prevents *separate* documents from having the
same value for the indexed key.
Because the constraint applies to separate documents, for a unique
:ref:`multikey <index-type-multikey>` index, a document may have array
elements that result in repeating index key values as long as the index
key values for that document do not duplicate those of another
document. In this case, the repeated index entry is inserted into the
index only once.
For example, consider a collection with the following documents:
.. code-block:: javascript
{ _id: 1, a: [ { loc: "A", qty: 5 }, { qty: 10 } ] }
{ _id: 2, a: [ { loc: "A" }, { qty: 5 } ] }
{ _id: 3, a: [ { loc: "A", qty: 10 } ] }
Create a unique compound multikey index on ``a.loc`` and ``a.qty``:
.. code-block:: javascript
db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )
The unique index permits the insertion of the following document into
the collection if no other document in the collection has an index key
value of ``{ "a.loc": "B", "a.qty": null }``.
.. code-block:: javascript
db.collection.insertOne( { _id: 4, a: [ { loc: "B" }, { loc: "B" } ] } )
.. _unique-index-and-missing-field:
Missing Document Field in a Unique Single-Field Index
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If a document has a ``null`` or missing value for the indexed field in a unique
single-field index, the index stores a ``null`` value for that document.
Because of the unique constraint, a single-field unique index can only
contain one document that contains a ``null`` value in its index entry. If there is
more than one document with a ``null`` value in its index entry, the index
build fails with a duplicate key error.
For example, a collection has a unique single-field index on ``x``:
.. code-block:: javascript
db.collection.createIndex( { "x": 1 }, { unique: true } )
The unique index allows the insertion of a document without the field
``x`` if the collection does not already contain a document missing the
field ``x``:
.. code-block:: javascript
db.collection.insertOne( { y: 1 } )
However, you cannot insert a document without the field ``x`` if the
collection already contains a document missing the field ``x``:
.. code-block:: javascript
db.collection.insertOne( { z: 1 } )
The operation fails to insert the document because of the violation of
the unique constraint on the value of the field ``x``:
.. code-block:: javascript
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error index: test.collection.$a.b_1 dup key: { : null }"
}
})
.. _unique-partial-indexes:
Missing Document Fields in a Unique Compound Index
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If a document has a ``null`` or missing value for one or more indexed
fields in a unique compound index, the index stores a null value for
each ``null`` or missing field in the document's index entry. Because of
the unique constraint, a unique compound index only permits one document
that has a ``null`` value for all indexed fields in an index entry. If
there is more than one index entry with a ``null`` value for all indexed
fields, the index build fails with a duplicate key error. MongoDB
permits multiple documents with missing fields in unique compound
indexes as long as each index entry is unique.
For example, a collection ``students`` has a unique compound index on fields
``name``, ``age``, and ``grade``:
.. code-block:: javascript
db.students.createIndex(
{
"name": 1,
"age": -1,
"grade": 1
},
{ unique: true }
)
If the collection does not already contain identical documents, the
unique compound index allows the insertion of the following documents
that are all missing the ``grade`` field.
.. code-block:: javascript
db.students.insertMany(
{ "name": "Meredith", "age": 12 },
{ "name": "Olivia", "age": 11 },
{ "name": "Benjamin" }
)
However, you cannot insert a document that has the same index key (value
for ``name``, ``age``, and ``grade``) as another document in the
collection.
.. code-block:: javascript
db.students.insertOne( { name: "Meredith", age: 12 } )
The operation fails to insert the document because of the violation of
the unique constraint on the values of the fields ``name``, ``age``, and ``grade``:
.. code-block:: javascript
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" :
"E11000 duplicate key error collection: test.students
index: name_1_age_-1_grade_1
dup key: { name: "Meredith", age: 12, grade: null }
}
} )
You also cannot insert a document that is unique but shares an index
key with an existing index entry.
.. code-block:: javascript
db.students.insertOne( { name: "Olivia", "age": 11, "favorite color": "red"} )
The operation fails to insert the document because of the violation of
the unique constraint on the values of the fields ``name``, ``age``, and
``grade``:
.. code-block:: javascript
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" :
"E11000 duplicate key error collection: test.students
index: name_1_age_-1_grade_1
dup key: { name: "Olivia", age: 11, grade: null }
}
} )
Unique Partial Indexes
~~~~~~~~~~~~~~~~~~~~~~
Partial indexes only index the documents in a collection that meet a
specified filter expression. If you specify both the
``partialFilterExpression`` and a :ref:`unique constraint
<index-type-unique>`, the unique constraint only applies to the
documents that meet the filter expression.
A partial index with a unique constraint does not prevent the insertion
of documents that do not meet the unique constraint if the documents do
not meet the filter criteria. For an example, see
:ref:`partial-index-with-unique-constraints`.
.. _sharded-clusters-unique-indexes:
Sharded Clusters and Unique Indexes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You cannot specify a unique constraint on a :ref:`hashed index
<index-type-hashed>`.
For a ranged sharded collection, only the following indexes can be
:ref:`unique <index-type-unique>`:
- the index on the shard key
- a :term:`compound index` where the shard key is a :ref:`prefix
<compound-index-prefix>`
- The default ``_id`` index; however, the ``_id`` index only
enforces the uniqueness constraint **per shard** if the ``_id`` field
is not the shard key.
.. include:: /includes/sharding/shard-collection-uniqueness-enforcement-note.rst
.. include:: /includes/sharding/sharding-unique-index-constraints.rst
To maintain uniqueness on a field that is not your shard key,
see :ref:`shard-key-arbitrary-uniqueness`.
Sparse and Non-Sparse Unique Indexes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. include:: /includes/fact-5.0-sparse-unique-index-updates.rst
Basic and Unique Indexes With Duplicate Key Patterns
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Starting in MongoDB 5.0, basic and unique indexes can exist with the
same :ref:`key pattern <key_patterns>`.
This duplication in key patterns allows for adding a unique index to
already indexed fields.
In this example:
Create a basic index with the key pattern ``{ score : 1 }`` and insert
three documents.
.. code-block:: javascript
db.scoreHistory.createIndex( { score : 1 }, { name: "basic_index" } )
db.scoreHistory.insert( { score : 1 } )
db.scoreHistory.insert( { score : 2 } )
db.scoreHistory.insert( { score : 3 } )
Create a unique index with the same key pattern ``{ score : 1 }``.
.. code-block:: javascript
db.scoreHistory.createIndex( { score : 1 }, { name: "unique_index", unique: true } )
Try to insert a duplicate ``score`` document that fails because of
the unique index.
.. code-block:: javascript
db.scoreHistory.insert( { score : 3 } )
.. toctree::
:titlesonly:
Convert to Unique </core/index-unique/convert-to-unique>