I am trying to create an add to cart button which fetches the data from product database using the id of specific product which I selected. I am trying to push the object found using the same Id into a normal javascript array and then to display it using ejs methods. While I was tring I found I am unable to push the data in object form.
Summary:
On 7th line I have declared an array and in that array I want to store some objects which I have fetched frome a db model.
On 15th line I am trying to push the object form into my array so that I could iterate through the objects to display them on my page using ejs. But I am unable to do that.
screenshots:
Here's the final result I'm getting even after trying to push objects in array:
empty array logged
Here are the objects I'm trying to push:
Objects
Code:
app.get("/cart", (req, res) => {
if (req.isAuthenticated()) {
const findcartdata = req.user.username;
userData.findOne({email: findcartdata}, (err, BookId) => {
// console.log(BookId.cartItemId);
const idArray = BookId.cartItemId;
var bookArray = [];
idArray.forEach((data) => {
productData.findOne({_id: data}, (err, foundBookData) =>{
// console.log(foundBookData);
if(err){
console.log(err);
}
else{
bookArray.push(foundBookData);
}
})
});
console.log(bookArray);
// res.render("cart", {
// cartBookArray: BookId.cartItemId
// })
});
} else {
res.redirect("/login");
}
})
In above code i found the user's email using passport authentication user method and using that email I wanted to add the products in a different javascript array (which I am goint to pass to my ejs file of cart and then iterate it on list) using those array of Id which I got from another model called userData. The problem is I am able to find userData of each Id but unable to store them as an array of objects.
Looks like a timing issue, your code completes before the database downloads the objects and pushes them to your array.
This should fix your issue:
// ...
const idArray = BookId.cartItemId;
var bookArray = [];
for (const data of idArray) {
const foundBookData = await productData.findOne({_id: data}).catch(console.error);
if (!foundBookData) continue;
bookArray.push(foundBookData);
}
console.log(bookArray);
// ...
By the way, make sure to make the whole function asynchronous as well, which would be done by changing this line:
userData.findOne({email: findcartdata}, async (err, BookId) => { // ...
Related
I have a large csv and I need to read t and insert to mongodb
Csv contains user name, category name and policy name.
Need to insert Users into User collection with category id and policy id. Csv provides only the category name and policy name. So I need to fetch category id from collection using its name.
If category name not exist, create a new one and returns its id. Same case for policy.
So I tried
fs.createReadStream('./data_sheet.csv')
.pipe(csv())
.on('data', async (row) => {
// console.log(row)
let res = await Category.findOneOrCreate({ name: row.cat.trim() });
console.log(res)
})
.on('end', () => {
console.log('CSV file successfully processed');
});
categorySchema.statics.findOneOrCreate = async function findOneOrCreate(condition) {
try {
const self = this
let agent = await self.findOne(condition)
console.log("condition")
console.log(condition)
console.log("agent")
console.log(agent)
if (agent) return agent._id
else {
agent = await self.create(condition)
return agent._id
}
} catch (e) {
console.log(e)
}
}
This is not working in proper manner. What is the proper way to do this?
If by not working you mean, the data is not coming up for category then make sure you follow the right async approach or else provide more info.
There are several things to keep in mind,
You might need to create a cronjob for recursive process
Import the csv file into an array of Object
Loop over the object to match with category Id
If not then create a category Id
Return to the main function
update the document [here you can either update all or update one at a time using the step 2 looping we did]
I am trying to update a mongoose document, But its a deeply nested array of objects and I am having trouble updating it using the spread operator. I have an array of image-links and I wanna iterate through the relationships array in the database and add an image to each relation. The code shows my approach, but the syntax is wrong. I have added a db image which shows where I wanna add the image variable.
// Get Images
const imagesData = await axios.get(
"https://randomuser.me/api/?results=4&gender=male"
);
const images = [];
imagesData.data.results.forEach((result) => {
images.push(result.picture.large);
});
// Update Company
for (let i = 0; i <= 3; i++) {
const updateCompany = await Companies.findByIdAndUpdate(
req.params.id,
{ relationships: [
...relationships,
relationships[i]: {
...relationships[i],
image: images[i]}
] },
{ new: true }
).exec();
}
Also I am using a mongoose query inside a for loop. Is it the right way to do it.
mognoDB
You should fetch the document that you want. Then treat the fetched object as a javascript object and add or update whatever you want then use .save() function provided by mongoose.
let result = await Companies.findById(id);
result = result.map((company)=>{
update your object here
})
result.save()
The .save() function will take care of updating the object in the database
I am making a bot using Discord.js and it only needs to track messages in a certain channel, which I currently have this hard-coded for testing purposes.
var { channelID } = require(`./config.json`);
bot.on("message", async (message) => {
const args = message.content.split(/ +/g);
if (message.channel.id === channelID) {
// ...
}
});
I would like for it to store multiple IDs in a JSON file and to have a [p]setchannel command, that would allow me to add one.
I tried this guide, with no luck.
What you probably want to do is store an array of IDs so that you can retrieve them later.
You should have a channelIDs property in your JSON file set to an empty array. Inside your code you can fetch it like this:
const { channelIDs } = require('./config.json') // Now it's an empty array: []
When you want to update this array you should update your local one first, and then you can update the config file: to do that you can use fs.writeFileSync() in combination with JSON.stringify().
const fs = require('fs')
function addChannelID(id) {
channelIDs.push(id) // Push the new ID to the array
let newConfigObj = { // Create the new object...
...require('./config.json'), // ...by taking all the current values...
channelIDs // ...and updating channelIDs
}
// Create the new string for the file so that it's not too difficult to read
let newFileString = JSON.stringify(newConfigObj, null, 2)
fs.writeFileSync('./config.json', newFileString) // Update the file
}
Once you set this function you can add a new ID every time you want, just by calling addChannelID('channel_id').
To check whether the channel the message is coming from should be considered you can use this:
if (channelIDs.includes(message.channel.id)) {
// OK
}
I am stuck in what I thought was a very simple use case: I have a list of client ids in an array. All I want to do is fetch all those clients and "watch" them (using the .onSnapshot).
To fetch the client objects, it is nice and simple, I simply go through the array and get each client by their id. The code looks something like this:
const accessibleClients = ['client1', 'client2', 'client3']
const clients = await Promise.all(
accessibleClients.map(async clientId => {
return db
.collection('clients')
.doc(clientId)
.get()
})
)
If I just needed the list of clients, it would be fine, but I need to perform the .onSnapshot on it to see changes of the clients I am displaying. Is this possible to do? How can I get around this issue?
I am working with AngularFire so it is a bit different. But i also had the problem that i need to listen to unrelated documents which can not be queried.
I solved this with an object which contains all the snapshot listeners. This allows you to unsubscribe from individual client snapshots or from all snapshot if you do not need it anymore.
const accessibleClients = ['client1', 'client2', 'client3'];
const clientSnapshotObject = {};
const clientDataArray = [];
accessibleClients.forEach(clientId => {
clientSnapshotArray[clientId] = {
db.collection('clients').doc(clientId).onSnapshot(doc => {
const client = clientDataArray.find(client => doc.id === client.clientId);
if (client) {
const index = clientDataArray.findIndex(client => doc.id === client.clientId);
clientDataArray.splice(index, 1 , doc.data())
} else {
clientDataArray.push(doc.data());
}
})
};
})
With the clientIds of the accessibleClients array, i create an object of DocumentSnapshots with the clientId as property key.
The snapshot callback function pushes the specific client data into the clientDataArray. If a snapshot changes the callback function replaces the old data with the new data.
I do not know your exact data model but i hope this code helps with your problem.
I am using firebase's .onSnapshot to grab the ID of the users currently online, and store each ID to an array. I successfully deployed .onSnapshot to get the ID of the online users, but I return an empty array at the end
var learning_language;
db.collection(ll_profile).doc(user_uid).get().then(function(doc) {
learning_language = doc.data().learning_language;
})
db.collection(ns_status).where("state", "==", "online").onSnapshot(function(snapshot) {
var ns_match = [ ];
snapshot.forEach(function(userSnapshot) {
db.collection("ns_profile").doc(userSnapshot.id).get().then(function(doc) {
spoken_language = doc.data().spoken_language;
if (learning_language == spoken_language) {
ns_match.push(userSnapshot.id);
console.log(ns_match);
}
})
})
return (ns_match);
What I am trying to do is to first define the learning_language retrieved from the collection ll_profile with the current user's ID named user_uid.
Then .onSnapshot listens to another group of users' online state (which automatically updates if an user is online or offline) inside ns_status collection. After, the returned online user from .onSnapshot is checked if the spoken_language field inside their document (named with their corresponding uid) matches with learning_language defined earlier. If it matches, then store the uid into the array of ns_match.
The values inside ns_match are correct. I think .get() executes asynchronously. That is why ns_match is returned empty.
How should I return ns_match at the end with all the values stored properly?
Thanks in advance.
function getMatches() {
return new Promise(resolve => {
db.collection(ll_profile).doc(user_uid).get()
.then(function(doc) {
var learning_language = doc.data().learning_language;
db.collection(ns_status)
.where("state", "==", "online")
.onSnapshot(function(snapshot) {
var ns_match = [];
snapshot.forEach(function(userSnapshot) {
db.collection("ns_profile")
.doc(userSnapshot.id)
.get()
.then(function(doc) {
spoken_language = doc.data().spoken_language;
if (learning_language == spoken_language) {
ns_match.push(userSnapshot.id);
console.log(ns_match);
}
});
});
resolve(ns_match);
});
});
});
}
getMatches().then(ns_matches => console.log(ns_matches));
wrapping in a promise is the correct move. However, remember that snapshot returns metadata about your result. Particularly, snapshot.size. One can use that value to count records, inside the foreach method, or compare the destination array length with the snapshot.size value