Retrieving documents for MongoDB cluster - javascript

I am trying to retrieve all the documents from a MongoDB cluster. I have followed code I've seen online, however I am facing a small problem.
const MongoClient = require('mongodb');
const uri = "mongodb+srv://<user>:<password>#cluster0-10soy.mongodb.net/test?retryWrites=true&w=majority";
var questionsArray = [];
MongoClient.connect(uri, function (err, client) {
const database = client.db("WhatSportWereYouMadeFor");
database.collection("Questions").find({}, (error, cursor) =>{
cursor.each(function(error, item){
if (item == null){
console.log(error);
}
questionsArray.push(item);
});
})
});
module.exports = { questionsArray };
I connect fine to the database, however I've set a breakpoint at the stop variable and that gets hit before any of the documents retrieved from the database get pushed to the questions array.
I've also tried wrapping the code inside an async function and then awaiting it before the stop variable, but still that breakpoint gets hit first and only after the documents get pushed to the array.

What I would do, this wrap the whole thing into a promise, and the export that.
const MyExport = () => {
return new Promise((resolve, reject) => {
var questionsArray = [];
MongoClient.connect(uri, function (err, client) {
const database = client.db("WhatSportWereYouMadeFor");
database.collection("Questions").find({}, (error, cursor) =>{
cursor.each(function(error, item){
if (item == null){
console.log(error);
}
questionsArray.push(item);
});
resolve(questionsArray)
})
});
})
}
module.exports.questionsArray = MyExport
But then when you import it, you need to run and await it
cosnt questionsArrayFunc = require("path/to/this/file").questionsArray
const questionsArray = await questionsArrayFunc()
I hope this is what you looking for. There might be some other way, but I think this works.

Related

Where can I put an async function so I can use await to send a discord response?

I am pulling data from a Google Sheet and after some help, I have reached the point where the discord bot is responding to the inquiry, with the correct data, but it responds with each row of the map array in separate responses rather than gathering the data and sending it in one message. So I believe I need to use an async function and the await feature. I just can't seem to figure out where or how to put it in. I've been stuck on this for a few hours now and can't seem to get it to work?
Here is my code:
const { google } = require('googleapis');
const { sheets } = require('googleapis/build/src/apis/sheets');
const keys = require('../Data/client_secret.json');
const { Team, DiscordAPIError } = require('discord.js');
const Command = require("../Structures/Command");
const gclient = new google.auth.JWT(
keys.client_email,
null,
keys.private_key,
['https://www.googleapis.com/auth/spreadsheets']
);
module.exports = new Command({
name: "freeagents",
description: "Potential free agents for next season.",
async run(message, args, client) {
gclient.authorize(function(err,tokens){
if(err){
console.log(err);
return;
} else {
console.log("Connected!");
gsrun(gclient);
}
});
async function gsrun(cl){
const gsapi = google.sheets({version:'v4', auth: cl });
gsapi.spreadsheets.values.get({
spreadsheetId: "11e5nFk50pDztDLngwTSmossJaNXNAGOaLqaGDEwrbQM",
range: 'Keepers!C1:F',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const rows = res.data.values;
if (rows.length) {
const cells = rows.filter(cell => cell[3])
cells.map((cell) => {
console.log(`${cell[0]}, ${cell[1]}`);
console.log(`${cells}`);
return message.reply(`${cell[0]}, ${cell[1]}`);
});
} else {
console.log('No data found.');
}
})
};
}
});
Any help would be greatly appreciated!
You're receiving multiple messages because you're sending the message inside cells.map((cell) => {}). That method will call a function on each member of the array. You should instead iterate over the cells array to produce a single string that you can then send as a message, for example:
const strings = [];
for (let cell of cells) {
strings.push(`${cell[0]}, ${cell[1]}`);
}
return message.reply(strings.join("\n"));

js doesnt execute extern function to recieve data from db

I'm trying to receive same version data from my MySQL (MariaDB) Server.
For better maintenance i created one connection Object to handle all database queries.
However when I query some data, it seems like it isn't executed in time, but later when the first await command appears.
dbControl.js :
var mysql = require('mysql');
function getConnection(){
let dbConnection = mysql.createConnection({
host: "localhost",
user: "root",
password: ""
});
dbConnection.connect(function (err) {
if (err) throw err;
});
this.get_version = function() {
let sql = 'SELECT * FROM versionControl ORDER BY id DESC LIMIT 1;'
dbConnection.query(sql, function (err, result) {
if (err) throw err;
console.log("vData:", result);
return result;
});
}
}
module.exports.getConnection = getConnection;
dataHandler.js:
const browserControl = require('./browserControl');
const dbControl = require('../db/dbControl');
const dbConnection = new dbControl.getConnection();
let versionData;
// Here it should be executed -->
versionData = dbConnection.get_version();
console.log(versionData);
async function get_something(){
// Here it is executed -->
const browser = await browserControl.startBrowser();
//......
}
There is a 3th file which simply controls the program. At the moment it just executes the function get_something() like:
const originData = require('./dataHandler.js');
let data = originData.get_something();
console.log(data);
P.s.: its all running with node, thanks in advance ;_)
Your get_something() is marked as async.
Call it with await get_something() or get_something().then(console.log).
Ok, I got a solution. The SQL query function returns a promise now and I created an extra "getVersion"-async-function which is waiting for the resolve of the promise. Thus the promise waits for the db answer and the rest waits until the promise is resolved.
the dataHandler.js now looks like this:
const browserControl = require('./browserControl');
const dbControl = require('../db/dbControl');
const dbConnection = new dbControl.getConnection();
async function getVersion() {
let versionData;
versionData = await dbConnection.get_version();
console.log(versionData);
}
getVersion();
async function get_something(){
const browser = await browserControl.startBrowser();
}
and the query-function now looks like this:
this.get_version = function() {
let sql = 'SELECT * FROM versionControl.lol_scraper ORDER BY id DESC LIMIT 1;'
return new Promise(resolve => {
dbConnection.query(sql, function (err, result) {
if (err) throw err;
console.log("vData:", result);
resolve(result);
})
});
P.s.: still open for smarter or more modern solutions ;_)

