Why do i get 'undefined' at my request in Node and Mongo? - node.js

I'm creating my first API, I've used .env for database variables in this url:
const uri = `mongodb+srv://${mongo_user}:${mongo_pwd}#cluster0.ynvbj.mongodb.net/${mongo_db}?retryWrites=true&w=majority`
then created the client:
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true })
Then, a main function that calls the functions that finds data from Mongo like users:
async function main() {
try {
await client.connect();
await getUser(client, 'users', mongo_db);
} catch (e) {
console.error(e);
} finally {
await client.close();
}
}
main().catch(console.err);
//------GET
//user by Dni
async function getUser(client, coll, mongo_db){
const collection = await client.db(`${mongo_db}`).collection(`${coll}`)
.find({dni: 38383838}).toArray(function(err, results) {
console.log(results);
return results;
})
};
And finally, I created the routes, but I get undefined. I've check everything and I don't get what's wrong.
const {getUser, getOrder, getProducts} = require('./db_connection')
const {Router} = require('express')
const router = Router()
//GET
//get user
router.get('/users', async (req, res) => {
let data = await getUser;
res.json({data});
})
module.exports = router;
And this is app.js
const express = require('express')
const app = express()
require('dotenv').config();
//settings
app.set('port', process.env.PORT || 3000)
//middlewares
app.use(express.urlencoded({extended:false}))
app.use(express.json())
//server
app.listen(app.get('port'), ()=> {
console.log(`Server running on port ${app.get('port')}`)
})
//require api
app.use('/api', require('./api_routes'))

It looks like your results are undefined, that could be for a lot of different reasons.
Where you have console.log(results) can you replace that with console.debug(err, results);
That might give you more insight into the reason it's not getting the results.
async function getUser(client, coll, mongo_db){
const collection = await client.db(`${mongo_db}`).collection(`${coll}`)
.find({dni: 38383838})
.toArray(function(err, results) {
console.debug(err, results);
return results;
})
};

Related

Schema DB querying with Mongo Db. I don't understand why but the way I call to push or retrieve data from the db it seems to time out and throw err

I'm very new to MERN so I'm trying to figure out how to use schema correctly within my backend. I'm trying to just make a very simple case here where I just create a new user document in the database. I'm not trying to do anything with auth yet I just want to figure the syntax i guess behind why my code is not communicating correctly with the db.
When I run my backend code it says I successfully am running on port 4000 and that I've connected to my database.
When I check my routes with Postman it seems to time out and return bad request.
Here is my Schema code
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: {type:String, required:true},
balance: {type:Number, required:true},
currentLimit: {type:Number, required:true},
maximumLimit: {type: Number, required:true, default:50}
});
module.exports = mongoose.model('user', userSchema);
This is where I make the call to the database in my router function
const express = require('express');
const User = require('../Models/user');
const userInfo = express.Router();
userInfo.route('/userInfo').get(
async function (req, res) {
await User.find().then((err, results) => {
if (err) throw err;
res.json(result);
})
}
);
userInfo.route('/makeUser').post(
async function (req, res) {
const { name, balance, currentLimit, maximumLimit } = req.body;
try {
const user = await User.create({ name, balance, currentLimit, maximumLimit });
res.status(200).json(user);
} catch (error) {
res.status(400).json(error);
console.log('error');
}
}
);
module.exports = userInfo;
This is my connection code
const { MongoClient } = require('mongodb');
const Db = process.env.URI;
const client = new MongoClient(Db, {
useNewUrlParser: true,
useUnifiedTopology: true
});
module.exports = {
connectToDatabase: async function (callback) {
try {
client.connect();
console.log('Succesfully Connected to Database');
} catch (e) {
console.error(e);
}
}
}
This is my index file
const express = require('express');
const cors = require('cors');
require('dotenv').config({path: "./config.env"});
const PORT = process.env.PORT || 4000;
const app = express();
app.use(cors());
app.use(express.json());
app.use(require('./routing/userInfo'));
const dbo = require("./DB/connection");
app.listen(PORT, ()=>{
console.log(`Server is running on port ${PORT}.`);
dbo.connectToDatabase(function (err){
if (err) console.error(err);
})
})
I feel like I've read so many mongodb schema docs and I do exactly as the docs say but still fail to read or write to/from the db.
You should await client.connect():
module.exports = {
connectToDatabase: async function (callback) {
try {
await client.connect();
console.log('Succesfully Connected to Database');
} catch (e) {
console.error(e);
}
}
};
Also, make sure you are connected to the database before starting the service:
dbo.connectToDatabase(function (err){
if (err) {
console.error(err);
process.exit(1);
}
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
})
Finally, in the get route you are mixing await with then:
userInfo.route('/userInfo').get(async function (req, res) {
const result = await User.find();
res.json(result);
});

