How to retrieve document in mongoose - node.js

I have multiple document in collection having a long string in each document, I want to retrieve one document at time, I dont have anything in document except long string, how can I retrieve that?
I inserted all document in collection using insertMany(), here is my code and output when I retrieved all document
var schema = new mongoose.Schema({
question : String,
id: Number
})
var quizz = mongoose.model('Quiz', schema );
var firstDoc = new quizz({
question: 'question 1',
id: 1
})
var secondDoc = new quizz({
question: 'question 2',
id: 2
var question_data = [firstDoc, secondDoc];
quizz.insertMany(question_data, function(err, res){
if(err){
console.log("error occured while saving document object " + err )
}else{
console.log("saved data");
}
})
quizz.findOne({id : '1'}, function(err, res){
if(err){
console.log(err)
}else{
console.log(res);
}
})

insertMany Will return you the list of _ids that have been created for your documents you've inserted. You can then pull out each document based on the _ids individually
quizz.insertMany(question_data, function(err, res){
if(err){
console.log("error occured while saving document object " + err )
}else{
console.dir(res); // res has the _ids.
console.log("saved data");
}
})
http://mongoosejs.com/docs/api.html#model_Model.insertMany
Alternatively if you always want to ensure ordering you could add a sequence column to the question, and/or put all questions inside one quizz.

if you want to do something with the _id of the documents that was inserted into the collection then use the answer of Kevin, but if you want to just do something with them later, you can use .find() which return you all the documents that are in the collection.
quizz.find(function(err, docs) {
//docs = array of all the docs in the collections
})
if you want specific by id:
quizz.findOne({_id: id},function(err, doc) {
//doc = the specific doc
})
if you want specific by strong
quizz.findOne({question: "question 3"},function(err, doc) {
//doc = the first (!!!) doc that have question in his `question` attribute
})
or if you want all the docs that have question 3 in them:
quizz.find({question: "question 3"},function(err, docs) {
//docs = array with all the docs that have "question 3" there, (return array even if only 1 found)
})

Related

mongoose findOne data does not exit not working

user_id 2 does not exist in mongodb but console log does not print 'does not exist'
var query = PostData.findOne({ 'user_id': '2'});
query.exec(function (err, doc) {
if(doc) {
console.log('ok');
} else {
console.log('does not exist');
}
});
Without mongoose it works:
connection.db.collection("PostData", function(err, collection){
collection.find({ 'user_id': '2'}).toArray(function(err, data){
console.log(data); // it will print your collection data
})
});
prints []
No matter an object exists or not , MongoDB is going to return an array anyway. If the object exists, they array will be filled with it otherwise it's just an empty array. So if you want to check if the user exists or not you must check for doc.length , if it's 0 then it means the user doesn't exist.

Mongoose $addToSet return new list entrys

I have a question working with mongoose 4.0.1
I am trying to add new picture objects to an array inside a model. This is the code of my endpoint that is actually doing the job:
// Add new images
exports.pictures = function(req, res) {
Incident.findByIdAndUpdate(
req.params.id,
{$addToSet: {"pictures": {$each: req.body}}},
{new: true},
function(err, incident) {
if (err) { return handleError(res, err); }
return res.send(201).json(incident.pictures);
}
);
};
The problem: The callback object (incident) stores all information of the model which was found and updated. But I want to return only the new array entries which were created.
How can I receive the actual changes of the operation instead of the whole object that is storing the pictures array?
I solved the problem by creating a new schema for pictures and adding a reference to the incident model.
The endpoint changed as well:
Create new picture instances for a array of pictures
Find incident by id
Save the references of the picture instances to a array inside the incident
Return the id of the picture instances
var _ = require('lodash');
// Add new images
exports.pictures = function(req, res) {
Picture.create(req.body, function(err, pictures) {
if (err) { return handleError(res, err); }
Incident.findByIdAndUpdate(
req.params.id,
{$addToSet: {"pictures": {$each: pictures}}},
function(err) {
if (err) { return handleError(res, err); }
var pictureIds = _.map(pictures, '_id');
return res.status(201).json(pictureIds);
}
);
});
};

MongoDB node native driver creating duplicate documents

I'm getting a duplicate document when using the mongodb-native-driver to save an update to a document. My first call to save() correctly creates the document and adds a _id with an ObjectID value. A second call creates a new document with a text _id of the original ObjectID. For example I end up with:
> db.people.find()
{ "firstname" : "Fred", "lastname" : "Flintstone", "_id" : ObjectId("52e55737ae49620000fd894e") }
{ "firstname" : "Fred", "lastname" : "Flintstone with a change", "_id" : "52e55737ae49620000fd894e" }
My first call correctly created Fred Flinstone. A second call that added " with a change" to the lastname, created a second document.
I'm using MongoDB 2.4.8 and mongo-native-driver 1.3.23.
Here is my NodeJS/Express endpoint:
app.post("/contacts", function (req, res) {
console.log("POST /contacts, req.body: " + JSON.stringify(req.body));
db.collection("people").save(req.body, function (err, inserted) {
if (err) {
throw err;
} else {
console.dir("Successfully inserted/updated: " + JSON.stringify(inserted));
res.send(inserted);
}
});
});
Here is the runtime log messages:
POST /contacts, req.body: {"firstname":"Fred","lastname":"Flintstone"}
'Successfully inserted/updated: {"firstname":"Fred","lastname":"Flintstone","_id":"52e55737ae49620000fd894e"}'
POST /contacts, req.body: {"firstname":"Fred","lastname":"Flintstone with a change","_id":"52e55737ae49620000fd894e"}
'Successfully inserted/updated: 1'
Why doesn't my second update the existing record? Does the driver not cast the _id value to an ObjectID?
What you are posting back the 2nd time contains a field named "_id", and it's a string. That is the problem.
Look at the document, what the save method does is a "Simple full document replacement function". I don't use this function quit often so here's what I guess. The function use the _id field to find the document and then replace the full document with what you provided. However, what you provided is a string _id. Apparently it doesn't equal to the ObjectId. I think you should wrap it to an ObjectId before passing to the function.
Besides, the save method is not recommended according to the document. you should use update (maybe with upsert option) instead
I don't exactly know why a second document is created, but why don't you use the update function (maybe with the upsert operator)?
An example for the update operation:
var query = { '_id': '52e55737ae49620000fd894e' };
db.collection('people').findOne(query, function (err, doc) {
if (err) throw err;
if (!doc) {
return db.close();
}
doc['lastname'] = 'Flintstone with a change';
db.collection('people').update(query, doc, function (err, updated) {
if (err) throw err;
console.dir('Successfully updated ' + updated + ' document!');
return db.close();
});
});
And now with the upsert operator:
var query = { '_id': '52e55737ae49620000fd894e' };
var operator = { '$set': { 'lastname': 'Flintstone with a change' } };
var options = { 'upsert': true };
db.collection('people').update(query, operator, options, function (err, upserted) {
if (err) throw err;
console.dir('Successfully upserted ' + upserted + ' document!');
return db.close();
});
The difference is that the upsert operator will update the document if it exist, otherwise it will create a new one. When using the upsert operator you should keep in mind that this operation can be underspecified. That means if your query does not contain enough information to identify a single document, a new document will be inserted.

Mongoose searching FindOne with multiple arguments

My first attempt at building something with Angular + express + mongodb, so I'm probably going about this completely the wrong way. Express is being used to serve up json. Angular then takes care of all the views etc.
I'm using Mongoose to interact with Mongo.
I have the following database schema:
var categorySchema = new mongoose.Schema({
title: String, // this is the Category title
retailers : [
{
title: String, // this is the retailer title
data: { // this is the retailers Data
strapLine: String,
img: String , // this is the retailer's image
intro: String,
website: String,
address: String,
tel: String,
email: String
}
}
]
});
var Category = mongoose.model('Category', categorySchema);
and in Express I have a couple of routes to get the data:
app.get('/data/categories', function(req, res) {
// Find all Categories.
Category.find(function(err, data) {
if (err) return console.error(err);
res.json(data)
});
});
// return a list of retailers belonging to the category
app.get('/data/retailer_list/:category', function(req, res) {
//pass in the category param (the unique ID), and use that to do our retailer lookup
Category.findOne({ _id: req.params.category }, function(err, data) {
if (err) return console.error(err);
res.json(data)
});
});
The above works - I'm just having big problems trying to get at a single retailer. I'm passing the category, and retailer id through... I've tried all sorts of things - from doing a find on the category, then a findOne on the contents within... but I just cant get it to work. I'm probably going about this all wrong...
I found this thread here: findOne Subdocument in Mongoose and implemented the solution - however, it returns all my retailers - and not just the one I want.
// Returns a single retailer
app.get('/data/retailer_detail/:category/:id', function(req, res) {
//pass in the category param (the unique ID), and use that to do our retailer lookup
Category.findOne({_id: req.params.category , 'retailers.$': 1}, function(err, data) {
console.log(data);
if (err) return console.error(err);
res.json(data)
});
});
Thanks,
Rob
Now that I see your full filter/query, you should be able to use the array positional operator in this case as part of the projection rather than doing client side filtering:
app.get('/data/retailer_detail/:category/:id', function(req, res) {
//pass in the category param (the unique ID), and use that to do our retailer lookup
Category.findOne({
/* query */
_id: req.params.category ,
'retailers._id' : req.params.id
},
{ /* projection */
"retailers.$" : 1
},
function(err, data) {
var retailer = _.where(data.retailers , { id : req.params.id });
if (err) return console.error(err);
res.json(retailer)
});
});
For the { "retailers.$" : 1 } to work properly, the query must include a field from an element in the array. The $ operator returns the first match only.
The guys next door use Mongo + Express and gave me some pointers: they explained to me how mongo worked, and advised I should use underscore.js to assist with my filter.
They said I needed to pull the entire category out - and then run the filter. I don't strictly need , 'retailers._id' : req.params.id} but they said to leave it in as it guaranteed that the category would only be returned if an item within it contained that information. I still don't really know why or how... So can't really mark this as solved.. it it solved, but I don't really get why as yet - so will do more reading :)
app.get('/data/retailer_detail/:category/:id', function(req, res) {
//pass in the category param (the unique ID), and use that to do our retailer lookup
Category.findOne({_id: req.params.category , 'retailers._id' : req.params.id}, function(err, data) {
var retailer = _.where(data.retailers , { id : req.params.id });
if (err) return console.error(err);
res.json(retailer)
});
});

How to update document in mongo with nested schema

I have the following code:
add_new_patient : function(username,pname,pid,pdesc,callback){
var find_md = function(){
return function(err,pat){
if (err){
console.log('Error at adding patient: error at searching for users');
callback(2);//In the callback method I'm passing I have specific behavior for error handling for error codes.
return;
}
if (pat.lenth > 0){
console.log('searching for md');
MD.find({'mdname':username},add_patient(pat));
}else{
console.log('Error at adding patient: no user found');
callback(-1);
return;
}
}}
var add_patient = function(pat){
return function(err,md){
if (err){
console.log('Error at adding patient: cannot find md');
callback(-1);
return;
}
callback(0);
}
}
console.log('searching for user '+pid);
User.find({'name':pid},find_md());
}
And these are my schemas:
var mdSchema = mongoose.Schema({
mdname : String,
pacients : [userSchema.ObjectId]
});
var userSchema =mongoose.Schema({
name : String,
password : String,
phone : String,
history : [{timestamp: Date , heart: Number }],
md : {mdname: String, contact: Number}
});
As you can guess from the code I want to add patients to the dms. First I search for the pid in the database. If I find a patient I start to look for mds. When I find the md I want to add the patient to the md. Now I don't know how to add them. The schema shows that I have an array of schemaUser, which is the type of patient, but I don't know how to append to it, not how to create an MD model from object from the data I received from the query. Also what should I insert into the array of patients? The _id of the found patient or the whole object?
I managed to solve it in the following way:
var add_patient = function(pat){
return function(err,md){
if (err){
console.log('Error at adding patient: cannot find md');
callback(-1);
return;
}
var query = {mdname: md.mdname};
console.log(md);
var doThis = { $addToSet: { patients: pat._id } };
console.log(query);
MD.update(query,doThis,done_adding());
}
}
var done_adding = function(){
return function(err,dat){
if (err){
console.log('Error at the end of adding new patient!');
callback(-1);
return;
}
console.log('new patient added');
callback(0);
}
So what this does is: when I have the md to whom I want to add a patient/user I use the update method, with the $addToSet operation so I will have a set of patients associated with an md. I don't know why, but the same code did not work for me with the $push parameter. Then simply nothing happened and when I set the upsert option to true my whole record in the database was overwritten by the id.

Resources