How to assign an id value in mongodb? - javascript

I'm working with node.js and mongoose. I'm creating a REST API to expose my User model:
var userSchema = new Schema({
_id: {type:Number},
username: {type:String},
age: {type:Number},
genre:{type: Number,ref:'Genre'},
country: {type: Number,ref:'Country'}
});
As you can see I decided to include an _id field, so if I want to create a new user I'll need to generate the value for this field, for example:
exports.createUser = function(req,res){
var user = new User({
_id: //Generate and assing value here
//Other properties are retrieved from the request object
});
};
How could I "generate" or assign a value to my _id field properly? How does mongo deals with this?

I never used mongoose. but if _id is not included in insert query, mongodb driver will generate _ids for you as an ObjectId object. and if you wish to use your own _ids, it's up to you to decide about its type and length, and also you have to guarantee its uniqueness among the collection because any attempt to insert a document with a duplicated _id will fail.
accepted answer of this question may be useful, if you are looking for a method for creating custom _ids that provides a decent degree of guaranteed uniqueness.

mongoDB requires that _id, if supplied, be unique. If _id is not supplied, it is created by the client-side driver (i.e. NOT the mongod server!) as a 12-byte BSON ObjectId with the following structure:
4-byte value representing the seconds since the Unix epoch,
3-byte machine identifier,
2-byte process id, and
3-byte counter, starting with a random value.
more info available here: http://docs.mongodb.org/manual/reference/object-id

Related

Mongoose creating new document duplicate key possibility?

If I define a model in mongoose, and create a document using something like the code below:
const Model = require("./Model")
const newModelItem = new Model({
...data
})
await newModelItem.save()
I noticed that there is an ID field immediately available in the newModelItem object.
How does MongoDB ensure that the key isn't a duplicate?
Actually that's MongoDB's work to generate (automatically) unique 12-bytes / 24 hex digits IDs. Please have a look at its structure and how it is being created:
Source: MongoDB ObjectId generation

Incrementing index in mongo db

When adding a field called date in mongo db, I can do just:
date: {
type: Date,
default: Date.now
}
and it will automatically add date field to my new collection when it was created. Is there some way to add a self-incrementing index (id) to my collections?
Note: I tried to do it on client side, however with every time I push collection with (id) field, its being deleted from the collection and replaced with _id which is a long string with random characters. Way to long!
Looking for every hints.
Edit: code responsible for adding use to db
app.post("/users", function (req, res) {
createUser(req.body, function (err, user) {
if (err) {
return res.json(err);
}
return res.json(user);
});
});
MongoDB automatically makes unique ids for each object in the database, resulting in each entry having a unique _id field being an ObjectId. You don't really need to worry about specifying custom ids.
You can sort by _id if you want objects roughly in the order they were created, or you could add a date field which is set on creation and sort by that.
Other than that, I'm not sure what you'd gain by having auto incrementing ids
There are multiple ways to implement an auto-increment index but it is not considered a good practice.
Detailed information here: Auto increment in MongoDB to store sequence of Unique User ID
Check Rizwan Siddiquee answer about how to implement it with a stored javascript function.
Another way would be to implement it on application layer using any kind of ODM but this is obviously dangerous and not so trustable for serious applications.

How to track increase of number attribute in given time range with expressjs and mongodb?

I'm using Express and Mongoose/Mongodb to create an API.
I have a model in mongoose representing apps(basic schema given below).
/* In apps collection */
app = {
_id: ObjectID,
createdAt: Date,
name: String,
numberOfDownloads: Number,
downloadLink: String
/* More object data */
}
When an app is downloaded, the numberOfDownloads attribute is incremented and this functionality already exists. How do I keep track of apps whose numberOfDownloads attribute has increased the most in a given time range? Let's say in the last 24 hours.
One way that I've thought of is to have a background job running and saving in a different collection named indexedAppDownloads every few hours objects with appId and numberOfDownloads attributes. And another collection named popularApps having only the most popular apps.
/* In indexedAppDownloads collection */
indexedAppDownload = {
appId: ObjectId,
_id: ObjectId,
createdAt: Date,
numberOfDownloads: Number
}
So the current numberOfDownloads attribute in apps collection is checked against that in the indexedAppDownloads collection using appId to find the app and where the difference is highest, apps are selected and stored in the popularApps collection after deleting everything there. This is done every few hours or once in a given time range.
Is there a better approach to this than what I plan to do?

How to query meteor-mongo on value, not _id or key

I am creating a meteor app that gets sensor data from remote devices via POST, and need to query on a value in a mongo collection, returning the document _id.
The document is similar to this:
[{
_id: 0,
device: {
mac: 'XXX', // always unique
sd1: nnn,
sd2: nnn,
...
}
}]
I need to be able to do a findOne() on XXX, determine if it exists, and get the _id of the corresponding doc.
I've tried variations of collection.findOne({}, {mac: 1}), but that only returns the first document that contains the key 'mac'. As every doc will contain that key (but the value will always be unique), this is pretty useless as it always returns the first document in the collection. I need to query on the value of the key.
There must be a very obvious solution, but it has eluded me thus far.

Mongoose - recursive query (merge from multiple results)

I have the following generic schema to represent different types of information.
var Record = new Schema (
{
type: {type: String}, // any string (foo, bar, foobar)
value: {type: String}, // any string value
o_id: {type:String}
}
);
Some of the records based on this schema have:
type="car"
value="ferrari" or
value="ford"
Some records have type "topspeed" with value "210" but they always share o_id (e.g. related "ferrari has this topspeed"). So if "ferrari has top speed 300", then both records have same o_id.
How can I make query to find "ferrari with topspeed 300" when I don't know o_id?
The only solution I found out is to select cars "ferrari" first and then with knowledge of all o_id for all "ferrari" use it to find topspeed.
In pseudocode:
Record.find({type:"car", value:"ferrari"}, function(err, docs)
{
var condition = [];// create array of all found o_id;
Record.find({type:"topspeed", value:"300"}...
}
I know that some merging or joining might not be possible, but what about some chaining these conditions to avoid recursion?
EDIT:
Better example:
Lets imagine I have a HTML document that contains DIV elements with certain id (o_id).
Now each div element can contain different type of microdata items (Car, Animal...).
Each microdata item has different properties ("topspeed", "numberOfLegs"...) based on the type (Car has a topspeed, animal numberOfLegs)
Each property has some value (310 kph, 4 legs)
Now I'm saving these microdata items to the database but in a general way, agnostic of the type and values they contain since the user can define custom schemas from Car, to Animal, to pretty much anything). For that I defined the Record schema: type consists of "itemtype_propertyname" and value is value of the property.
I would eventually like to query "Give me o_id(s) of all DIV elements that contain item Ferrari and item Dog" at the same time.
The reason for this general approach is to allow anyone the ability to define custom schema and corresponding parser that stores the values.
But I will have only one search engine to find all different schemas and value combinations that will treat all possible schemas as a single definition.
I think it'd be far better to combine all records that share an o_id into a single record. E.g.:
{
_id: ObjectId(...),
car: "ferarri",
topspeed: 300
}
Then you won't have this problem, and your schema will be more efficient both in speed and storage size. This is how MongoDB is intended to be used -- heterogenous data can be stored in a single collection, because MongoDB is schemaless. If you continue with your current design, then no, there's no way to avoid multiple round-trips to the database.

Categories

Resources