Mongo Indexing - Nodejs - node.js

Im using the following schema and code to create collection in Mongo along with the Indexer and insert data. Please note that the collection is getting created dynamically based on the categoryName.
var employeeSchema = new mongoose.Schema({
categoryId : {type: String, required: true },
loc : {type: {lon: Number, lat: Number}, index: '2d'},
// createdBy : {type: String, required: true },
createDate : {type: Date, default: Date.now}
});
exports.register = function (objEmployee , callback)
{
var emp = db.model(objEmployee.categoryName, employeeSchema );
var objSchema = new emp(objEmployee);
objSchema.save(function (err) {
if (err) return callback(err);
console.info ('Data inserted successfully.');
return callback(null);
});
};
Im able to insert data but when I run the query based on the radious, when I run I get the following error.
Sat Sep 29 20:21:24 uncaught exception: error: {
"$err" : "can't find special index: 2d for: { loc: { $within: { $center: [ [ 50.9393925139, -114.0 ], 2.0 ] } } }",
"code" : 13038
Anything going wrong with in my code ?

I think your schema definition for loc is wrong. It should be
loc: {
lon: Number,
lat: Number
}
And after your schema definition add the index
employeeSchema.index({
loc: "2d"
});

Related

How to store reference data using mongoose refs?

I'm making a note app, each note will have multiple categories.
var NotesSchema = new mongoose.Schema({
title: String,
note: String,
favorite: {type: Boolean, default: false},
category: [{ type: mongoose.Schema.Types.ObjectId, ref: "categories" }]
},{ timestamps: { createdAt: 'created_at' } });
var Notes = mongoose.model('Notes', NotesSchema);
var CategoriesSchema = new Schema({
name: {type: String, required: true},
favorite: {type: Boolean, default: false},
})
var Categories = mongoose.model('Categories', CategoriesSchema);
I can do this with only one category but I don't know how it's done for multiple categories.
First I thought I need to store the categories, get each id and then store the note. Here's what I tried:
.get('/', (req, res) => {
var data = {
title : "scientific revolution",
note : " some note",
favorite : true,
category : [ 'science', 'books']
}
var catIds = [], seriesIds = [];
data.category.map(cat =>{
const category = new Categories({
name: cat
})
category.save((err,data)=>{
if(err) throw err;
catIds.push(data._id)
})
})
data.category = catIds;
const note = new Notes(data)
note.save((err, data)=>{
if(err) throw err;
res.json(data)
})
})
The catIds array never gets the ids!
I'm totally new at using references. Didn't even know they existed.
Your ref field should point to the model name not the table name.
In this case Categories.
I see you have write {ref: 'categories'} with small c but mongoose collection name is case sensitive and you should do {ref: 'Categories'}.
You can read more about mongoose case sensitivity in this post

node-mongo-native and mongo-shell return different results given the same query

Given the next code:
var daysToBeOld = 7;
var dateOlder = moment().subtract(daysToBeOld, 'days').toDate();
MongoClient.connect(mongouri, function(err, db) {
console.log('Filtering pending topics before: %s', dateOlder);
var conditions = {status: 'pending', updated: {$lt: dateOlder}};
console.log('Using the next filters: %j', conditions);
var topicsCol = db.collection('topics');
topicsCol.find(conditions).toArray(function (err, topics) {
if (err) {
console.log(err);
}
console.log("found %j topics", topics);
callback(err, topics);
});
});
I get the next console.log results. As you can see the result is an empty array:
Filtering pending topics before: Tue Feb 21 2017 15:13:35 GMT+0000 (UTC)
Using the next filters: {"status":"pending","updated":{"$lt":"2017-02-21T15:13:35.191Z"}}
found [] topics
If I execute the same query against mongo-shell it returns one document:
I.e:
> db.topics.find({"status":"pending","updated":{"$lt":"2017-02-21T15:13:35.191Z"}})
{ "_id" : "076bbbc0-e318-11e6-9375-e94b488c7ad8", "status" : "pending", "text" : "lalalalalla", "topicType" : "InformaciĆ³n", "member" : "NoUsuarioForus", "service" : "Limpieza", "idCard" : "", "receiveAnswer" : "1", "toc" : "1", "date" : ISODate("2016-08-31T16:36:45Z"), "sender" : { "name" : "alalalal", "email" : "alalalalala#lalalalal.com" }, "__v" : 0, "deleted" : false, "answered" : true, "firstAnswerTime" : 15614529, "updated" : "2016-02-01T17:28:34.868Z"
Why I'm getting no results in the query launched from node-mongo-native?
My node-mongo-native version is 2.2.24.
I've started using mongoose but switched to node-mongo-native to make this query because I was thinking that was an issue with mongoose. Btw I'm going to post my schema if it helps to clarify why it's not working:
topic.js:
var mongoose = require('mongoose');
var mongoosePaginate = require('mongoose-paginate');
var Schema = mongoose.Schema;
var uuid = require('node-uuid');
var xss = require('xss');
var TopicSchema = new Schema({
_id: {
type: String,
default: uuid.v1
},
status: {
type: String,
// open: When the message is created first time or not exists
// pending: The issue has been answered by some employee. Waiting for answer from the customer
// closed: The issue has been resolved
enum: ['open', 'closed', 'pending']
},
sender: {
name: String,
email: {
type: String,
required: true,
}
},
text: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
updated: {
type: Date
},
// If the topic is answered by an user different than creator it will be true
answered: {
type: Boolean,
default: false
},
firstAnswerTime: Number,
centerId: String,
topicType: String,
member: String,
service: String,
idCard: String,
receiveAnswer: String,
toc: String,
satisfaction: Number,
deleted: {
type: Boolean,
default: false
}
});
TopicSchema.plugin(mongoosePaginate);
TopicSchema.pre('save', function(next) {
this.updated = new Date();
this.text = xss(this.text);
next();
});
module.exports = mongoose.model('Topic', TopicSchema);
In the underlying collection, updated field is stored as a string and in your application you are querying it as a date, which won't yield anything but when you query it in mongo shell using a string it correctly returns the document.
Seeing that updated field is a string, try querying it as one i.e. changing the query variable to
var dateOlder = moment().subtract(daysToBeOld, 'days').toISOString();

mongodb schema.createIndex is not a function

So I am trying to create an index in my messageSchema
var messageSchema = new Schema({
senderName : String,
content : String,
reply : String,
date: { type: Date, default: Date.now() },
room : { type: Schema.Types.ObjectId }
});
// this is how to tried to create the index
messageSchema.createIndex({content : "text"}, function(err, data){
console.log(err);
console.log(data);
});
//Also tried
messageSchema.createIndex({content : "text"});
//tried this too
messageSchema.createIndex({"content" : "text"});
The error I keep on getting is
TypeError: messageSchema.createIndex is not a function
Can anyone help me with this.
It seems you are using mongoose. Under the hood,
Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.
In the mongo shell, collection.createIndex() works, but in mongoose you need to use mySchema.index(). Mongoose will do the work.
See here for more information: http://mongoosejs.com/docs/guide.html.
from mongoose:
var messageSchema = new Schema({
senderName : String,
content : { type: String, index: true },
reply : String,
date: { type: Date, default: Date.now() },
room : { type: Schema.Types.ObjectId }
});
messageSchema.index({content: 'text'});
The method you are looking for is called index, not createIndex

MongoDB join two collections using aggregation $lookup or populate in Node.js

Here are two collections' schema
var activitySchema = new Schema({
activity_id: {type: String, index: {unique: true}, required: true},
begin_date : String,
...
})
var registrationSchema = new Schema({
activity_id: {type: String, index: {unique: true}, required: true},
registration_id: {type:String, trim: true, index: true ,required: true },
email : String,
...
})
I want activity.begin_date , registration.id , registration.email in the same query. How can I do? I've found some solutions on the internet, but still don't know whether using populate or aggregation $lookup (this one seems new).
Here's how I tried, but not working at all.
models.Registration.aggregate([
{
$lookup: {
from: "Activity",
localField: "activity_id",
foreignField: "activity_id",
as: "activity_docs"
}
},
{"$unwind" : "activity_docs"},
], function( err , result ){
if(result){
fullDoc = result;
}else{
next( err );
}
})
activity_id should be ObjectId data type. ObjectId documentation
If you want to use pupoluate, you must to use ref to the other schema.
Population documentation
var activitySchema = new Schema({
begin_date : String,
...
})
var Activity= mongoose.model('Activity', activitySchema );
var registrationSchema = new Schema({
activity_id: {type: Schema.Types.ObjectId, ref : 'Activity', required: true},
email : String,
...
})
var Registration = mongoose.model('Registration', registrationSchema);
So the query such as :
var query = Registration.find({_id: 'registration_id parameter'});
query.select('_id activity_id email');
query.populate('activity_id','_id begin_date');
query.exec(function(error,result){
if(error){
/// handle error
}else{
// handle result
}
});

Mongoose + Expressjs - E11000 duplicate key error index?

I don't understand why I got this error below after adding the first entry:
E11000 duplicate key error index: mydb.datasets.$id_1 dup key: { : null }
I don't have any null value in my first entry:
{
"index" : "9IPZMW7IL",
"name" : "Tweets",
"owner_name" : "xxx",
"read_key" : "fb6f9125f4ca15c33fea89416c3351d1",
"write_key" : "d8a6c7e5fc73b5a91aa7a533565ed1f1",
"data" : {
"var1" : {
"name" : "particles"
}
},
"_id" : ObjectId("57729dc20cb70952424cdbb4"),
"created_at" : ISODate("2016-06-28T15:54:42.576Z"),
"entries_number" : 0,
"public" : true,
"__v" : 0
}
Below is my code:
// CRUD API:
// POST/ Create new dataset request
router.post("/", helper.authenticate, function(req, res) {
// Used to set the dataset owner
var sessionUser = req.session.user.name;
// Get values from the post request
var name = req.body.name;
var isPublic = req.body.public != undefined ? true:false;
// Delete the values from the request body so that we only keep information about the variables
delete req.body.name;
delete req.body.public;
// This is so that we can loop through the object in reverse order
// We do that so that the fields are saved in the right order on the db
// (this way it will appear in the right order on the 'edit' view)
var propertiesList = [];
for (var property in req.body) {
if (req.body.hasOwnProperty(property)) {
propertiesList.push(property);
}
}
propertiesList.reverse();
var variablesFields = {};
for (var i in propertiesList) {
console.log(propertiesList[i])
variablesFields[propertiesList[i]] = {name:req.body[propertiesList[i]],
values: Array};
}
// Create dataset
Dataset.create({
index: helper.uniqueIndex(),
name: name,
owner_name: sessionUser,
read_key: hat(),
write_key: hat(),
public: isPublic,
data: variablesFields
}, function(err, dataset) {
if (err) {
console.log("Error creating the dataset: " + err);
req.session.error = "A problem occured when creating the dataset. Please try again.";
} else {
console.log("New dataset created with id: " + dataset._id);
req.session.success = "Dataset " + name + " created successfully.";
}
res.redirect("/index");
});
});
Error:
Error creating the dataset:
WriteError({"code":11000,"index":0,"errmsg":"E11000 duplicate key
error index: mydb.datasets.$id_1 dup key: { : null
}","op":{"index":"2IPZMWHGI","name":"PM
2","owner_name":"xxx","read_key":"fc31c152aa86070252c70c0304e4ca5c","write_key":"238110753c8762ce4a547fa02100a299","data":{"var1":{"name":"particles"}},"_id":"57729dcf0cb70952424cdbb5","created_at":"2016-06-28T15:54:55.459Z","entries_number":0,"public":true,"__v":0}})
Model:
var datasetSchema = new mongoose.Schema({
index: {type: String, required: true, index: {unique: true}},
name: {type: String, required: true},
owner_name: {type: String, required: true},
read_key: {type: String},
write_key: {type: String},
public: {type: Boolean, default: false},
data: {type: Object},
entries_number: {type: Number, default: 0},
created_at: {type: Date, default: Date.now},
last_entry_at: {type: Date}
});
Any idea why and how I can fix this?
I solved it by removing a "id" key that I initially declared as
id: { type: String, unique: true, required: true},
I removed this line and deleted the initial collection and that solved the issue.

Resources