Retrieve unique ID from MongoDB using Express.js - node.js

I'm fairly new to MongoDB. My current code is as follows:
var app = express();
app.post('/myDB', function(req, res) {
console.log('POSTed data');
db.myDB.insert(req.body, function(err, doc) {
console.log(err);
res.json(doc);
});
})
I know that when data is inserted into MongoDB, a unique _id key:value pair is created. I would like to have access to this unique id upon data insertion.
But from what I know currently (admittedly not a whole lot), I would have to do an app.get('/myDB/:id')... (Or something similar) in order to access that unique identifier. Is there a way to do this without having to make an extra http request?

In MongoDB, with the Node.js driver, you can get the inserted id from the callback function's second parameter. The syntax is:
collection.insert(docs[[, options], callback])
where docs is a single document object or an array of documents, options is an options object and callback is a callback function to run after the record is inserted. The second paramter returns an array of documents inserted.
Thus you can retrieve the inserted id this way:
var app = express();
app.post('/myDB', function(req, res) {
console.log('POSTed data');
db.myDB.insert(req.body, {w:1}, function(err, doc) {
console.log("Record added as "+ doc[0]._id);
res.json(doc);
});
You can read more on the docs here.

Related

FindOne NODEJS mongoDB

I have this code that check for me if the token provided is valid or not, the code is working but the problem that it is returning wrong id, => it returns the first Id that he found in the database
the code that I'm using is this
const checkToken = async (req, res ,next) => {
const token= req.body.token //the token is mix of number and letters lenght (6)
User.findOne(token,
(err, user) => {
if (err) {
const error = new Error('Token not Found');
error.status= 406;
return next(err, error);
}else
{
res.send('/api/users/'+ user.id +'/update') // u need to mention user.id from DB
}
})
this is my image of the database :
I don't want to use the id to search the token , what I want is use the provided token and search in DB if it is found so I retrieve Id
According to MongoDB documentation that is the usual behavior of findOne method. When multiple documents satisfy the condition the function returns the first document that is written first. Reference
To check use find() and see all the documents it returns for the correct id and to use findOne make sure the token is unique for all the document.

How can I filter an array with the result of the mongoose query?

I would like to filter an array based on a mongoose query. However, I am relatively new to node.js and asynchronous programming. I am aware that Array.prototype.filter is a synchronous function and the mongoose queries are asynchronous.
When searching on this site I came across the following two solutions:
filtering an array with a function that returns a promise - but this looks quite complicated and I don't understand the concept yet.
how to wait for the result of a mongoose query? - at first this solution looks quite understandable, so I gave it a try
here is my example code based on the second approach:
exports.create = function(req, res) {
async.filter(req.body.data.entries, function(item, callback){
MyCollection.findOne({'_id': item.id}, function(err, doc) {
callback(err == null && doc != null);
});
},
function(results){
req.body.data = results
// default controller to create a document in Mongo DB
return controller.create(Model, req, res);
});
};
However, this does not seem to work. results does not correspond to a filtered list as described in the answer, but corresponds exactly to the result of the Boolean expression of the callback function. I also checked this in the current async documentation to see if anything has changed in the filter function, but didn't see any change.
Well, There is another way to do it. Instead of getting rows in async. You can get all the records filtered from database. There is a concept of $in in mongodb. You can use this to retrieve multiple records at a time with specific Ids. In your case, here is the exmaple
exports.create = function(req, res) {
var ids = []
req.body.data.entries.forEach(function (item) {
ids.push(item.id);
});
MyCollection.findOne({'_id': {$in: ids}}, function (err, docs) {
// here you have all your filter data
var myDocs = docs;
//Callback from here to return data
});
}

Are there other ways to update a document with Express and Mongoose without having to delete the _id property?

When I update a document with Express and Mongoose is the best practice to just delete the _id value and then save the document? Here is an example of the code I'm using.
exports.update = function(req, res, next) {
var data = _.extend(app.locals.crewListing, req.body);
data = data.toObject();
delete data._id;
app.locals.crewListing.save(function(err, result) {
if (err) return next(err);
res.json({
message: null,
data: result
});
});
};
I don't think so. You definitely need to make sure that _id property isn't changed while updating. The best way is,
if(data._id) {
delete data._id;
}
But I would prefer updating each field of the object individually instead of using .extend() function since you know what fields you are updating.

How to loop over mongodb array with express and monk to create a page for each element?

I am building a web app with express, nodejs and monk. I am trying to create a page for each element of an array in my mongodb database.
That data is already in the collection called collections with the key coll_list like so:
{ "_id" : ObjectId("53dbaefd3d85d57492506f1f"), "coll_list" : [ "data_pagename1",
"data_pagename2", "data_pagename3" ] }
I thought it might be possible to loop over all the elements in coll_list with something like:
router.get('/index', function(req, res) {
var db = req.db;
var collection = db.get('collections');
collection.find( "coll_list" , function(e,docs) {
for (elems in docs) {
res.render(elems, {
elems : docs
});
}
});
});
Any suggestions or help/pointers on how to do this would be greatly appreciated.
Use req.params
router.get('/coll/:id',
function(req,res){
//access the id by req.params.id
//req.params.id will essentially be the _id of the document
//use it to obtain data from mongoDB and render the page using that data
//From the front end you make the call to /coll/<ObjectId> like
// /coll/53dbaefd3d85d57492506f1f and you get that id in req.params.id and use it to
//render data specific to that _id.
});
Thus, using a single route you would be able to create a page for every item in coll_list

mongo on nodejs collection not found

I connect to a database and receive a client.
The next step is to create a collection (table).
db.createCollection("test", function(err, collection){ //I also tried db.collection(...
if(collection!=null)
{
collection.insert({"test":"value"}, function(error, model){console.log(model)});
}
else if(err!=null)
console.log(err);
});
Now I would have created a collection "test" as well as a document(row) "test" in it.
Next is to get the content of the collection:
db.test.find({}); //An empty query document ({}) selects all documents in the collection
Here I get the error: Cannot call "find" of undefined . So, what did I do wrong?
Edit: I connect to the database this way:
var mongoClient = new MongoClient(new Server("localhost", 27017, {native_parser:true}));
mongoClient.open(function(err,mongoclient){
if(mongoclient!=null)
{
var db = mongoclient.db("box_tests");
startServer(db);
}
else if(err!=null)
console.log(err);
});
In the mongo command line you can use db.test.find({}) but in javascript there is no way to replicate that interface so far (maybe with harmonies proxies some day).
So it throws an error Cannot call "find" of undefined because there is no test in db.
The api for the node.js driver of mongodb is like this:
db.collection('test').find({}).toArray(function (err, docs) {
//you have all the docs here.
});
Another complete example:
//this how you get a reference to the collection object:
var testColl = db.collection('test');
testColl.insert({ foo: 'bar' }, function (err, inserted) {
//the document is inserted at this point.
//Let's try to query
testColl.find({}).toArray(function (err, docs) {
//you have all the docs in the collection at this point
});
});
Also remember that mongodb is schema-less and you don't need to create the collections ahead of time. There are few specific cases like creating a capped collection and few others.
If you call db.test.find "next" after the db.createCollection block it ends up being immediately next before db.createCollection succeeds. So at that point, db.test is undefined.
Remember that node is async.
To get the results I believe you are expecting, db.test.find would have to be in the collection.insert callback where you're calling console.log(model).
db.createCollection("test", function(err, collection){
if(collection!=null)
{
// only at this point does db.test exist
collection.insert({"test":"value"}, function(error, model){
console.log(model)
// collection and inserted data available here
});
}
else if(err!=null)
console.log(err);
});
// code here executes immediately after you call createCollection but before it finishes
Checkout the node async.js module. Good writeup here: http://www.sebastianseilund.com/nodejs-async-in-practice

Resources