Trying to select every document with the same ID using MongoDB - javascript

So I'm trying to fetch every document which matches the same ID.
Here is what did I do:
app.get('/comments/:id', async (req,res)=>{
let db = await connect();
let id = req.params.id;
console.log(id);
let results = await db.collection('comments').find({postID: id});
console.log(results);
res.json(results);
});
How to send more than one documents with the same ID?
I want to select every postID property with the same ID
My code while connecting with MongoDB:
const { MongoClient } = require('mongodb');
let connection_string = 'mongodb+srv://user:pass#host/myFirstDatabase?retryWrites=true&w=majority';
let client = new MongoClient(connection_string, {
useNewUrlParser: true,
useUnifiedTopology: true
});
let db = null
export default () => {
return new Promise((resolve, reject) =>{
if (db /*&& client.isConnected()*/){
resolve(db)
}
client.connect(err => {
if(err){
reject("Error while connecting: " + err)
}
else{
console.log("Successful connection!")
db = client.db("posts")
resolve(db)
}
});
})
};

Make sure you are importing client from the file where you are making the connection.
app.get("/comments/:id", async (req, res) => {
await client.connect(); // Simply connect() won' work.
const db = client.db("posts"); // Specify the db here
let id = req.params.id;
console.log(id);
let results = await db.collection("comments").find({ postID: id }).toArray(); // Without toArray(), it returns a cursor to the array.
console.log(results);
res.json(results);
});
db.js
const { MongoClient } = require("mongodb");
let connection_string = "mongodb+srv://admin:admin#cluster0.3ctoa.mongodb.net/myFirstDatabase?retryWrites=true&w=majority";
let client = new MongoClient(connection_string, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = function () {
return new Promise((resolve, reject) => {
client.connect((err) => {
if (err) {
reject("Došlo je do greške prilikom spajanja: " + err);
} else {
resolve("Successful connection!");
}
});
});
};
module.exports = { client, db };
And instead of importing connect, import both client and db from db.js.

If you are talking about the id created by mongoose.scheme.Types.objectId, There is only one entry with that ID

Related

Convert Promise to async

I am trying to convert mySQL connection from promise to asycn await so far I have the following setup:
const mysql = require("mysql");
const pool = mysql.createPool({
connectionLimit: 10,
password: "",
user: "root",
database: "usersdb",
host: "localhost",
port: "3306",
});
let usersDB = {};
usersDB.all = () => {
return new Promise((resolve, reject) => {
pool.query("SELECT * FROM users", (err, results) => {
if (err) {
return reject(err);
}
return resolve(results);
});
});
};
usersDB.one = (id) => {
return new Promise((resolve, reject) => {
pool.query("SELECT * FROM users WHERE id = ?", [id], (err, results) => {
if (err) {
return reject(err);
}
return resolve(results[0]);
});
});
};
module.exports = usersDB;
Is there a way to convert this codes:
return new Promise((resolve, reject) => {
pool.query("SELECT * FROM users", (err, results) => {
if (err) {
return reject(err);
}
return resolve(results);
});
to async await and make the code more compress or succint?
UPDATE: on my router, I have these codes:
const router = express.Router();
router.get("/", async (req, res) => {
try {
let results = await db.all();
res.json(results);
} catch (error) {
console.log(error);
res.sendStatus(500);
}
});
router.get("/:id", async (req, res) => {
try {
let results = await db.one(req.params.id);
res.json(results);
} catch (error) {
console.log(error);
res.sendStatus(500);
}
});
So it just fine calling async await twice?
You can convert any callback function to promise by using util.promisify
const util = require('util')
// ....
const query = util.promisify(pool.query)
// ... inside some async function
const users = await query("SELECT * FROM users;")
// or promise style
query("SELECT * FROM users;")
.then((users) => {
console.log(users)
})
.catch(console.error)
usersDB.one = (id) => {
try {
const users = pool.query("SELECT * FROM users WHERE id = ?", [id]);
return users;
} catch (e) {
throw e;
}
};
Or more simply,
usersDB.one = (id) => pool.query("SELECT * FROM users WHERE id = ?", [id]);
What you want to do is to promisify the DB call. You can acheive this by factorisation :
const mysql = require("mysql");
const pool = mysql.createPool({
connectionLimit: 10,
password: "",
user: "root",
database: "usersdb",
host: "localhost",
port: "3306",
});
function promisify(...args){
return new Promise((resolve, reject) => {
pool.query(...args, (err, result) => {
if(err) reject(err);
resolve(result);
});
});
}
let usersDB = {};
//Then you can call it this way :
usersDB.all = async () => {
return await promisify("SELECT * FROM users");
//Note that you can avoid to await there.
};
usersDB.one = async (id) => {
return await promisify("SELECT * FROM users WHERE id = ?", [id]);
};
module.exports = usersDB;

Making a jest test file for mysql database calls

I'm very new to testing with Jest. I want to make a test to see if the following function returns user data from the database I have:
let dbConnect = require('../config/dbConnect');
let findUserByEmail = (email) => {
return new Promise(async (resolve, reject) => {
try {
dbConnect.query("SELECT * FROM user_login WHERE email = ?", email, function (error, results) {
if (error) reject(error);
let user = results[0];
if(user == undefined){
resolve()
}
resolve(user);
})
} catch (e) {
reject(e);
}
})
}
How would I go about making mock data to use in testing?
EDIT: Here is dbConnect:
let mysql = require('mysql');
let dotenv = require('dotenv');
dotenv.config({path: '../.env'});
let db = mysql.createConnection({
host: process.env.DATABASE_HOST,
database: process.env.DATABASE,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
});
db.connect(function (error) {
if (error) console.log(error);
else console.log("MYSQL Connected...");
});
module.exports = db;
Edit: fixed mistake
const mysql = require('mysql')
const mockQuery = jest.fn()
jest.mock('mysql', () => ({
createConnection: () => ({
connect: () => undefined,
query: mockQuery
}),
}))
describe('findUserByEmail', () => {
it('should resolve with the user when query suceeds', async () => {
mockQuery.mockImplementationOnce((sql, email, callback) => callback(null, ['TEST USER']));
expect(await findUserByEmail()).toBe('TEST USER');
})
});

How to export mongodb db collections to another js file?

I have initialized the connection to my mongodb and now export the db to other nodejs files. How can I do that?
i thought of something like this but it is giving errors.
let database;
export const connectDB = async () => {
const client = new MongoClient(config.dbUri, {
useUnifiedTopology: true,
});
try {
await client.connect();
database = client.db('azkaben');
logger.info('Connected to Database');
} catch (e) {
logger.error(e);
} finally {
await client.close();
}
};
export default database
Error : undefined value of database
database will always be null when you import it.
connectDB is aync call by the time it executes your database variable is already loaded as null.
connectDB you can return database from here.
export const connectDB = async () => {
const client = new MongoClient(config.dbUri, {
useUnifiedTopology: true,
});
try {
await client.connect();
database = client.db('azkaben');
return database; // you can get from here
logger.info('Connected to Database');
} catch (e) {
logger.error(e);
} finally {
await client.close();
}
};
Updated code
export const connectDB = async () => {
if (database) return database; // return if database already connected.
const client = new MongoClient(config.dbUri, {
useUnifiedTopology: true,
});
try {
await client.connect();
database = client.db('azkaben');
return database; // you can get from here
logger.info('Connected to Database');
} catch (e) {
logger.error(e);
} finally {
await client.close();
}
};

learning and implementing async await

I've been reading about async and await in JS and tried to implement them in my code (which I totally messed up).
Here is my JS.
var express = require('express');
var router = express.Router();
var jsforce = require('jsforce');
const SEC_TOKEN = 'SEC_TOKEN';
const USER_ID = 'USER_ID';
const PASSWORD = 'PWD';
const { default: axios } = require('axios');
router.get("/", async (req, res, next) => {
await initConnect;
await soqlData;
await slackPostTest;
});
initConnect = async () => {
var conn = new jsforce.Connection({
loginUrl: 'https://login.salesforce.com'
});
await conn.login(USER_ID, PASSWORD + SEC_TOKEN, (err, userInfo) => {
if (err)
console.log(err);
else {
console.log(userInfo.Id);
}
});
}
soqlData = async () => {
await conn.query('Select Id, Name from Account LIMIT 1', (err, data) => {
if (err)
console.log(err);
else
return data.records[0];
})
}
slackPostTest = async () => {
await axios.post('SLACK_WEBHOOK', {
"text": "soqlRes"
})
}
module.exports = router;
What I am trying to achieve?
Initialize my connection by passing in SEC_TOKEN, USER_ID, PASSWORD to my initConnect function this will give me a connection (conn).
Use this conn and query my salesforce instance and get some other data.
post some message(currently irrelevant, but will hook up with the above response later) to my slack endpoint.
Also can someone please give me a little detailed explanation of the solution (in terms of async/await)?
Thanks
Assuming everything else about your JsForce API usage was correct (I have no experience with it, so I can't say), here's how to promisify those callback-based APIs and call them.
var express = require("express");
var router = express.Router();
var jsforce = require("jsforce");
const SEC_TOKEN = "SEC_TOKEN";
const USER_ID = "USER_ID";
const PASSWORD = "PWD";
const { default: axios } = require("axios");
router.get("/", async (req, res, next) => {
const { conn, userInfo } = await initConnect();
const data = await soqlData(
conn,
"Select Id, Name from Account LIMIT 1",
);
await slackPostTest(data.records[0]);
});
function initConnect() {
const conn = new jsforce.Connection({
loginUrl: "https://login.salesforce.com",
});
return new Promise((resolve, reject) => {
conn.login(USER_ID, PASSWORD + SEC_TOKEN, (err, userInfo) => {
if (err) return reject(err);
resolve({ conn, userInfo });
});
});
}
function soqlData(conn, query) {
return new Promise((resolve, reject) => {
conn.query(query, (err, data) => {
if (err) return reject(err);
resolve(data);
});
});
}
function slackPostTest(soqlRes) {
return axios.post("SLACK_WEBHOOK", {
text: soqlRes,
});
}
module.exports = router;

using foreach inside foreach and losing the variable from the first foreach, mongodb

I want to look in a collection for every "open" project, than find for every project the signd in users in a different collection. But after the first .finally() the variable ´code = users´ is empty instead to save the users from the .foreach.
var code = "";
var project_details = "";
var users = "";
var endcode= "";
MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, (err, client) => {
if (err) throw err;
const db = client.db(dbname);
//find projects which are open
let collection = db.collection('project');
collection.find({ status: "open" }).forEach(function (project) {
//find users that signd in for that project
let collection = db.collection('users');
collection.find({ project: project.id }).forEach(function (user) {
users = user.name + users;
})
.catch((err) => { console.log(err); })
.finally(() => {
code = users;
});
//console.log(code); is empty and this point
//foreach project
project_details = "Project:" + project.name + ", Users: " + code;
endcode = endcode + project_details;
})
.catch((err) => { console.log(err); })
.finally(() => {
res.render('projects', { code: endcode });
client.close();
});
//////
});
The expected result in endcode should be "Project: Projectname1, Users: User1,User2 Project: Projectname2, Users: User3,User4 ....
How can I prevent from losing the written variable code?

Categories