Return Mongoose query result through multiple methods - javascript

I'm trying to retrieve data from a MongoDB database using Mongoose to access the data, however I am trying to retrieve the data through a few methods. Here is my retrieveDocument method:
function retrieveDocument(collectionName, schema, _id) {
conn.once('open', async () => {
var model = mongoose.model(collectionName, schema, collectionName)
return await model.findById(_id)
});
}
and how I'm calling the method:
function retrieveUserDocument(_id){
return retrieveDocument("User", some_Schema, _id);
}
console.log(retrieveUserDocument("some_Id"));
However the result isn't being printed out, and instead the code is logging undefined, as the model.findById(_id) method returns a Promise.
How can I print out the result in the structure I have defined above?

I think you should try promise here. It might work and you should try await when you are calling mongoose model. Try the code which is written below
function retrieveDocument(collectionName, schema, _id) {
return new Promise(async(resolve, reject) => {
conn.once('open', async () => {
var model = await mongoose.model(collectionName, schema, collectionName)
resolve(model.findById(_id))
});
});
}

Related

FindOne inside map returns no results

I'm trying to do a search using FindOne inside map but it never finds the data by Product Id. I don't understand the reason. Im using express on nodejs.
This is my code:
const calc = (details) => {
let grandSubtotal = 0;
details.map( async detail => {
const {verifyProduct} = await Product.find({ _id: detail._id});
console.log(detail._id);
console.log(verifyProduct); // UNDEFINED
...
Should be:
const result = await Promise.all(details.map( async (detail) => { … } ));
when you do it like you done you will get a pending promise object that never going to be resolved, I don’t know if you want to return some results, if no just do await Promise.all
Also this should be:
const calc = async (details) => { … }
Mongoose find returns a list of results. findOne returns an object.
The code is doing the equivalent of:
const {verifyProduct} = []
Use findOne to get an object to destructure, and test the result before use.
details.map( async (detail) => {
const res = await Product.findOne({ _id: detail._id });
if (!res) {
//throw new Error('No id '.detail._id)
console.log('No id', detail._id)
}
const { verifyProduct } = res
console.log(detail._id);
console.log(verifyProduct);
}
Also (as #antokhio noted), if you want to use the returned result array of the details.map you will need to await those as well.
You don't need await here
Product.find(({ _id }) => _id === detail._id );

How to correctly resolve promise in a mongoDB call?

I am trying to read data from a mongoDB. Ultimately I want the data retrieved from the DB to be in json formate. My currently function goes as:
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true })
const getdata = async (): Promise<string[]> => {
let alldata: string[]
try {
await client.connect()
const database = client.db('data')
const collection = database.collection('datacollection')
const cursor = collection.find({ type: 'featureName' })
alldata = await cursor.toArray()
//console.log(alldata) //This correctly sends the required data to the console.
} finally {
void client.close()
}
//console.log(alldata) //This correctly sends the required data to the console.
return alldata
}
const data = getdata()
console.log(data) // this sends a "Promise { pending }"
I am new to javascript/typescript, but I thought that I was doing all the correct things with an asyc function and the await's -> but that clearly is not the case. Any suggestions as to what I am doing wrong is appreciated.
Your function is returning a Promise so you need to use promise.then.
E.g.
getData().then((data) => {
console.log(data);
});
Take a look at the Promise documentation here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Perform Firestore query in a JavaScript function

I want to perform a Firestore query in a JavaScript function, but I'm having some difficulties with promises.
Let's say I want to get the document ID from a user. So I have created this JavaScript function:
function getUid(email) {
db.collection("users").where("email", "==", email)
.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
return doc.id;
});
})
.catch(function(error) {
return error;
});
}
Now when I call the function res.send(getUid("user#example.com")), it returns undefined.
Which is the correct syntax to wait until the Firestore query finsished?
get() is an async function, so you need to wrap it into an async function. Also, you are not returning anything from the getUid function - you are just returning inside a forEach parameter. If you want to get all id from the snapshot, you can use the map function.
async function getUids(email) {
const db = admin.firestore();
const querySnapshot = await db.collection("users").where("email", "==", email).get();
const uids = querySnapshot.docs.map((doc) => { return doc.id });
return uids;
}
exports.yourFunction = functions.http.onRequest(async (req, res) => {
const email = // ...
res.send(await getUids(email));
});

