MongoDB indexing in Node.js - node.js

Hi I have the following code as part of my application in which I have to enable indexing
var db = mongoose.createConnection(config.database.address, config.database.dbName);
var testSchema = new mongoose.Schema({
status : String,
loc : {lon: Number, lat: Number },
createDate : {type: Date, default: Date.now}
});
exports.registerEmployee = function (objEmployee , callback)
{
var employee = db.model(objEmployee.categoryName, testSchema );
// Saves data
}
How to enable indexing for the above schema? Since the collection name (objEmployee.categoryName) is being created dynamically I'm kind of stuck here because for different category there will be a new collection get created. When we create new collection we have to enable Indexing also.
How to do this ?

The fact that the collection name is dynamic doesn't affect how you'd create an index on loc. You declare the index as part of the loc field definition of testSchema and Mongoose will take care of creating that index on each collection you register the schema for via db.model. As for the index definition, you can specify that right in the schema:
loc: {type: {lon: Number, lat: Number}, index: '2d'},

Related

Nested objects are not update

Allora, I'm using mongoose for the first time and I decided to create 2 schemes: the first one represents a user and the second one represents his enquires. Users have an array of enquires like:
var userSchema = new mongoose.Schema({
name: String,
enquires: { type : [Enquire.schema] , "default" : [] },
});
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
I see that if I search for an enquire and update its status, it doesn't update the same enquire on the user's array, meaning that they are different object. I don't want to save an array of IDs as it will be the same as a relational database, so I see only 1 solution which is forgetting about the enquire scheme and use only the User scheme. Is it the way mongoose works? For every relationship do I have to insert everything like nested object?
I think you should use references to achieve what you want to achieve.
For more information on mongoose references and populate see Mongoose Populate documentation.
Try this, It may help you.
User Schema :
var userSchema = new mongoose.Schema({
name: String,
enquires: [{ type : mongoose.Schema.Types.ObjectId , ref : 'Enquiry' }]//array of enquiries
});
var User = mongoose.model('User',userSchema );
module.exports = User;
Enquiry Schema :
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
var Enquiry = mongoose.model('Enquiry',enquireSchema );
module.exports = Enquiry ;
Working :
create a new Enquiry.
Push it's ID(_id) into user's enquires array.
var enquiry = new Enquiry();
enquiry.enquire = "Dummy enquiry";//set the enquiry
enquiry.save(function(err,result){
if(!err){
//push 'result._id' into users enquires array
}
});
whenever you update an enquiry, it will be automatically updated in
user's document.
use populate to retrieve user's enquiries.
You can embed sub documents (entity) which has id and is like a document or embed native array like a normal property.
And I think the correct definition for yours is :
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
var userSchema = new mongoose.Schema({
name: String,
enquires: { type : [enquireSchema] , "default" : [] },
});
If you use refs in embedded link then there are two separate collections and be like relational db's.

Deleted Unique Constraint in MongoDB create again with same name

During starting my project some how i define modal as unique in mongoose
let Say:
var CategorySchema = new Schema({
categoryName: { type: String, Unique: true},
discription:String
});
After some day a situation comes and i delete Unique key now my model is:
var CategorySchema = new Schema({
categoryName:String,,
discription:String
});
Now the real Problem is that when i publish and document inserted it still creates indexes of categoryName.
Want to know why this still create and how to recover from these error on production.

Mongoose error: nesting Schemas