Iterate through all documents in a MongoDB collection and saving the data in array

I thought this would be a straightforward task but what I am trying to do is go through all the documents (users) in my collection using a cursor and saving some data into a JS array or set about a specific field of the user or all of the data on that user. I am able to see each document printed on the console, but after looping through all the documents, my array is still empty when printed. Where am I going wrong and if there is an alternative approach please let me know.
const mongoose = require('mongoose');
let Users = require('./models/user.model');
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, { useNewUrlParser: true, useCreateIndex:true, useUnifiedTopology: true});
const connection = mongoose.connection;
connection.once('open', () => {
console.log("MongoDB connection success");
})
let arr = [];
async function getRecords() {
let cursor = Users.find({}).cursor();
for (let doc = await cursor.next(); doc != null; doc = await cursor.next()) {
arr.push(doc); //does not work :(
console.log(doc); //this works
}
}
getRecords();
console.log("ARRAY:",arr); //prints []
Suggestion
Your code should read as such
let arr = [];
// This is an async function (returns a promise)
async function getRecords() {
let docs = await Users.find({}).lean();
arr = docs.filter((doc) => doc !== null); // As an example, however, enter appropriate condition for filter
return arr;
}
// Call the async funtion
getRecords().then(docs => {
console.log("ARRAY:", arr);
});

Trouble with asynchronous code and mongodb

This code searches for a company then searches for all of the websites listed in an array on that company, then searches for all the conversations on that website, then searches for all the messages for each conversation, then sends those arrays of message ObjectIDs to the helper function which then returns an array of JSON data for each message. Fhew.. that was a mouthful.
I need to somehow wait for all of this to complete before cleaning it up a bit then res.send'ing it. All of the code works and the console.log(messagesWithData) posts a few arrays of messages (since it is sent a few in this scenario).
All help is appreciated :)
Company.findOne({ 'roles.admins': userId }, function (err, doc) {
if (!err) {
for (const item of doc.websites) {
Website.findById(item, function (err, doc) {
for (const item of doc.conversations) {
Conversation.findById(item, function (err, doc) {
async function findMessageData() {
var messagesWithData = await helper.takeMessageArray(
doc.messages
);
await sendMessages(messagesWithData);
}
findMessageData();
async function sendMessages(messagesWithData) {
// not sure what to put here!
console.log(messagesWithData)
}
});
}
});
}
} else {
res.send(err);
}
});
Code above can be simplified a bit with async/await
const company = await Company.findOne({ 'roles.admins': userId });
let allMessages = []
for (const websiteId of company.websites) {
const website = await Website.findById(websiteId);
for (const conversationId of website.conversations) {
const conversation = await Conversation.findById(conversationId);
const messagesWithData = await helper.takeMessageArray(
conversation.messages
);
allMessages = [...allMessages, ...messagesWithData]
}
}
// Everything completed, messages stored in one place...
console.log(allMessages)

save method in mongodb/mongoose

This is my first question here. I tried to save document in my collection, but it doesn't work. Response of function is exactly like I want, but it doesn't save in my db. In another controller (createRoom) foundUser.save() it works, but in this controller it doesn't. Thanks in advance!
I am using mongodb/mongooose and express.
const removeRoom = async (req,res,next) => {
const {roomId, userData} = req.body;
const { userId, token } = userData;
let foundUser;
let updatedRooms;
let indexOfNamespaces;
try {
foundUser = await User.findById(userId)
foundUser.namespaces.forEach((ns,i1)=>{
updatedRooms = ns.rooms.filter((room,i2) => {
if(room.id === roomId){
indexOfNamespaces = i1;
}
return room.id !== roomId
})
})
foundUser.namespaces[indexOfNamespaces].rooms = updatedRooms;
console.log(foundUser);
await foundUser.save();
} catch (err) {
console.log(err);
const error = new HttpError('Sth went wrong [removeRoom]', 500);
return next(error);
}
res.status(201).json({updatedNamespaces: foundUser.namespaces});
}
Mongoose does some optimizations where it will only actually save a field if it "changes". In this case you are modifyting an array, but the array is still the "same" array as in it still === (equals) the previous array. You need to use a new array to replace namespaces.
For example:
foundUser.namespaces = [
...foundUser.namespaces.slice(0, indexOfNamespaces),
{ ...foundUser.namespaces[indexOfNamespaces], rooms: updatedRooms },
...foundUser.namespaces.slice(indexOfNamespaces + 1)
]
Now, when you save Mongoose will see a "new" array that !== (does not equal) the previous array because it is a new instance and it will save it.

Categories

Resources