Поле _id и тип ObjectId
Первичный ключ каждого документа: что такое ObjectId и когда стоит назначать _id вручную.
Каждый документ обязан иметь уникальное поле _id — это его первичный ключ. Если вы его не задали, MongoDB подставит значение типа ObjectId.
_id есть всегда
В MongoDB нет документа без _id. Это поле уникально в пределах коллекции и автоматически индексируется, поэтому поиск по нему очень быстрый. По сути это аналог PRIMARY KEY из реляционных баз — только обязательный и встроенный.
Как устроен ObjectId
Значение по умолчанию — ObjectId, 12-байтовый идентификатор. Он не случаен, в нём закодированы:
- 4 байта — время создания (Unix-время в секундах);
- 5 байт — случайное значение, уникальное для процесса/машины;
- 3 байта — инкрементирующий счётчик.
Такая конструкция даёт два приятных свойства: идентификаторы практически не сталкиваются даже на разных серверах (важно при шардировании), и они примерно отсортированы по времени — более новые документы имеют большие ObjectId. Из ObjectId даже можно достать дату создания:
const id = ObjectId("652f1a2b3c4d5e6f7a8b9c0d");
id.getTimestamp(); // вернёт Date создания документаСвой собственный _id
Вы не обязаны использовать ObjectId. Если у сущности есть естественный уникальный ключ — артикул товара, email, код страны — можно задать _id самому:
db.products.insertOne({
_id: "SKU-1001",
name: "Кофе",
price: 450
})Теперь поиск по артикулу — это поиск по первичному ключу, самый быстрый из возможных. Но помните: _id уникален, и повторная вставка с тем же значением даст ошибку дубликата.
Результат:
{
"errmsg": "E11000 duplicate key error",
"code": 11000
}Что использовать
Если естественного ключа нет — оставьте ObjectId по умолчанию, это надёжно и удобно. Если есть стабильный бизнес-идентификатор, который точно не меняется, — задавайте его сами: запросы по нему станут проще и быстрее. Менять _id у существующего документа нельзя, поэтому выбирайте то, что не будет меняться.
Итог
_id— обязательный уникальный первичный ключ, индексируется автоматически.ObjectIdкодирует время создания, что даёт уникальность и приблизительную сортировку по времени.- Можно задать собственный
_id; повтор значения вызовет ошибку дубликата (E11000).