REST API call using nodejs and mongodb - node.js

I am new to node.js. Following is my GET request:
router.get('/EPODS/Product/:id?', function(req, res) {
if(req.params.id){
var inputIdObj={'ProductEBM.DataArea.Product.ProductGroupID': req.params.id};
} else {
res.status(500).json({
"Error": "No input given Try give something or Check for the case sensitive in the input query fields"
});
res.end();
return;
}
db.collection('Product').findOne(inputIdObj,function(err, doc) {
if (err) {
console.log("No record found for the given input");
res.end("No record found for the input data- Please check again");
} else {
res.send(doc);
}
});
});
I am receiving null value when I hit the request in POSTMAN but the query works in MONGODB.
Please Help!
Thanks in Advance.

When you get the parameter of the GET request, you get the ID in a String format, which will not work if you use ObjectID. First, cast your param in ObjectID (you can import the object with require('mongodb').ObjectID) and so create: new ObjectID(req.params.id)

Related

Nodejs/Mongoose fetch individual data with routes. [MongoDB]

Im trying to find the cleartext for a certain hash with making a get including the hash in the link.
This code only fetches the data from the given id
router.get('/:id', async (req, res) => {
try {
const md5 = await MD5.findById(req.params.id)
res.json(md5);
} catch (err){
res.status(500).json({ message: err.message })
}
})
GET Request
http://localhost:3000/md5/5ecd8e223ec4a031bccb299b
Output
{"cleartext":"softking","hash":"1e055704bb253ab362b3563902e88fe8","_id":"5ecd8e223ec4a031bccb299b"}
My goal is to make a get request with a hash to find the cleartext instead of requesting with a id. Sorry that I can't explain better, Im a newbie in this.
First you need to pass the hash as a parameter to your get request. Then, you can use find method instead of findById provided by mongoose
router.get('/:hash', async (req, res) => {
try {
const md5 = await MD5.find({hash:req.params.hash});
res.json(md5);
} catch (err){
res.status(500).json({ message: err.message });
}
});

Bad Request error in uber api

I've been trying to get the uber price estimates endpoint working, but I'm stuck on an error that leads me to a blank page saying, "Bad Request." The console also says "callback not a function" but I can't seem to find out what is wrong.
My route:
// Get an upfront fare before requesting a ride
app.get('/v1.2/estimates/price', function(request, response) {
// extract the query from the request URL
var query = request.query;
// if no query params sent, respond with Bad Request
if (!query || !query.lat || !query.lng) {
response.sendStatus(400);
} else {
uber.estimates.getPriceForRouteAsync( {
"product_id": "33de8094-3dc4-4ca9-8f67-243275f57623",
"start_latitude": "38.9597897",
"start_longitude": "-94.60699369999999",
"end_latitude": "39.010969",
"end_longitude": "-94.61509899999999"
})
.then(function(res) {
log(res);
})
.error(function(err) {
console.error(err);
});
}
});
Any help is appreciated.
Please check out the README for node-uber. The method does not take a JSON object but the arguments in the method call:
uber.estimates.getPriceForRouteAsync(38.9597897, -94.606994, 39.010969, -94.615098)
.then(function(res) { console.log(res); })
.error(function(err) { console.error(err); });
Also, the product ID is not needed as the /estimates/price endpoint returns an array of estimates for each product.

KeystoneJS CloudinaryImage upload via API

There seems to be lack of documentation on this topic. I'm trying to upload an image and set it to avatar: { type: Types.CloudinaryImage } in my Keystone model.
I'm posting content as multipart form data with the following structure: avatar: <raw_data>. Here is how I handle this in my API:
exports.upload_avatar = function(req, res) {
if (!req.files.avatar) {
console.info('Request body missing');
return res.status(400).json({ message: 'Request body missing', code: 20 });
}
req.current_user.avatar = req.files.avatar;
req.current_user.save();
}
where current_user is a mongoose model. What I find confusing is how to set my CloudinaryImage type field to the data I receive in the API.
So, rather than just setting the avatar to the raw data (which would work fine for e.g. a string field), you'll need to go through the update handler, which calls to the {path}_upload special path in cloudinary image.
You should then be able to do avatar.getUpdateHandler, perhaps following this example.
I would like to share what worked for me. The process is kind of strange but by adding in this code, all of the model validation works just fine and cloudinary uploads are set.
post(req, res, next) {
const newBundle = new Bundle(); //A mongoose model
newBundle.getUpdateHandler(req).process(req.body, (err) => {
if (err) {
return res.status(500).json({
error: err.message,
});
}
return res.json(newBundle);
});
}
When posting to the endpoint, all you need to do is make sure you set your file fields to be {databaseFieldName}_upload.
Ok after some digging through the source code, I figured out a way to do that:
exports.upload_avatar = function(req, res) {
req.current_user.getUpdateHandler(req).process(req.files, {fields: 'avatar'}, function(err) {
if (err) {
return res.status(500).json({ message: err.message || '', code: 10 });
}
res.send('');
});
}
I had the following gotchas:
use getUpdateHandler to update CloudinaryImage field.
use "magic" naming for multipart form data fields you POST to your API: {field_name}_upload, which in my case would be avatar_upload.
process req.files, which is a dictionary with your field names as keys and your file data as values. req.body is empty due to some post-processing with multer.
invoke update handler on your keystone model (you need to fetch it with find first) rather than on a specific field. Then specify {fields: <>} to limit its scope, otherwise you could have some issues like validation errors trying to update the whole object.