When I click the client site then show this error

This is my Code
const express = require('express');
const { MongoClient } = require('mongodb');
const cors = require('cors');
require('dotenv').config()
const app = express();
const port = 5000;
// middle ware
app.use(cors());
app.use(express.json());
const uri = `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASS}#cluster0.84pml.mongodb.net/myFirstDatabase?retryWrites=true&w=majority`;
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
client.connect(err => {
const collection = client.db("carMechanic").collection("services");
// perform actions on the collection object
client.close();
});
async function run() {
try {
await client.connect();
const database = client.db("carMechanic");
const servicesCollection = database.collection("services");
// post API
app.post('/services', async (req, res) => {
const service = req.body;
// console.log('hit the post is', service);
const result = await servicesCollection.insertOne(service);
console.log(result);
res.send('post hitted')
});
}
finally {
// await client.close();
}
}
run().catch(console.dir);
app.get('/', (req, res) => {
res.send('Running Genius Server');
});
app.listen(port, () => {
});
And This is the error message
G:\web_projects\practice\node\module-65-Genius-car\backend\node_modules\mongodb\lib\utils.js:690
throw new error_1.MongoRuntimeError(`illegal state transition from [${target.s.state}] => [${newState}], allowed: [${legalStates}]`);
^
MongoRuntimeError: illegal state transition from [closed] => [connected], allowed: [closed,connecting]
at stateTransition (G:\web_projects\practice\node\module-65-Genius-car\backend\node_modules\mongodb\lib\utils.js:690:19)
at G:\web_projects\practice\node\module-65-Genius-car\backend\node_modules\mongodb\lib\sdam\topology.js:226:21
at G:\web_projects\practice\node\module-65-Genius-car\backend\node_modules\mongodb\lib\cmap\connection_pool.js:272:25
at handleOperationResult (G:\web_projects\practice\node\module-65-Genius-car\backend\node_modules\mongodb\lib\sdam\server.js:363:9)
at MessageStream.messageHandler (G:\web_projects\practice\node\module-65-Genius-car\backend\node_modules\mongodb\lib\cmap\connection.js:479:9)
at MessageStream.emit (events.js:375:28)
at processIncomingData (G:\web_projects\practice\node\module-65-Genius-car\backend\node_modules\mongodb\lib\cmap\message_stream.js:108:16)
at MessageStream._write (G:\web_projects\practice\node\module-65-Genius-car\backend\node_modules\mongodb\lib\cmap\message_stream.js:28:9)
at writeOrBuffer (internal/streams/writable.js:358:12)
at MessageStream.Writable.write (internal/streams/writable.js:303:10)
The problem is this line:
client.connect(err => {
const collection = client.db("carMechanic").collection("services");
// perform actions on the collection object
client.close();
});
you don't need this because you made connection to the database later
I answered myself.
I had made a mistake, that was I wrote the extra code given below.
client.connect(err => {
const collection = client.db("carMechanic").collection("services");
// perform actions on the collection object
client.close();
});
Because this has already been declared inside of my function.
await client.connect();
const database = client.db("carMechanic");
const servicesCollection = database.collection("services");
When I remove this--
client.connect(err => {
const collection = client.db("carMechanic").collection("services");
// perform actions on the collection object
client.close();
});
the code is working well.
I have my code below and works as is. A few things:
Install dependencies again if needed
I am using the sample airbnb db they provide in Atlas service on cloud.mongodb.com
Change username:0987654321 to your own username and password where 'username' is the username and 0987654321 is the password.
Run() works fine locally but it's not straight forward to have a local method start a server endpoint and keep track of it or vice versa. For that you need good chaining
So only USE the run method to test locally and it works fine or use the express endpoints to test via your app client side or curl or postman and that works too independently.
Heres my whole server file:
const express = require('express');
const { MongoClient } = require('mongodb');
const cors = require('cors');
// middle ware
const app = express();
const port = 5000;
// middle ware
app.use(cors());
app.use(express.json());
const uri = "mongodb://username:0987654321#cluster0-shard-00-00.czraf.mongodb.net:27017,cluster0-shard-00-01.czraf.mongodb.net:27017,cluster0-shard-00-02.czraf.mongodb.net:27017/sample_airbnb?ssl=true&replicaSet=atlas-wmfxrm-shard-0&authSource=admin&retryWrites=true&w=majority";
async function run(){
//1 connect
const client = await MongoClient.connect(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
//2 set db and collection
const collection = client.db("sample_airbnb").collection("listingsAndReviews");
// perform actions on the collection object
//3 CREATE
let doc = {
"_id":"100009090",
"listing_url":"https://www.airbnb.com/rooms/100009190",
"name":"Ribeira Charming Duplex",
"summary":"Fantastic duplex apartment with three bedrooms, located in the historic area of Porto, Ribeira (Cube)",
"neighborhood_overview":"In the neighborhood of the river, you can",
"price":"250gbp"
}
//4.0 POST INDEPENDENTLY
//collection.insertOne(doc).then(doc => { console.log('inserted id is: ', doc.insertedId)});
//FIND ONE
//const result = await collection.find( {_id: {$eq: "10006546"} }).toArray();
//FIND MANY
//const many = await collection.find( {_id: { $in: ["10006546", "100009090"] } } ).toArray();
//LOGGER
//console.log(many)
client.close();
};
//server methods
//get route
app.get('/', (req, res) => {
res.send('Running Genius Server');
});
//get docs
app.get('/docs', async (req, res) => {
//FIND MANY
const many = await collection.find( {_id: { $in: ["10006546", "100009090"] } } ).toArray();
//LOGGER
console.log(many)
res.send('docs returned', JSON.stringify(many));
});
//add docs
app.post('/test', async (req, res) => {
//get data through body
const service = req.body.name;
//get data through query params in url
const qparam = req.query.name;
const _id = req.query.id;
//build your doc
let doc = {service:qparam, _id: _id};
//connect to db and collection
//2 set db and collection
//1 connect
const client = await MongoClient.connect(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const collection = client.db("sample_airbnb").collection("listingsAndReviews");
collection.insertOne(doc).then(doc => { console.log('inserted id is: ', doc.insertedId)});
// /res.status(status).send(body)
res.send(JSON.stringify(service + ' ' + qparam));
});
app.listen(port, () => {
});
run();

Can i add mongodb _id to localhost adress to display one post from database?

I have set up my project to display posts from a MongoDB database. My localhost address is http://localhost:5000/api/posts and it displays my two saved posts. How can I add MongoDB _id to localhost adress to only display one post?
MongoDB _id: 6061890d59ec3b6abcb011fb
I have tried this:
http://localhost:5000/api/posts/6061890d59ec3b6abcb011fb
http://localhost:5000/api/posts/id:6061890d59ec3b6abcb011fb
http://localhost:5000/api/posts/_id:6061890d59ec3b6abcb011fb
All of them returns error Cannot GET /api/posts/and_the_above_parameters_for_each_example`
Index.js to connect my backend to my application.
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
//Middleware
app.use(bodyParser.json());
app.use(cors());
const posts = require("./routes/api/posts");
app.use("/api/posts", posts);
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server started on port ${port}`));
posts.js to connect to MongoDB database. Below Password, MY_DATABASE and TABLE is changed to real values in my code.
const express = require("express");
const mongodb = require("mongodb");
const router = express.Router();
//Get posts
router.get("/", async (req, res) => {
const posts = await loadPostCollection();
res.send(await posts.find({}).toArray());
});
//Add post
router.post("/", async (req, res) => {
const posts = await loadPostCollection();
await posts.insertOne({
text: req.body.text,
createdAt: new Date(),
});
res.status(201).send();
});
router.delete("/:id", async (req, res) => {
const posts = await loadPostCollection();
await posts.deleteOne({
_id: req.params.id,
});
res.status(200).send();
});
async function loadPostCollection() {
const client = await mongodb.MongoClient.connect(
"mongodb+srv://MongoDB:PASSWORD#cluster0.5pnzd.mongodb.net/MY_DATABASE?retryWrites=true&w=majority",
{
useNewUrlParser: true,
useUnifiedTopology: true,
}
);
return client.db("MY_DATABASE").collection("TABLE");
}
module.exports = router;
PostService.js to display posts on localhost and methods to post and delete.
import axios from "axios";
const url = "http://localhost:5000/api/posts/";
class PostService {
// Get posts
static getPosts() {
return new Promise((resolve, reject) => {
axios
.get(url)
.then((res) => {
const data = res.data;
resolve(
data.map((post) => ({
...post, //spread operator
createdAt: new Date(post.createdAt),
}))
);
})
.catch((err) => {
reject(err);
});
});
}
// Create posts
static insertPost(text) {
return axios.post(url, {
text,
});
}
static deletePost(id) {
return axios.delete(`${url}${id}`);
}
}
export default PostService;
router.get("/:id", async (req, res) => {
const posts = await loadPostCollection();
res.send(await posts.findOne({
_id: req.params.id,
}));
});
Number 1: http://localhost:5000/api/posts/6061890d59ec3b6abcb011fb is correct, but you're going to need to create a new route to handle that request.
These are often called 'show' routes.
router.get("/:id", async (req, res) => {
// code to handle the logic of that request
// access the url parameter via: req.params.id
});