I have a question about nesting Mongoose schema.
Here is a simple code snippet
var aSchema = new Schema({bar: String});
var bSchema = new Schema({a: aSchema, foo: String});
var cSchema = new Schema({as: [aSchema], foo:String});
This will throw TypeError on bSchema: TypeError: Undefined type at 's' Did you try nesting Schemas? You can only nest using refs or arrays., but works fine for cSchema.
Just want to ask why bSchema does not work. Cannot find explanation in Mongoose doc. Thanks.
MongoDB is not a relational database. This can cause confusion for some who are used to the RDBS model (I still get tripped up occasionally...but I'm really not a DB guy).
Oftentimes, you'll find it beneficial to reference other documents in your Mongo entities. Mongoose schemas provide a very simple and effective way to do this that feels very relational.
When defining a schema that will store a reference to a different type of document, you define the relevant property as an object with a type and a ref. Typically when defining schema properties, you can simply say: a: Number; however, Mongoose provides many different options for a schema property other than type:
a: {
type: Number,
required: true
}
Setting required: true will prevent us from saving a document where the a property is not present.
Once you understand how to define your schemas with object definitions, you can leverage Mongoose's population mechanic:
a: {
type: Mongoose.Schema.ObjectId,
ref: 'a'
}
This tells Mongoose to store the ObjectId (a Mongoose-specific identifier) of a specific a document as the a property of our schema. Still following me?
When setting this property on a Mongoose document, you can simply say: doc.a = myA. When you go to save doc, Mongoose will automagically make the conversion and only store the ID in your database.
When retrieving a document that references another schema, you'll need to populate. I won't go into that, but its pretty simple - check out the documentation.
I was facing this issue as I was completely new to the MongoDB. Later I found we need to use the relationship as below with the help of Mongoose.
Below is my country schema.
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var ObjectId = Schema.Types.ObjectId;
var CountrySchema = new Schema({
name: { type: String, required: true },
activeStatus: Boolean,
createdOn: Date,
updatedOn: Date
});
And I can use this schema in my State schema as follows.
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var ObjectId = Schema.Types.ObjectId;
var StateSchema = new Schema({
name: { type: String, required: true },
country: {type: ObjectId, ref: "Country"},
activeStatus: Boolean,
createdOn: Date,
updatedOn: Date
});
Here I am using pointing to my other schema with the help of ref.

Mongoose custom schema type date interval

I have many fields in my documents of type date intervals, such as this
{
publishDate:
{
start: {type: Date, required: true},
end: {type: Date, required: true}
}
}
To reduce duplication of the code and make it easier to maintain, how to create custom Mongoose type, for instance DateInterval, containing two fields:
start
end
and containing validator that makes sure both fields are filled out, and start is before end?
You can reuse schemas in mongoose.
var DateIntervalSchema = new Schema({
start: {type: Date, required: true},
end: {type: Date, required: true}
});
var SomeSchema = new Schema({
publishDate: [DateIntervalSchema],
// ... etc
});
You can also reference documents from other collections.
var SomeSchema = new Schema({
publishDate: {type: Schema.ObjectId, ref: 'DateInterval'}
});
//using populate
SomeModel.findOne({ someField: "value" })
.populate('publishDate') // <--
.exec(function (err, doc) {
if (err) ...
})
You'll want to develop a custom schema type. There are a number of plugins that do this already, one of which, for long numbers, can be found here: https://github.com/aheckmann/mongoose-long/blob/master/lib/index.js . This is a good basic example to follow.
For your purposes, then, you can create a DateInterval custom schema, casting it as type Date, and then use a validator to check start and end - http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate.
Since mongoose >=4.4 you can implement your custom schema type.
Documentation is not very clear, but you can follow this example.
You have to:
define your DateInterval custom object with toBSON() / toJSON() and toObject() prototype methods
define the DateIntervalType inherited from mongoose.SchemaType for handle the mongoose integration, and casting to DateInterval.
In this way you can achieve full control on memory (Mongoose model) and mongodb (raw's bson) data representation.

Mongoose sort by child value

I have a parent and child schema that looks like:
schedule = Schema ({
from: Date,
to: Date
});
content = Schema ({
schedule: { type: Schema.ObjectId, ref: "schedule" }
name: String
});
My question is, how do I query Mongoose to return "all content, sorted by schedule.from date"?
You'll need to sort in two steps on the client, or store the date fields you want to sort on as embedded fields within the content object.
You're trying to do a collection join by using data from two collections. As MongoDB doesn't support a join, you'd need to populate the schedule field and then do a sort locally on the client. If you have very many documents, or want to do paging of data, this of course won't work.
The most efficient means would be to store the date fields in the content model so that you can perform sorting directly from a single document and collection, without the need of a join. While that may cause other issues with the schema design that you'd like to have, you may find this is the most efficient. The benefit of this denormalization process is that you can do sorting, filtering, etc. very easily and efficiently (especially if you've indexed the date fields for example).
schedule = Schema ({
from: Date,
to: Date
};
content = Schema ({
schedule: { type: Schema.ObjectId, ref: "schedule" },
schedule_data: {
from: Date,
to: Date
},
name: String
});
You could leave the schedule field in the content schema if you wanted to be able to quickly locate and update content documents (or if there were other less used or not needed for sorting/filtering).
In your case, you don't need a reference from one collection to another simply to store schedule.from & schedule.to.
Try the following :
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback () {
console.log('Mongoose connected to MongoDB\n');
content_sch = Schema ({
schedule: {
from: Date,
to: Date
},
name: String
});
var content = mongoose.model('content', content_sch);
contentObj = new content();
contentObj.schedule.from = Date.now();
contentObj.schedule.to = Date.now();
contentObj.name = 'Ryan Rife';
contentObj.save();
//Sorting; -1 to specify an ascending or 1 descending sort respectively
content.find({}).sort({'schedule.from': -1}).exec(function(err,contentDocs){
console.log(contentDocs);
});
});
You can do sorting in many ways another one is as follows which you could try:
content.find({}, null, {sort: {schedule.from: -1}}, function(err, contentDocs) {
//console.log(contentDocs);
});
Check this for more info
When to go for references to documents in other collections?
There are no joins in MongoDB but sometimes we still want references to documents in other collections (schema). Only then you need to use the ObjectId which refers to another schema and from that schema back to the parent.Example:
var personSchema = Schema({
_id : Number,
name : String,
age : Number,
stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }] //Here is a link to child Schema 'Story'
});
var storySchema = Schema({
_creator : { type: Number, ref: 'Person' }, //Field which again refers to parent schema 'Person'
title : String,
fans : [{ type: Number, ref: 'Person' }] //Array which again refers to parent schema 'Person'
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
For more info check this mongoose populate docs

Resources