Mongodb custom object id - node.js

If I want to use custom object id(using firebase user uid) in a mongodb model, then do I have to do anything thing different in model declaration or at the time of saving instance of the model?

Yes it is perfectly fine to use firebase user uid for an object id, if some value is present in _id field of a document being stored, it is treated as objectId.
Just make sure every object has a unique _id as _id is indexed and is used as primary key.

Related

define primary key myself and prevent creating the _id in mongodb

I am two questions:
1- I want get by Id from database but operation is based on the key that is made automatically by MangoDB e.g _id. I want to search based on a field that I created myself e.g: id. for this porpouse I used following :
app.get('/:id',async(req,res)=>{
try{
const get=await product.findById({id:req.params.id});
res.json(get);
}
catch(err){
res.send(err);
}
});
and get following output:
{"stringValue":"\"{ id: '1' }\"","valueType":"Object","kind":"Number","value":{"id":"1"},"path":"_id","reason":{"generatedMessage":true,"code":"ERR_ASSERTION","actual":false,"expected":true,"operator":"=="},"name":"CastError","message":"Cast to Number failed for value \"{ id: '1' }\" (type Object) at path \"_id\" for model \"product\""}
when creating the database the fied _id is created by mongodb and know as key. What command should I use to prevent this field from being created? how do i define key field myself in database or select my own definition field as the primary key on which to search?
If you want to do that, you should use find method:
const get = await product.find({id:req.params.id});
I'm not sure, but I think that is not possible to avoid the creation of field _id in mongodb, although you can avoid the ObjectId type if you specify the field _id with a custom value (should be unique) when you insert the document.
But if you want to use a custom id value, you will need to use mongoose find method by you custom id as I indicated before. Since your custom id field should be unique you can use findOne in order to improve the performance of the query.

Generate a unique ObjectId for a collection

I would like to generate a unique ObjectId for a resource to give back clients with the nodejs mongodb driver.
IE:
var ObjectID = require('mongodb').ObjectID;
var objectId = new ObjectID();
Reading about an ObjectId it seems that there are some cases in which this id may not be unique. Even though this is extremely rare I still cannot take a chance on having a duplicate id.
Question #1, Using this driver is it possible (even though unlikely) to get a duplicate id doing this:
var objectId = new ObjectID();
Question #2 (if above is not 100% guarantee to give a unique id):
Does this driver guarantee that for a certain collection the ObjectId that is automatically created when a new document is inserted is unique? If yes, how? If yes, can I somehow duplicate that behavior when calling new ObjectID() myself without a collection?
If the driver or the mongo server ensures (100% of the time) that for a collection every new doc gets a unique id, I could always have a collection of just ids, then when generating a new, empty doc for that collection I would ensure I get a unique ObjectId. However seems like overkill to have another collection just to store ids.
That being said some might ask why not just generate the ObjectId in a collection and update that doc later with data. The answer is that in my case data may not ever come later and I don't want to implement logic to check for empty docs that only contain an id.
It's very unlikely that the same ObjectID will generate as mongo guarantees unique ID. objectID is created with a combination of two same values and two different values (unix epoch time, and a random value). However, in any case of a duplicate, you won't be allowed to insert a document as objectID acts as a primary key and insert function will return duplicate key error to your callback. Read more here. The same error is returned if mongo node native library creates a duplicate ObjectID.
UPDATE: again after reading the code base, if "hypothetically" the objectID that was generated by the library isn't unique, the answer is no. We are not ensured by the library that the id is unique, but we are ensured of a duplicate error doesn't matter who or what sent the id.
Here's the process:
1. generates ID
2. Sends straight to server.
3. Returns results.
Mongo isn't looping in nodeJS with existing ids because the library isn't storing it in cache. Read the code base for the library.

danger in using id property for Mongoose models?

Database design decision making here and there's no other way to do this but poll the experts on SO.
We are using the Mongoose ODM with Node.js Express. MongoDB uses _id as the default property on models which hold ObjectIDs unique to each document.
We are using an auto-incrementer which gives integer ids to each model. We want to call this field 'id' which will complement the '_id' field.
My concern is that there is a small risk that using an 'id' field will cause problems. Does anyone have experience positive or negative with using 'id' for integer ids on all their Mongoose models?
yes, be very careful. Mongoose by default adds a virtual property called "id" to your model. This virtual property returns the cast to String of the _id property.
If you really want to add a real property "id" to your model your must turn off this automatic virtual using the option: {id: false} in your new Schema() calls:
new Schema({name: String, id: int}, {id: false})
Be aware that even if this possible you will confuse every developer who knows mongoose when he reads your code by doing this.
Maybe better call your property differently.
Or when you create this incrementing id anyway as your primary key maybe you can assign it to _id directly because then there is probably no need to generate an additional ObjectId anyway... and the id property will then automatically return your integer as a String.

Manipulating ref'd mongo records based on _id field

Ok so I have a pretty simple DB setup in a MEAN app (node, mongoose, mongo) where I have Book records, and User records. A book has a single Owner, and can have any number of shared users which are stored in an array in a field called sharedWith:. Originally I was storing the user records with an email address as the _id field. I now realize this was a dumb move on my part because if someone wants to change their email address it effectively cuts them off from their books.
The app is not live yet, so it's not a fatal mistake.
My question is, once I revert the User documents to using the original hash value for _id, and store those in the Owner and sharedWith fields in the book documents, will I have to query each hash just to retrieve the actual usable user data?
I know mongoose has a .populate() method which will resolve sub documents, but as for inserting them? Will I POST the users as email addresses, then query each and store the resulting hashes? I can do this manually, but I wanted to make sure there is not some secret mongo-sauce that can do this in the DB itself.
Thanks!
If you have the _id available in the frontend for the user. You can directly share him a book by adding the _id to the sharedWith array of a book. But if you don't have the _id of the user available in the frontend, you need to manually get the _id by querying with the email and then store the _id in the sharedWith. As to retrieve the books, populate is indeed the best option to use to get user data.
And to get all books shared with a user you can do something like this,
Book.find({sharedWith:user1._id},function(err,docs){ });
This query can be made efficient if you use an index on sharedWith but that depends on your use case.

Mongoose create custom _id from other fields

I know that Mongoose populates the _id field automatically with an ObjectID if none is given and that you can overwrite the _id when constructing and instance of the model.
What I want: create the _id from other fields in a transparent way. I want to omit the _id field when creating an instance of the model and then have a function called which fills it. This function should be declared on a Schema level and whoever uses the model does not know that _id was filled by the function instead of Mongoose.
Is there a hook or a parameter of the Schema constructor I missed?
Mongoose 3.0.x
Let's make this more concrete. Imagine a BlogPost and I want to create nice URLs by slugging the title. In order to map the slug to a Mongo Object I hash the slug and turn it into a ObjectID to leverage it's benefits. Now what I'm looking for is a transparent method which allows me to create an instance of BlogPost by only passing in title and have the slug and _id property automatically generated.
use a setter on title which slugifies and idifies for you: https://gist.github.com/3658511
If you want to make sure your code is only executed once the object is created, check for this.isNew inside the setter.
Is this what you are looking for?
You could define a function to create the _id before the model is saved, as in:
http://mongoosejs.com/docs/middleware.html
If this middleware is called after Mongoose creates the _id by default (my guess is it's not), you could tell Mongoose to not create an _id, with the _id option.
http://mongoosejs.com/docs/guide.html#options

Resources