I am trying to make individual API get requests in server.js but I don't get the desired results. The error that I get in Postman is as followed:
objectId.isValid is not a function in making API request
Here is the code of server.js:
var express=require('express');
var bodyParser=require('body-parser');
var ObjectID = require('mongodb');
var mongoose=require('./db/mongoose');
var Todo=require('./models/todo');
var User=require('./models/user');
var app = express();
app.get('/todos/:id', (req, res) => {
var id=req.params.id;
if (!ObjectID.isValid(id)) {
return res.status(404).send();
}
Todo.findById(id).then((todo) => {
if (!todo) {
return res.status(404).send();
}
res.send({todo});
}).catch((e) => {
res.status(400).send();
});
});
Note: This is answered in the comments. Writing a detailed answer to help completeness of this post.
ObjectID is a property of the object returned by require('mongodb'), which is why var ObjectID = require('mongodb').ObjectID works fine.
If you switch to ES6, object destructuring assignment comes handy.
const { ObjectID } = require('mongodb');
http://mongodb.github.io/node-mongodb-native/3.0/api/ObjectID.html
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
Related
I am building out an API using Node for the first time but a little stuck on something.
I have the following files:
My routes, routes/index.js:
const express = require('express');
const router = express.Router();
const transactionsController = require('../controllers/transactionsController');
const ordersController = require('../controllers/ordersController');
const ordersCountController = require('../controllers/ordersCountController');
router.get('/transactions', transactionsController);
router.get('/orders', ordersController);
router.get('/orders_count', ordersCountController);
module.exports = router;
My controllers, controllers/ordersCountController.js:
const ordersCountService = require('../services/ordersCountService');
const ordersCountController = async () => {
try {
const data = await ordersCountService();
console.log(data);
return data;
} catch(err) {
console.log(err);
}
};
module.exports = ordersCountController;
My service to fetch from an external API, services/ordersCountService.js:
const fetch = require('node-fetch');
const ordersCountService = async () => {
const URL = ....;
const settings = { method: 'Get'};
const res = await fetch(URL, settings);
if (!res.ok) throw new Error('Unable to retrieve data');
return await res.json();
}
module.exports = ordersCountService;
How can I pass the JSON through to the browser?
I have been trying a few things - you'll notice the return data; - but I can't figure out how to return the JSON so that it's displayed in the browser when someone visits ourdomain.com/api/orders_count.
Any suggestions as to what I am doing wrong here? I am still new to JS so sorry if I am missing something completely obvious here.
Thank you all for your time. If there is anything I can add for clarity, please don't hesitate to ask.
In your controller, ordersCountService should have 2 parameters: req and res:
The req object represents the HTTP request and has properties for the request query string, parameters, body, and HTTP headers.
The res object represents the HTTP response that an Express app sends when it gets an HTTP request.
In this case, your controller should be:
const ordersCountController = async (req, res) => {
try {
const data = await ordersCountService();
console.log(data);
res.json({data})
} catch(err) {
console.log(err);
}
};
Save it, and open the express server, and type the route url in the browser, you would see the json format.
You could find more information about Express in this article.
Express Explained with Examples - Installation, Routing, Middleware, and More
I'm trying to write a header of an MD5 hash token using crypto then return it back as a response. For some reason, it isn't actually running synchronously. I know JS is an asynchronous language, and that's really the only part I'm struggling with right now. Any help would be appreciated.
This is what I have so far:
const crypto = require('crypto');
const bodyParser = require('body-parser');
const formidable = require('formidable');
const async = require('async')
app.post('/pushurl/auth', (req, res) =>
var data = req.body.form1data1 + '§' + req.body.form1data2
async.waterfall([
function(callback) {
var token = crypto.createHash('md5').update(data).digest("hex");
callback(null, token);
},
function(token, callback) {
res.writeHead(301,
{Location: '/dashboard?token=' + token}
);
callback(null)
},
function(callback) {
res.end();
callback(null)
}
]);
}
});
Output:
Uncaught Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
<node_internals>/internal/errors.js:256
No debugger available, can not send 'variables'
Process exited with code 1
JavaScript is an asynchronous language, yes, but it can also do synchronous tasks very well. In your case, you don't need to do any async expect if you're dealing with promises.
If you write your code like in the example below it will just execute from top to bottom.
But the error (probably) occurred because you forgot to add an opening curly brace to your app.post callback, which results in the data var being immediately returned because of an implied return statement () => (implied), () => {} (explicit).
const crypto = require('crypto');
const bodyParser = require('body-parser');
const formidable = require('formidable');
app.post('/pushurl/auth', (req, res) => {
const data = req.body.form1data1 + '§' + req.body.form1data2;
const token = crypto.createHash('md5').update(data).digest("hex");
res.writeHead(301, {
Location: '/dashboard?token=' + token
});
res.end();
});
I am using NodeJs and MongoDB as a backend service.I am trying to delete document on MongoDB but couldn't delete but sending response deleted.
This what I have done so far:
const express = require('express');
const MongoClient = require('mongodb').MongoClient;
const app = express();
var dburl = process.env.URL;
app.post('/deleteRow', (req,res) => {
MongoClient.connect(dburl,{useNewUrlParser:true}, (err,client) => {
var myquery = { _id:req.body.postId};
if(err){
console.log("Error:", +err);
}
else{
var collect = client.db('abc').collection('xyz');
collect.deleteOne(myquery, function(err,obj){
if(err){
console.log("Error".red, +err);
}
else{
res.send("Deleted");
}
});
}
});
});
Let me know what I need to correct in above code. Any help would be appreciated.
THANKS
Try casting your req.body.postId to an ObjectId
Something like
var ObjectID = require(‘mongodb’).ObjectID;
var postId = new ObjectID(req.body.postId);
Then use that postId in your deleteOne({}) params
The error is triggered in the Product.find statement below:
var bodyparser = require('body-parser');
var express = require('express');
var status = require('http-status');
var _ = require('underscore');
var mongoose = require('mongoose');
var productSchema = require('./product');
var schema = new mongoose.Schema(productSchema);
schema.index({ name: 'text' });
module.exports = function(wagner) {
var api = express.Router();
api.use(bodyparser.json());
api.get('/product/text/:query', wagner.invoke(function(Product) {
return function(req, res) {
console.log("we are in the get " + req.params.query);
Product.
find(
{ $text : { $search : req.params.query } },
{ score : { $meta: 'textScore' } }).
sort({ score: { $meta : 'textScore' } }).
limit(10).
exec(handleMany.bind(null, 'products', res));
};
}));
return api;
};
function handleMany(property, res, error, result) {
console.log("We are handling the many");
if (error) {
console.log(error);
return res.
status(status.INTERNAL_SERVER_ERROR).
json({ error: error.toString() });
}
var json = {};
json[property] = result;
res.json(json);
}
I'm running MongoDB 3.4.2 on windows 10. I explicitly ran the statement db.products.ensureIndex({name: "text"}); in the MongoDB shell and for the first time I didn't get the error. It still gets timeout errors intermittently, though, when the query takes more than 2000 ms. I thought that I didn't have to explicitly add an index in the MongoDB shell because I'm putting on a schema index in the above code, but I don't know for sure.
Thanks,
William
I got into the MongoDB shell and put the index on the products collection like this:
db.products.createIndex({name: "text"})
That was my solution, and it worked, but I don't know if there was a glitch somewhere that made that solution necessary.
I am using Node.js, Express, MongoDB, and Mongoose. I have a function that fetches the largest id number of a document in my MongoDB database and returns it to the program. I have begun modularizing my code, and have migrated that function to another module. I have successfully accessed the function in my main module, but it involves an asynchronous database query. As the function returns a value, I want to assign it to a variable. Unfortunately, When the returned value is assigned to the variable, the variable is actually set to undefined. I was thinking about using event emitters to signal that the query is finished, but that presents two issues as well:
1) I don't think you can do anything in a program AFTER a return statement, which would be what is required.
2) Event Emitters between modules seem very finicky.
Please help me get the variable to be assigned to the correct value. Code for both the main function and the module is below:
(main file) app.js:
//requires and start up app
var express = require('express');
var mongoose = require('mongoose')
, dbURI = 'localhost/test';
var app = express();
var postmodel = require('./models/post').postmodel;
//configures app for general stuff needed such as bodyParser and static file directory
app.configure(function () {
app.use(express.bodyParser());
app.use(express.static(__dirname + '/static'));
});
//configures app for production, connects to mongoLab databse rather than localhost
app.configure('production', function () {
dbURI = 'mongodb://brad.ross.35:lockirlornie#ds037387.mongolab.com:37387/heroku_app6901832';
});
//tries to connect to database.
mongoose.connect(dbURI);
//once connection to database is open, then rest of app runs
mongoose.connection.on('open', function () {
var PostModel = new postmodel();
var Post = PostModel.setupPostSchema();
var largest_id = PostModel.findLargestID(Post);
(module) post.js:
var mongoose = require('mongoose');
module.exports.postmodel = function () {
this.setupPostSchema = function () {
var postSchema = new mongoose.Schema({
title: String,
body: String,
id: Number,
date_created: String
});
var Post = mongoose.model('Post', postSchema);
return Post;
};
this.findLargestID = function (Post) {
Post.find(function (err, posts) {
if (err) {
console.log("error finding largest ID!");
} else {
var largest_id = 0;
for (var post in posts) {
if (posts[post].id >= largest_id) largest_id = posts[post].id;
}
console.log(largest_id);
return largest_id;
}
});
};
};
You need to have findLargestID accept a callback parameter that it will call once largest_id is available:
this.findLargestID = function (Post, callback) {
Post.find(function (err, posts) {
if (err) {
console.log("error finding largest ID!");
callback(err);
} else {
var largest_id = 0;
for (var post in posts) {
if (posts[post].id >= largest_id) largest_id = posts[post].id;
}
console.log(largest_id);
callback(null, largest_id);
}
});
};