What is the difference between mongo ObjectID, ObjectId & Mongoose ObjectId - node.js

I can't figure out the difference between mongo ObjectID & ObjectId.
The document said ObjectId, but when I read the code, I see
import { ObjectID } from 'bson';
To make things even more confused is the mongoose document & code.
The mongoose also says ObjectId http://mongoosejs.com/docs/api.html#types-objectid-js. But when I read the codes I saw
// mongodb.ObjectID does not allow mongoose.Types.ObjectId(id). This is
// commonly used in mongoose and is found in an example in the docs:
// http://mongoosejs.com/docs/api.html#aggregate_Aggregate
// constructor exposes static methods of mongodb.ObjectID and ObjectId(id)
type ObjectIdConstructor = typeof mongodb.ObjectID & {
(s?: string | number): mongodb.ObjectID;
}
So what exactly is the difference between ObjectID, ObjectId and mongoose ObjectId?
I found there was another SO talking about this BSON::ObjectId vs Mongo::ObjectID
The links there were dead though and it didn't take about mongoose. So I hope my question won't be marked as duplicated.

Mongo ObjectID is a unique 12-byte identifier which can be generated by MongoDB as the primary key.
An ObjectID is a unique, not null integer field used to uniquely identify rows in tables
In Mongoose ObjectID is same as Mongo ObjectID and referencing an object in another collection

Related

Mongoose: convert _id types in existing collection

I have an existing mongoose collection with using the default ObjectID type for _id.
I want to migrate this collection to use a UUID for the _id, ideally without a special migration step.
My new schema makes use of the package mongoose-uuid4:
var uuidv4 = require('uuid/v4');
require('mongoose-uuid4')(mongoose);
const schema = new mongoose.Schema({
_id: { type: mongoose.Types.UUID, default: uuidv4 },
...
});
const Model = mongoose.model('Model', schema);
My theory here is that my existing ObjectIDs could be zero-padded to be valid UUID objects, so I should be able to write my access methods so I can find by either a short ObjectID or a full UUID.
If I do a Model.find({}) on this collection, the documents come back with no _id fields, but I do get an exception thrown that says it couldn't cast the id value to a UUID:
ValidationError: <Model> validation failed: undefined: Could not cast 6132ba2d6474631eeb038a9b to UUID.
So this makes me think there's a place where I can insert some code to do a type conversion to make this work, because some part of the mongoose stack tried to do this conversion, but didn't know how to.
My first preference is an on-the-fly way of allowing existing _id fields to get upgraded, but I am also ok with a one-time 'fixup' pass through the collection to upgrade fields.
Any suggestions are appreciated.

Cast to ObjectId failed for value "some_id" at path "_id" for model "Category"

when I use findOne from mongoose version 5.9.12, I got some error like this :
error
https://i.stack.imgur.com/8kAcY.png
my code:
[code][2]
https://i.stack.imgur.com/v8Prd.png
my models:
models
From the mongoose documentation:
If you want to query by a document's _id, use findById() instead of
findOne().
The id is cast based on the Schema before sending the command.
So the recommended way to do this is:
Category.findById(categoryId)
If you really want to use findOne and specify _id inside the filter, you can convert the string using
Category.findOne( { _id: mongoose.Types.ObjectId(categoryId) })
to an ObjectId.
Edit: The actual problem is that your categoryId contains a trailing whitespace which causes this problem: "5f05445a9789663d08fb12d2 " - it should be "5f05445a9789663d08fb12d2".

Mongoose keeps giving both _id and id with same value

I have some Mongoose schemas, whose certain fields need getter and setters.
For that, i've set the following:
MySchema.set('toObject',{getters:true});
MySchema.set('toJSON',{getters:true});
Whenever I send/read the result of MySchema.find(), it gives me both _id and id fields, which have same value.
I think thats a virtual field (correct me if i'm wrong here)
How do i stop this? I don't want to process through each and every object and remove the field.
Documented here:
Mongoose assigns each of your schemas an id virtual getter by default which returns the documents _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it passing this option at schema construction time.
Just set the id field to false while creating the schema:
var schema = new Schema({ name: String }, { id: false });

Manually deleting connect-mongo session by _id cast error

I'm attempting to manually delete a document from the connect-mongo sessions collection. When I try to delete a document I get the following error:
message: 'Cast to ObjectId failed for value "gl9-V-bjAjqv2Nwdf9vHPLN_Fnnl4Thz" at path "_id"'
express-session uses the following function to generate a session id:
function generateSessionId(sess) {
return uid(24);
}
The session generated from this function is making it way into the _id property of the sessions document. However when you try and find or delete the document by the generated id you get the error.
The mongodb docs say the _id should be
ObjectId is a 12-byte BSON type
ObjectId
I've tried to override the session id using the genid option on the session, but the override doesn't make it into the database.
How can I get a valid _id onto the document or query the document with an invalid _id?
Thanks!
My Infrastructure: Express 4.10, Node v0.12.7, Compose.io, connect-mongo, express-session
Okay so your problem here is the mongoose model you are using to delete documents from the session store. You probably should be calling req.session.destroy() or setting up TTL to remove expired sessions instead.
But basically, mongoose is expecting the "type" of the _id field to be an ObjectId and as such "autocasts". The mongo-connect middleware itself does not use mongoose methods, but talks to the underlying driver methods instead. So it does not have this problem when using it's internal methods.
Your mongoose schema definition should therefore look something like this:
var sessionSchema = new Schema({
"_id": String,
"session": String
},{ "_id" false });
Or at the very least contain { "_id": false } in order to remove the default autocasting behavior.

How can I generate an ObjectId with mongoose?

I'd like to generate a MongoDB ObjectId with Mongoose. Is there a way to access the ObjectId constructor from Mongoose?
This question is about generating a new ObjectId from scratch. The generated ID is a brand new universally unique ID.
Another question asks about creating an ObjectId from an existing string representation. In this case, you already have a string representation of an ID—it may or may not be universally unique—and you are parsing it into an ObjectId.
You can find the ObjectId constructor on require('mongoose').Types. Here is an example:
var mongoose = require('mongoose');
var id = mongoose.Types.ObjectId();
id is a newly generated ObjectId.
Note: As Joshua Sherman points out, with Mongoose 6 you must prefix the call with new:
var id = new mongoose.Types.ObjectId();
You can read more about the Types object at Mongoose#Types documentation.
You can create a new MongoDB ObjectId like this using mongoose:
var mongoose = require('mongoose');
var newId = new mongoose.mongo.ObjectId('56cb91bdc3464f14678934ca');
// or leave the id string blank to generate an id with a new hex identifier
var newId2 = new mongoose.mongo.ObjectId();
I needed to generate mongodb ids on client side.
After digging into the mongodb source code i found they generate ObjectIDs using npm bson lib.
If ever you need only to generate an ObjectID without installing the whole mongodb / mongoose package, you can import the lighter bson library :
const bson = require('bson');
new bson.ObjectId(); // 5cabe64dcf0d4447fa60f5e2
Note: There is also an npm project named bson-objectid being even lighter
With ES6 syntax
import mongoose from "mongoose";
// Generate a new new ObjectId
const newId2 = new mongoose.Types.ObjectId();
// Convert string to ObjectId
const newId = new mongoose.Types.ObjectId('56cb91bdc3464f14678934ca');

Resources