Get results with Mongodb Nodejs driver and Express using find

I have a tiny express server that I want to use to get some data from a collection in my database:
const express = require('express');
const MongoClient = require('mongodb').MongoClient;
const app = express();
const PORT = 3000;
const MONGO_URI = 'mongodb://127.0.0.1:27017/test';
async function myReport(schoolId) {
const client = new MongoClient(MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true });
try {
await client.connect()
console.log("Hello!"); // This is never ran unless I remove "await" from the above line :S
const db = client.db();
const result = db.collection('states').find({}).map((a, b, c) => {
console.log("This never runs", a, b, c);
return "asdf";
});
return result;
} catch (err) {
console.log("ERROR", err);
}
client.close();
};
// Hoisting server
app.get('/api/reports/states/:id', async function (req, res, next) {
const report = myReport(req.params.id)
res.json(report); // {}
});
app.listen(PORT, (err) => {
console.log(`reporting listening in`, PORT);
});
I really don't know what I'm doing wrong here. Tried using .each, toArray and I'm not able to get the actual results as a list.
I've been following these docs: https://mongodb.github.io/node-mongodb-native/3.6/api/Cursor.html
Any idea what I'm doing wrong?
As per your saying:
await client.connect()
console.log("Hello!"); // This is never ran unless I remove "await" from the above line :S
I think connection is not establishing. I tried your code with a little bit modification. I created a cluster on Atlas Mongodb and used its URI as a connection string.
const express = require('express');
const MongoClient = require('mongodb').MongoClient;
const app = express();
const PORT = 3000;
const MONGO_URI = 'mongodb+srv://<username>:<password>#cluster0-oqotc.mongodb.net/<dbname>?retryWrites=true&w=majority';
const getListings = async () => {
const client = new MongoClient(MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true });
try {
await client.connect()
console.log("Hello!"); // This will print now :-)
const listings = await client.db("sample_airbnb").collection("listingsAndReviews").findOne({});
return listings;
} catch (err) {
console.log("ERROR", err);
}
client.close();
};
// Hoisting server
app.get('/api/get-listings', async function (req, res, next) {
const report = await getListings()
res.json(report);
});
app.listen(PORT, (err) => {
console.log(`reporting listening in`, PORT);
});
You need to change username, password and dbname with your ones.
Note: While using Atlas Mongodb Cluster, if you are getting connection error, you need to whitelist your ip as well.
Hope it will help you. Thanks
You defined myReport as an asynchronous function which returns a promise. Add toArray() back into your code and then get your report like this
app.get('/api/reports/states/:id', async function (req, res, next) {
myReport(req.params.id).then(report => {
res.json(report);
});
});
Because its the call to res.json is also in an asynchronous function I think you can also do
app.get('/api/reports/states/:id', async function (req, res, next) {
const report = await myReport(req.params.id);
res.json(report);
});

