When I click the client site then show this error - node.js

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

Related

why am i getting Cannot read properties of undefined (reading 'collection') in the code below?

i'm new to mongodb and dev web and i'm using mongodb with nodejs in this project and i got this problem "Cannot read properties of undefined (reading 'collection')" on postman when i send a request but in VS it connect to database without any problem could anyone help me please
here is my code
that's my connection.js and here when i hover on collection and db it says in visual code it's undefined
const {MongoClient} = require('mongodb');
const {dbURL, dbName} = require('../config');
const client = new MongoClient(dbURL, {
useUnifiedTopology: true,
useNewUrlParser:true
});
function Connect(){
return new Promise(async(resolve, reject) =>{
try {
await client.connect();
const db = client.**db**(dbName);
const users = db.**collection**('users');
users.createIndex({email: 1},{unique: 1});
resolve(db, client);
}catch(error){
reject(error);
}
});
};
module.exports = Connect;
i hope someone can find the solution here
and this is my index.js
const Connect = require('./connection');
const {port} = require('../config');
const app = require('./app');
Connect().then(({db}) => {
app.setupRoutes(db);
console.log('The database is connected');
}).catch((e) => {
console.error("couldn't connect to database", e);
});
app.listen(port, () => console.log(`App listening on port ${port}!`));
module.exports = app;
and that's my app.js
as you see i'm using db.collection here
const express = require("express");
const cors = require("cors");
const ValidationError = require('./errors/ValidationError');
const app = express();
app.use(cors());
app.use(express.json());
const handleNewUser = (user, db) => {
return new Promise(async(resolve, reject)=>{
try {
const users = db.collection('users');
const results = await users.insertOne(user);
resolve(results.insertedId);
}catch (error){
reject(error);
}
})
};
app.setupRoutes = (db) => {
app.post('/users',async (req, res) =>{
const user = req.body;
try {
const errors = validateUser(user);
if(errors.length > 0) throw new ValidationError(errors, 'Validation Error');
const results = await handleNewUser(user, db);
res.status(201).send(results);
}catch (error){
if(error instanceof ValidationError)
res.status(500).send({message:error.message,errors:error.errors});
else if(error.message.startsWith('E11000 duplicate'))
res.status(500).send('duplicate email.');
else res.status(500).send(error.message);
}
});
}
module.exports = app;
i donét know what's wrong and i'm following a tutoriel
resolve(db, client) - you resolve not object but separate values "db" and "client".
Connect().then(({db}) => { -
tries to destructure the 'db' property of the first resolved value, and if your "db" value is not an object or doesn't have .db property, it would always be undefined.
So remove destructuring and use just the value:
Connect().then((db) => {

Why do i get 'undefined' at my request in Node and Mongo?

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

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

Mongodb query does not the show the expect result

I am using node and express server to run the mongoDb. For connection and schema I am using mongoose. i successfully connect the database and able to post the data by using postman but problem is it does not show the expected query. Mongodb returns me only the id not the query which is name and description
Here is models
const mongoose = require("mongoose");
const { Schema } = mongoose;
const form = new Schema(
{
name: { type: String },
description: { type: String }
},
{
timestamps: true
}
);
const formSubmit = mongoose.model("formSubmit", form);
module.exports = formSubmit;
This is my express server
const express = require("express");
const port = 5000;
const cors = require("cors");
const morgan = require("morgan");
const app = express();
const formSubmit = require("./models");
const mongoose = require("mongoose");
app.use(cors());
app.use(morgan("dev"));
mongoose
.connect(
"url",
{
useUnifiedTopology: true,
useNewUrlParser: true
}
)
.then(() => console.log("DB Connected!"))
.catch(err => {
console.log(err);
});
//get method
app.get("/show", async (req, res) => {
try {
const entrries = await formSubmit.find();
res.json(entrries);
} catch (error) {
console.log(error);
}
});
//post method
app.post("/post", async (req, res, next) => {
try {
const logs = new formSubmit(req.body);
const entry = await logs.save();
res.json(entry);
} catch (error) {
if (error.name === "ValidationError") {
res.status(422);
}
next(error);
}
});
app.listen(port, () => {
console.log(`Server is running port ${port}`);
});
I think the problem is you don't correctly save the documents to the collection, so when you retrieve them only _id fields display.
To be able to read request body, you need to add express.json() middleware to your server.js.
app.use(express.json());

Resources