Handling 503 Error in Express/Node.js especially in TryCatch case

I have a special case for which I want to clear the possible reason for 503 Error. The following code snippet has a catch statement which runs when system is not able to find any results
app.post('/api/fetch/user', function(req, res){
var email = req.body.emailTxt;
db.one('SELECT * FROM users WHERE email=$1', [email])
.then(function(data){
console.log('DATA:', data);
var userCard = { id: data.user_id, name: data.user_name,
email: data.email, regDate: data.date_created };
res.status(200).json({ 'valid': true, '_payload': userCard });
})
.catch(function(error){
if(error.search(/No data returned from the query/im) > 0) // regex case insensitive search and search multiline as source string is multiline
res.status(500).send('Invalid Request Match');
else
res.status(500).send('ERROR: '+error);
})
});
When my API call is made to this API end point and when no result found the control moves in catch() which is fine but quite strangely it returns 503 - Request timeout error.
I have tried to to remove conditions in if() in order to debug but seems like no matter what but the if-else does not seem working in ExpressJs.
Note: Everything works well and also when control stays in .then(). If I remove if,else and keep simple error display/response return then everything works ok. There is nothing special included in my API; it is only one single page script I prepared to test API.
I think you got error in the .catch block.
Try to modify the code and see if this helps:
app.post('/api/fetch/user', function(req, res){
var email = req.body.emailTxt;
db.one('SELECT * FROM users WHERE email=$1', [email])
.then(function(data){
console.log('DATA:', data);
var userCard = { id: data.user_id, name: data.user_name,
email: data.email, regDate: data.date_created };
res.status(200).json({ 'valid': true, '_payload': userCard });
})
.catch(function(error){
console.error(error); //never ignore errors!
try {
//i think error is an Error Object here, so it doesn't have .search function
if(error.search(/No data returned from the query/im) > 0) // regex case insensitive search and search multiline as source string is multiline
res.status(500).send('Invalid Request Match');
else
res.status(500).send('ERROR: '+error);
} catch (err) {
console.error(err);
res.status(500).send('some unknown error');
};
});
});
Edit: Sorry, removed .finally because you may send response twice.
Edit, better approach to handle error in .catch block.
//make catch block error safe to make sure no error occurs
if (error && error.message == 'No data returned from the query.') {
res.status(500).send('Invalid Request Match');
} else {
res.status(500).send('ERROR: '+error);
}
We use response codes in ExpressJs quite intensively when creating an API service. So it seems a right way that we make use of them directly instead of doing if-else in catch().
Hence, the right way would be:
.catch(function(error){
console.log('ERROR:', error);
res.status(204).send('No Content; Invalid Request Match');
})
However, If you want to display/return detailed message you can do that as well. You can check: http://expressjs.com/en/api.html#res for details on ways you can response back. You can render an HTML template, or return JSON response or even multiline text.
I don't know why if-else creates problem but you can go other way around.
In your specific case the error does not have .search() method attached to it. So better to parse it to string first using .toString();.

Marklogic nodejs Api error

I have the following marklogic rest-api url :
http://marklogicserver:8060/v1/search?format=json&options=optionname&q=question
This url send me results and format them according the optionname. Everything is ok.
Now I need to do the same work with Nodejs API :
I use a querybuilder to do the same thing but my results are never formatted according to optionname.
qb.optionsName = 'optionname';
//qb.search = {q: question};
db.documents.query(
qb.where(qb.parsedFrom(‘question’))
).result( function(results) {
results.forEach(function(document) {
console.log(JSON.stringify(document,null,2));
return document;
});
}).catch(function (error){
console.log(error);
});
Although I am sure that the optioname is the right one, the system returns the following error message:
[Error: query documents: response with invalid 400 status]
message: 'query documents: response with invalid 400 status',
statusCode: 400,
body:
{ errorResponse:
{ statusCode: 400,
status: 'Bad Request',
messageCode: 'REST-INVALIDPARAM',
message: 'REST-INVALIDPARAM: (err:FOER0000) Invalid parameter: No configured options: optionname' } }
You are not passing the querybuilder to the function but a query built by it. Try creating the query and then attaching the optionsName property like this:
var query = qb.where(qb.parsedFrom(‘question’))
query.optionsName = 'optionname';
db.documents
.query(query)
.result( function(results) {
results.forEach(function(document) {
console.log(JSON.stringify(document,null,2));
return document;
});
})
.catch(function (error){
console.log(error);
});
The QueryBuilder defines the query entirely in the client. This approach gives the application complete flexibility for dynamic construction of queries and avoids the housekeeping of maintaining persisted query options.
To use query options persisted on the server, you can instead define a combined query as a JavaScript object and identify the persisted query options in that object:
http://docs.marklogic.com/jsdoc/documents.html#toc14
However, the QueryBuilder alternative is recommended.
Hoping that clarifies,
Someone from marklogic gave me the good syntax:
my query.search was malformed, if it can help somebody.
var query = qb.where();
query.optionsName = 'optionsname';
query.categories = ['none'];
query.search = {
'options':{
'search-option':['unfiltered']
},
'qtext': 'q'
};
db.documents
.query(query)
.result( function(results) {
console.log(JSON.stringify(results,null,2));
})
.catch(function (error) {
console.log(error);
});
}
Thank you very much :)

Resources