Data not persisting/saving into MongoDB database

I'm trying to figure out why my data hasn't been saving in MongoDB, despite calling the .save() method. I'm aware that this is an asynchronous process, but as you can see below, I set up a callback using .then() - which executes without error. The target database has a single empty collection in it, so I was expecting the data to appear there or in a new collection, neither of which happened. Here's the code for my index.js file:
const express = require('express');
const mongoose = require('mongoose');
const { body, validationResult } = require('express-validator/check');
const router = express.Router();
const Registration = mongoose.model('Registration');
router.get('/', (req, res) => {
res.render('form', { title: 'Registration Form'});
});
router.post('/',
[body('name')
.isLength(1)
.withMessage('Please enter a name.'),
body('email')
.isLength(1)
.withMessage('Please enter an email address.')
],
(req, res) => {
//console.log(req.body);
const errors = validationResult(req);
if(errors.isEmpty)
{
const registration = new Registration(req.body);
//registration.markModified('collection_1');
registration.save()
.then(() => { res.send('Thank you for your registration!'); })
.catch(() => { res.send('Sorry! Something went wrong.'); });
} else {
// re-renders form with error message
res.render('form', {
title: 'Registration form',
errors: errors.array(),
data: req.body,
});
}
});
module.exports = router;
Let me know if any other files would be useful. Any assistance would be greatly appreciated.
EDIT: Here's my start.js file.
require('dotenv').config();
const mongoose = require('mongoose');
require('./models/Registration');
mongoose.connect(process.env.DATABASE, { useMongoClient: true });
mongoose.Promise = global.Promise;
mongoose.connection
.on('connected', () => {
console.log(`Mongoose connection open on ${process.env.DATABASE}`);
})
.on('error', (err) => {
console.log(`Connection error: ${err.message}`);
});
const app = require('./app');
const server = app.listen(3000, () => {
console.log(`Express is running on port ${server.address().port}`);
});

Resources