await is only valid in async function - nodejs

I'm using node and express to create server for my app. This is how my code looks like:
async function _prepareDetails(activityId, dealId) {
var offerInfo;
var details = [];
client.connect(function(err) {
assert.equal(null, err);
console.log("Connected correctly to server");
const db = client.db(dbName);
const offers_collection = db.collection('collection_name');
await offers_collection.aggregate([
{ "$match": { 'id': Id} },
]).toArray(function(err, docs) {
assert.equal(err, null);
console.log("Found the following records");
details = docs;
});
})
return details;
}
app.post('/getDetails',(request,response)=>{
var Id = request.body.Id;
var activityId = request.body.activityId;
_prepareDetails(activityId,Id).then(xx => console.log(xx));
response.send('xx');
})
While calling getDetails API I am getting
await is only valid in async function error (At line await offers_collection.aggregate)
I am also getting red underline while declaring async function. Node version I'm using is 11.x. I'm also using firebase API. What am I doing wrong here?
You are missing the async declaration on one of your functions. Here is the working code:
async function _prepareDetails(activityId, dealId) {
var offerInfo;
var details = [];
client.connect(async function(err) {
assert.equal(null, err);
console.log("Connected correctly to server");
const db = client.db(dbName);
const offers_collection = db.collection('collection_name');
await offers_collection.aggregate([
{ "$match": { 'id': Id} },
]).toArray(function(err, docs) {
assert.equal(err, null);
console.log("Found the following records");
details = docs;
});
})
return details;
}
app.post('/getDetails', async (request,response)=>{
var Id = request.body.Id;
var activityId = request.body.activityId;
let xx = await _prepareDetails(activityId,Id);
response.send('xx');
})
Await can only be used in an async function, because await is by definition asynchronous, and therefore must either use the callback or promise paradigm. By declaring a function as async, you are telling JavaScript to wrap your response in a promise. Your issue was on the following line:
client.connect(function(err) {
This is where I added the async as mentioned before.
client.connect(async function(err) {
You will notice I made your route use async also, because you would've had an issue before. Notice the two lines in your original code:
_prepareDetails(activityId,Id).then(xx => console.log(xx));
response.send('xx');
Your response would send before you even made your database call because you are not wrapping the response.send within the .then. You could move the response.send into the .then, but if you are going to use async/await, I would use it all the way. So your new route would look like:
app.post('/getDetails', async (request,response)=>{
var Id = request.body.Id;
var activityId = request.body.activityId;
let xx = await _prepareDetails(activityId,Id);
response.send('xx');
})

How to update multiple Mongo documents manually in NodeJs?

I have a collection of users in MongoDB. I need to generate a token for each user and save it to the database:
var crypto = require('crypto');
db.users.find({}).exec(function(users){
users.forEach(function(user){
user.token = crypto.randomBytes(32).toString('hex');
user.save();
});
});
I'm always confused about async methods and just can't understand how they work... So this code doesn't work beacuse it exists before the save() calls finish. How would you make it work? How would you wait for all the save()˙calls and print Done! to console?
Thanks!
Mongoose find function returns a promise, you can use it to create chain. Promise.all produces promises (or a mix of promises and values), iterate over all the values and return a promise that is fulfilled when all the items in the array are fulfilled.
var crypto = require('crypto');
db.users
.find({})
.then(users => {
var ops = users.map(user => {
user.token = crypto.randomBytes(32).toString('hex');
return user.save();
});
return Promise.all(ops);
})
.then(() => console.log('done'))
.catch(err => console.log('error' + err));
});

Categories

Resources