Cannot read property 'find' of undefined when requesting data from db - node.js

I am very new to back end development, so I am watching a tutorial. In the tutorial, mlabs is used, but Mongo Atlas seems to work differently. I am trying to display my posts using a get request, but am getting this error:
TypeError: Cannot read property 'find' of undefined
at C:\Users\reaga\Desktop\Projects\fullstack-crud\server\routes\api\posts.js:10:26
posts.js
const express = require('express');
const MongoClient = require('mongodb').MongoClient;
const router = express.Router();
// Get post
router.get('/', async (req, res) => {
const posts = await loadPostsCollection();
res.send(await posts.find({}).toArray());
});
// Add post
// Delete post
async function loadPostsCollection() {
// Adding connection string to var
const uri = 'mongodb+srv://nova:nova123#cluster0.deckb.mongodb.net/Cluster0?retryWrites=true&w=majority';
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
await client.connect(err => {
client.db('Project 0').collection('posts');
});
}
module.exports = router;

Related

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();

req.params.userId not found ( path set to /:userId) Node.js

I want to get an user by his userId parameter but it doesn't work. The app connects to the database(Atlas), I can create users, retrieve them all in bulk but I can't retrieve them with a specific parameter ( in this case UserId), producing a not found error message.
UserRoutes.js
const express = require('express');
const UserModel = require('../models/UserModel');
const app = express();
app.get('/getusersById/:userId', async (req, res) => {
const user = await UserModel.find(req.params.userId);
try {
res.send(user);
} catch (err) {
res.status(500).send(err);
}
});
UserModel.js
const mongoose = require('mongoose');
// Define Schema
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true,
},
age: {
type:Number,
required:true
},
userId: {
type:String,
required:true
},
});
//
const User = mongoose.model('user', UserSchema);
module.exports = User;
Server.js
// Open connection to test database
const express = require('express');
const mongoose = require('mongoose');
const UserRouter = require('./routes/UserRoutes.js');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const uri = "mongodb+srv://XXXXXXXXXXX#XXXXXXXeXXXX.gcp.mongodb.net/dbusers?retryWrites=true&w=majority";
mongoose.connect(uri,{
userNewUrlParser: true,
useUnifiedTopology: true
});
// Notify if connection was succesful
var db = mongoose.connection;
db.on ('error', console.error.bind(console, 'connection error'));
db.once('open', function() {
console.log("Connection Succesful");
});
db.on('close', () => {
db.removeAllListeners();
});
// Router & Port
app.use(UserRouter);
app.listen(3000,
() => {console.log('Server is running...')});
And this is the postman request:
Postman get userId
Your request is wrong. You defined your path as:
app.get('/getusersById/:userId', /* callback */)
So the request URL should be:
/getusersById/3
and not
/getusersById/?userId=3
'/getusersById/:userId'
What you are doing here is parameters of your request, which is userId
the correct usage of this api is /getusersById/3
app.get('/getusersById/:usersId', async (req, res) => {
const user = await UserModel.find(req.params.usersId );
However it seems you want to use ?usersId=3 for query the user id
You need to use req.query.usersId
app.get('/getusersById', async (req, res) => {
const user = await UserModel.find(req.query.usersId );
You can find examples of query usage : https://coderrocketfuel.com/article/handle-get-request-query-string-parameters-in-express-js
I think you are new to API development. From the image that I can see that you are sending userId as a query parameter. But in code, you are doing req.parms.userId which is used for path params. In your code you defined route for path parameter so the request should be like this:
/getusersById/3
And to be handled as below
app.get('/getusersById/:userId', async (req, res) => {
const user = await UserModel.find(req.params.userId );
However, If you want to pass userId in query parameter then do this:
app.get('/getusersById', ...)
request can be made like this:
/getusersById/?userId=3
and query parameter will be accessible as below:
app.get('/getusersById', async (req, res) => {
const user = await UserModel.find(req.query.userId );
Read this: Query vs Path params

TypeError: Cannot read property 'db' of null

I am having issue connecting to mongodb atlas, getting the error below
let express = require('express')
let mongodb = require('mongodb')
let app = express()
let db
let connectionString = 'mongodb+srv://olumide:xxxxxxxx#cluster0-edskm.mongodb.net/todoApp?retryWrites=true&w=majority'
mongodb.connect(connectionString, {useNewUrlParser: true, useUnifiedTopology: true}, function(err, client){
db = client.db()
app.listen(3000)
})
app.use(express.urlencoded({extended: false}))
app.post('/create-item', function(req,res){
db.collection('item').insertOne({text: req.body.item}, function(){
res.send("thanks for submitting the form")
})
})
Error message
This is because the mongo.connect function is asynchronous. You will need to include the app.post function inside of the mongo.connect callback.
Something kind of like this should work:
let express = require('express')
let mongodb = require('mongodb')
let app = express()
app.use(express.urlencoded({extended: false}))
let connectionString = 'mongodb+srv://olumide:xxxxxxxx#cluster0-edskm.mongodb.net/todoApp?retryWrites=true&w=majority'
mongodb.connect(connectionString, {useNewUrlParser: true, useUnifiedTopology: true}, function(err, client){
const db = client.db()
app.post('/create-item', function(req,res){
db.collection('item').insertOne({text: req.body.item}, function(){
res.send("thanks for submitting the form")
})
})
app.listen(3000)
})
I figured out, in newer versions of MongoDB (3 and higher) they have essentially changed the way of connecting node server to the database. To establish a reusable connection (So that we can access the connected database from any other file), I created an async function in my db.js file where the connection is established and then exported it. In the end of the file, I have called the function. The code is as follows:
const {MongoClient} = require('mongodb')
const client = new MongoClient('mongodb+srv://todoAppUser:<password>#cluster0.6lvjr.mongodb.net/myDatabase?retryWrites=true&w=majority')
async function start(){
await client.connect()
console.log("Connected")
module.exports = client.db()
const app = require('./app')
app.listen(3000)
}
start()
and while calling it from another file:
const productCollection = require('./db').collection("product");
This code gives me no error and works perfectly fine. With the help of the above code, one can use this conveniently while following the MVC (Model-View-Controller) framework.
use mongoose connection as a different javascript file and import it to express script file
database.js
let mongoose = require('mongoose');
const server = '127.0.0.1:27017'; // REPLACE WITH YOUR DB SERVER
const database = 'test'; // REPLACE WITH YOUR DB NAME
class Database {
constructor() {
this._connect()
}
_connect() {
mongoose.connect(`mongodb://${server}/${database}`,{ useUnifiedTopology: true ,useNewUrlParser: true, useFindAndModify: false})
.then(() => {
console.log('Database connection successful')
})
.catch(err => {
console.error('Database connection error')
})
}
}
module.exports = new Database()
strong text

How can I display my mongoDB query as json using express?

When I use nodemon to start my express server, it constantly loads in the browser and will not load any of my application.
This is the code in my dbconn.js and app.js files. I cannot figure out how to pull and display my query in order to verify my connection to the db. I am a total beginner in using mongoDB and express. Please help.
It is not throwing any exceptions, so I can't figure out what I am doing wrong.
const mongoose = require('mongoose')
const MongoClient = require('mongodb').MongoClient;
const express = require('express');
const router = express.Router();
const uri ='mongodb+srv://<username>:<password>#wager0-mhodf.mongodb.net/test?retryWrites=true&w=majority';
const client = new MongoClient(uri, { useUnifiedTopology: true, useNewUrlParser: true });
client.connect(err => {
console.log("Connected successfully to server");
router.get('/', function(req, res, next) {
const collection = client.db("wager0").collection("gameTypes");
// Get first two documents that match the query
collection.find({a:1}).limit(2).toArray(function(err, docs) {
res.json({length: docs.length, records: docs});
});
client.close();
});
});
module.exports = router;
var dbconnRouter = require('./services/dbconn');
app.use('/dbconn', dbconnRouter);

Node.js/Postgresql database connection returns undefined

I have a PostgreSQL database hosted on Heroku. Here is how I connect to it:
//sql_conn.js
const pgp = require('pg-promise')();
pgp.pg.defaults.ssl = true;
const db = pgp('postgres://connection_string_redacted');
if(!db) {
console.log("Database setup unsuccessful.");
process.exit(1);
}
module.exports = db;
And I try to access it here:
//test-endpoint.js
const express = require('express');
const app = express();
const router = express.Router();
let db = require('../utils/sql_conn').db;
const bp = require('body-parser');
router.use(bp.json());
router.get("/", (req, res) => {
let query = "SELECT * FROM table;";
db.manyOrNone(query)
.then((rows) => {
res.send({
success: true,
result: rows
})
}).catch((err) => {
res.send({
success: false,
error: err
})
});
});
module.exports = router;
I have verified that the connection string is correct, the database is live on Heroku, and the path of the require statement is correct, but calling test-endpoint.js from the browser returns:
TypeError: Cannot read property 'manyOrNone' of undefined
Why is the database undefined?
It looks like an import/export problem. Try to replace this line:
let db = require('../utils/sql_conn').db;
by
const db = require('../utils/sql_conn');
And you should be fine.

Resources