This is the 28th day of my participation in the August Challenge

By default, MongoDB creates an _ID attribute on each document of type ObjectId. Many other databases use the numeric ID attribute by default, but in MongoDB and Mongoose, ids default to objects.

const Model = mongoose.model('Test', mongoose.Schema({ name: String }))
const doc = new Model({ name: 'test' })
​
doc._id instanceof mongoose.Types.ObjectId // true
typeof doc._id // object
doc._id // 5d6ede6a0ba62570afcedd3a
Copy the code

ObjectIds

The MongoDB ObjectIds is expressed in 24 hexadecimal strings, for example, 5d6eDE6A0BA62570afcedd3a. Mongoose casts a 24-character string for your ObjectIds based on the pattern path.

const schema = mongoose.Schema({ testId: mongoose.ObjectId })
const Model = mongoose.model('Test', schema)
​
const doc = new Model({ testId: '5d6ede6a0ba62570afcedd3a' })
​
// testId is an ObjectId. Mongoose will automatically convert 24 hexadecimal character strings into an ObjectId based on your mode.
doc.testId instanceof mongoose.Types.ObjectId // true
Copy the code

Mongoose can also transform several other values into ObjectId. The key lesson is that ObjectId is 12 arbitrary bytes. Any 12-byte buffer or 12-character string is a valid ObjectId.

const schema = mongoose.Schema({ testId: mongoose.ObjectId })
const Model = mongoose.model('Test', schema)

// Any 12-character string will be a valid ObjectId because the only defining feature of the ObjectId is that they have 12 bytes.
let doc = new Model({ testId: '12char12char' })
doc.testId instanceof mongoose.Types.ObjectId; // true
doc.testId; / / '313263686172313263686172'

// Similarly, Mongoose will automatically convert a 12-length buffer to ObjectID.
doc = new Model({ testId: Buffer.from('12char12char') })
doc.testId instanceof mongoose.Types.ObjectId // true
doc.testId / / 313263686172313263686172
Copy the code

Get the timestamp from ObjectId

The ObjectId encodes the local time when they are created. This means that you can usually extract the time when the document was created from the document’s _ID.

const schema = mongoose.Schema({ testId: mongoose.ObjectId })
const Model = mongoose.model('Test', schema)
​
const doc = new Model({ testId: '313263686172313263686172' })
doc.testId.getTimestamp() / / the 1996-02-27 T01: most. 000 z
doc.testId.getTimestamp() instanceof Date // true
Copy the code

Why ObjectIds?

Suppose you are building your own database and want to set a numeric ID attribute on each new document. The ID attribute should be increased, so the first document inserted has ID = 0, then ID = 1, and so on.

Incrementing counters in a single process is an easy problem. But what if you have multiple processes, such as a sharded cluster? Now, every process needs to be able to increment the counter, so whenever a document is inserted, you need to increment the distributed counter. If there is significant network latency between two processes, performance may be unreliable. If a process is down, unpredictable results can result.

ObjectId aims to address this problem. The likelihood of an ObjectId conflict is small, so MongoDB can assign ids that might be unique in a distributed system without interprocess communication.