Why we use ObjectId(id) in Mongodb? - node.js

What is the purpose of using Object Id here?
app.get('/product/:id', async(req, res) => {
const id = req.params.id;
const query = { _id: ObjectId(id) };
const product = await productCollection.findOne(query);
res.send(product);
})

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 as default mongo use it as ObjectId.
So the purpose you parse the id it because id its a String and in you database _id it not a string it an ObjectId.
Note: if you are using mongoose you don't need to parse the id to ObjectId cause mongoose auto cast that field to ObjectId

Related

How to set a field value with same document id in mongoose

I want to create a schema on mongoose where a field value is the same as document id.
Desired output:
{
"_id": "61c75bf3b151c6c6854c83db",
"password":"some password",
"name":"some name",
"linkId": "61c75bf3b151c6c6854c83db"
}
Here document id and linkId is same. How can I do that when creating a new document? It maybe redundant but is it possible?
You can use pre-hook middleware for the save method, when you insert any document it will clone the _id field in to linkId field,
// SCHEMA
const SchemaObj = new mongoose.Schema(
// your schema...
);
// PRE MIDDLEWARE
SchemaObj.pre('save', function (next) {
this.linkId = this._id;
next();
});

How to prevent Mongoose findOneAndUpdate to add ObjectId automatically

I have a collection with the following document
{_id:'12345',account:{ba:0,br:0,ac:0}, scores:{a:0,b:0}}
I have a resolver and after running it
const input = {account:{ba:1,br:2,ac:3}, scores:{a:1,b:1}}
const profileId='12345'
const res = await modelProfile.findOneAndUpdate({ _id: profileId }, input);
it finds the document and properly changes it but it is adding also _id to each object there :
{_id:'12345',account:{_id:'46456',ba:1,br:2,ac:3}, scores:{_id:'4645677', a:1,b:1}}
How can I prevent mongoose from automatically adding _id to the SUBDOCUMENT objects of the document that they don't have ObjectId already. (as you saw, the document has ObjectId but objects inside as subdocuments does not have it)
I found the solution, I should change schema
var subSchema = mongoose.Schema({
// your subschema content
}, { _id : false });

Prevent _id field from being supplied in a MongoDB query

I'm using Mongoose in NodeJS to control a MongoDB database.
I'm creating an API and for obvious security reasons, I want to prevent the auto generated document _id field from getting replaced by a manually generated one in the API request.
Schema:
{ name: String }
Creating a document:
const record = {
_id: '5e35517cc894c90327a34baf'
name: 'bob'
}
const insertRecords = async () => {
await Quiz.create(record);
};
insertRecords();
Results in the following document:
{
_id: '5e35517cc894c90327a34baf'
name: 'bob'
}
As can be seen, the _id supplied in the query, as long as it's a valid ObjectID, would replace the _id that was supposed to be auto generated by mongo.
Is there a way to check if this _id field is in the query so that I can reject the API request? The .create method triggers the pre save middleware hook which would always have the _id of the final document so I cannot depend on it to know whether the _id was in the query or it's the auto generated one.
The only option I found is to disable the _id field altogether but this does not make sense.
Solution #1 - Use .create() method with an explicit object.
It's actually easier than you think. This is self-explanatory - we only define what we want to allow. Mongoose will ignore anything that's not in the object.
const record = {
_id: '5e35517cc894c90327a34baf'
name: 'bob'
}
const insertRecords = async () => {
await Quiz.create({
name: record.name // only allow names.
});
};
insertRecords();
Solution #2 - Define a function to clear unwanted objects.
You can define a helper function to clear out unwanted fields.
const filterObj = (obj, ...allowedFields) => {
const newObject = {};
// If the current field is one of the allowed fields, keep them in the new object.
Object.keys(obj).forEach((el) => {
if (allowedFields.includes(el)) {
newObject[el] = obj[el];
}
});
return newObject;
};
How to use:
const filteredRecord = filterObj(record, 'name'); // arbitrary list of allowed fields. In this case, we'll only allow 'name'.
await Quiz.create(filteredRecord);

Why can't I push to an array in Mongoose/Express with this code?

Here's my schema/model:
var todoSchema = new mongoose.Schema({
item: [String]
});
And here is the put method
app.put('/todo/:id', urlencodedParser, function(req, res) {
Todo.findByIdAndUpdate(req.params.id,
{ "$push": { "item": req.body } },
{ "new": true, "upsert": true },
function (err, data) {
if (err) throw err;
console.log(data);
}
);
});
What ought to happen is it grabs the id (:id), and finds the ID, and pushes req.body (Which is a string, an input from the web page) and pushes it on to the item array.
I am receiving the following error when this put is called:
CastError: Cast to ObjectId failed for value ":id" at path "_id" for model "Todo"
Which is strange, since I don't explicitly cast the id as an ObjectId when I use findById().
code is correct.i think may be your query id is not a valid objectId so that it cast the error..it must be string of 12 bytes..check it? if its correct means also check mongoose version, may be this also problem..so install the mongoose version 4
Mongoose's _id default type is ObjectId. This is why it happening you are passing _id to string value.
Mongoose's findByIdAndUpdate method casts the id parameter to the type of the model's _id field so that it can properly query for the matching doc. This is an ObjectId but "req.params.id" is not a valid ObjectId so the cast fails.
This doesn't happen with 59b67565c8745e27f9f3cf46 because that string is a valid ObjectId.
One way to resolve this is to add a check prior to your findByIdAndUpdate call to see if id is a valid ObjectId or not like so:
if (req.params.id.match(/^[0-9a-fA-F]{24}$/)) {
// Yes, it's a valid ObjectId, proceed with `findById` call.
}
Another way to do it that you can parse the string to ObjectId like:
ObjectId.fromString( req.params.id )

How to save to database with my custom _id? [duplicate]

This question already has answers here:
How to set _id to db document in Mongoose?
(4 answers)
Closed 5 years ago.
I want to save data to a database with my custom _id,
but I get an error: Cast to ObjectID failed for value...
I think that I shoyld convert my _id and then call the save() method.
Here is my code for this:
var uid = decodedToken.uid;
var body = _.pick(req.body, ['email' , 'fname', "lname", "providerID"]);
body._id = uid;
var userEX = new UserEX(body);
userEX.save().then( (user) => {
res.send(user);
}).catch( (err) => {
res.status(400).send(err);
});
Hope you can help me with that.
Thank you.
Your custom uid is not of type ObjectID.
By default Mongoose _id is of type ObjectID so they don't match.
You could specifically define _id in your schema to be the same type as your custom uid, for example:
var mySchema = new Schema({
_id: String,
// Other fields
});
However, it might be a better idea to leave the default _id as ObjectID and have a secondary uid field which you can use to query, etc.

Resources