Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Noisy irrelevant warning: "mongoose: Cannot specify a custom index on _id for model name "Settings", MongoDB does not allow overwriting the default _id index. See http://bit.ly/mongodb-id-index" #8462

Closed
nodkz opened this issue Dec 27, 2019 · 5 comments
Labels
help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary

Comments

@nodkz
Copy link
Contributor

nodkz commented Dec 27, 2019

Do you want to request a feature or report a bug?

BUG

What is the current behavior?

If we use the type String for _id field and make them unique index then we got the following noise warning:

mongoose: Cannot specify a custom index on _id for model name "Settings", MongoDB does not allow overwriting the default _id index. See http://bit.ly/mongodb-id-index

But MongoDB correctly works with such type for _id field. And by the provided link http://bit.ly/mongodb-id-index I did not find any restriction for _id field type. Moreover mongoose also correctly works but does not allow to hide this noisy warning.

If the current behavior is a bug, please provide the steps to reproduce.

The following JEST test works well and the correct data stored in MongoDB's collection. And if we try to save another record with the existed value we got EXPECTED (E11000) error that record already exists.

import mongoose from 'mongoose';

beforeAll(() => mongoose.connect());
afterAll(() => mongoose.disconnect());

const SettingsSchema = new mongoose.Schema({
  _id: {
    type: String,
    unique: true,
  },
  value: {
    type: String,
  },
});
const SettingsModel = mongoose.model('Settings', SettingsSchema);

it('try to create', async () => {
  await SettingsModel.create({
    _id: 'size',
    value: '15',
  });
  expect(
    await SettingsModel.findOne({ _id: 'size' })
      .lean()
      .exec()
  ).toEqual({
    __v: 0,
    _id: 'size',
    value: '15',
  });

  await SettingsModel.create({
    _id: 'size2',
    value: '30',
  });
  expect(
    await SettingsModel.findOne({ _id: 'size2' })
      .lean()
      .exec()
  ).toEqual({
    __v: 0,
    _id: 'size2',
    value: '30',
  });

  await expect(
    SettingsModel.create({
      _id: 'size',
      value: '666',
    })
  ).rejects.toThrow('E11000 duplicate key error dup key: { : "size" }');
});

What is the expected behavior?

Allow hiding warning message or remove it at all.

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
5.7.12 and checked with upstream code:

mongoose/lib/model.js

Lines 1587 to 1595 in 7fae539

for (const index of indexes) {
const keys = Object.keys(index[0]);
if (keys.length === 1 && keys[0] === '_id' && index[0]._id !== 'hashed') {
console.warn('mongoose: Cannot specify a custom index on `_id` for ' +
'model name "' + model.modelName + '", ' +
'MongoDB does not allow overwriting the default `_id` index. See ' +
'http://bit.ly/mongodb-id-index');
}
}

Related old issues: #6650 #7053

@vkarpov15
Copy link
Collaborator

That's because every MongoDB collection has a special index on _id, and you can't change that index. In particular, MongoDB's getIndexSpecs() function does not report the _id index as unique:

rs:PRIMARY> db.test.createIndex({ x: 1 }, { unique: true })
{
	"createdCollectionAutomatically" : true,
	"numIndexesBefore" : 1,
	"numIndexesAfter" : 2,
	"ok" : 1,
	"operationTime" : Timestamp(1578004914, 2),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1578004914, 2),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
rs:PRIMARY> db.test.getIndexSpecs()
[
	{
		"v" : 2,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_",
		"ns" : "test.test"
	},
	{
		"v" : 2,
		"unique" : true,
		"key" : {
			"x" : 1
		},
		"name" : "x_1",
		"ns" : "test.test"
	}
]
rs:PRIMARY> 

Why are you setting unique: true on _id?

@vkarpov15 vkarpov15 added the help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary label Jan 2, 2020
@nodkz
Copy link
Contributor Author

nodkz commented Jan 3, 2020

Why are you setting unique: true on _id?

I suppose that it's my old experience from the SQL world. To explicitly set unique for id fields.

Yep, _id field is a special field in MongoDB which automatically indexed as unique under the hood. And MongoDB does not have restrictions for the type of _id field (it can be ObjectID, Int, String or even more – any complex object).

I have just tried

db.getCollection('test').save({ _id: 1 });
db.getCollection('test').save({ _id: 2 });
db.getCollection('test').save({ _id: 1 });

and obtain 2 records with _id: 1 and _id: 2. Third command modified existed record with _id: 1.

For my test case above I just removed the unique index on _id field and got the same correct behavior got E11000 when tried to insert a new record with existed key size. And warning Cannot specify a custom index on '_id' for model... is gone.

So my problem completely resolved when I removed unique: true. Tnx for help! 👍


Anyway, MongoDB allows us to pass unique: true via shell for the _id field. But why mongoose restricts this behavior is still magic for me.

You may close this issue if think that this warning is helpful for developers.

@vkarpov15
Copy link
Collaborator

The problem is that setting unique on _id doesn't do anything, and can cause confusion because mongodb doesn't report the _id index as being unique.

@simoncarbajal
Copy link

This should be reopened.
MongoDB's documentation tells differently, and I quote:

The field name _id is reserved for use as a primary key; its value must be unique in the collection, is immutable, and may be of any type other than an array. If the _id contains subfields, the subfield names cannot begin with a ($) symbol.

It says it must be unique, it doesn't say it's always unique regardless of what you want, so I would naturally try to make it unique by adding unique: true

@vkarpov15
Copy link
Collaborator

@simoncarbajal MongoDB's docs say that the value of _id must be unique. It does not say that you're responsible for creating a unique index on _id.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary
Projects
None yet
Development

No branches or pull requests

3 participants