Looping through array and executing MongoDB query (NodeJS) - javascript

I have an object name profile that contains a favorites array that looks like this...
{favorites: [
{ name: 'Love Song',
id: 'Itja90E2tIE'},
{ name: 'I Need Your Love',
id: 'AtKZKl7Bgu0'}
]}
I want to loop through that array, get the id of each favorite, and do a .find() for that ID in my songs collection of my mongo DB, get the song's artist, and add it to the array.
I've tried something like...
for(var i=0; i<profile.favorites.length; i++) {
db.songs.find({"_id" : profile.favorites[i].id}, {"artistName" : 1}, function (e, result){
profile.favorites[i]["artistName"] = result[0].artistName;
});
}
But that doesn't seem to working, (primarily because Mongo/MongoJs is async.)
What is the proper way to do something like this?

You can use $in to query an field that match with any value in the specified array.
favoritesId = favorites.map(function(favorite){ return favorite.id; });
db.songs.find({ _id: { $in: favoritesId }}, function(err, songs){
// do you favor
});

Related

How to remove data in object from MongoDB document

The object contains the username and category. Categories is another object that contains categories and costs. How can I remove all key-values ​​in a category object? Now in my code, using deleteOne() I find all the fields of the object named "Bob". I am deleting the entire document named "Bob". And I need to clear the categories in this document, for example, deleteOne({ name: "Bob", category }, and have { name: "Bob", category: {} } output to the console
let users = [
{
name: "Bob",
сategories: {
eat: "20$",
entertainment: "100$",
},
},
];
mongoClient.connect(function (err, client) {
if (err) return console.log(err);
const db = client.db("expensesdb");
db.collection("users").deleteOne({ name: "Bob" }, function (err, result) {
console.log(result);
client.close();
});
});
You can use updateOne method to set сategories as empty object using $set or you can use $unset to unset your сategories data.

Is there a way to update an object in an array of a document by query in Mongoose?

I have got a data structure:
{
field: 1,
field: 3,
field: [
{ _id: xxx , subfield: 1 },
{ _id: xxx , subfield: 1 },
]
}
I need to update a certain element in the array.
So far I can only do that by pulling out old object and pushing in a new one, but it changes the file order.
My implementation:
const product = await ProductModel.findOne({ _id: productID });
const price = product.prices.find( (price: any) => price._id == id );
if(!price) {
throw {
type: 'ProductPriceError',
code: 404,
message: `Coundn't find price with provided ID: ${id}`,
success: false,
}
}
product.prices.pull({ _id: id })
product.prices.push(Object.assign(price, payload))
await product.save()
and I wonder if there is any atomic way to implement that. Because this approach doesn't seem to be secured.
Yes, you can update a particular object in the array if you can find it.
Have a look at the positional '$' operator here.
Your current implementation using mongoose will then be somewhat like this:
await ProductModel.updateOne(
{ _id: productID, 'prices._id': id },//Finding Product with the particular price
{ $set: { 'prices.$.subField': subFieldValue } },
);
Notice the '$' symbol in prices.$.subField. MongoDB is smart enough to only update the element at the index which was found by the query.

Use a Mongo Cursor to build a list with another query

I have two mongo collections.
Enrollment:
{UserID: String, CourseID: String, EducatorFlag: boolean}
Courses
{_id: String, courseName: String}
I'm attempting to generate a list of courseNames when given a UserID. This requires me to find all courses that a User is enrolled in. The following function returns just the CourseID of each course a user is in.
var currentCourses = Enrollment.find(
{ UserId: Meteor.userId(), EducatorFlag: false },
{ fields: { CourseID: 1 });
I'm unsure of how to take this cursor, and use each item in it to run another query and build a list from the output. Basically for each CourseID in currentCourses I need to do
var result = []
result += Courses.find({_id: CourseID}, {fields: {_id: 0, courseName: 1}});
The goal is simply to print all the courses that a user is enrolled in.
You have several options:
Use the cursor directly with a .forEach()
Use .fetch() to transform the cursor into an array of objects and then manipulate that.
Get an array of _ids of enrollments with .map() and directly search the courses with mongo's $in
Let's just use the first one for now since it's pretty simple:
let courseNames = [];
Enrollment.find(
{ UserId: Meteor.userId(), EducatorFlag: false },
{ fields: { CourseID: 1 }).forEach((e)=>{
let course = Courses.findOne(e.CourseID, { fields: { courseName: 1 }})
courseNames.push(course.courseName);
});
Note: when selecting fields in a query you can't mix exclusions and inclusions.
Getting an array of _ids and using that with $in is also pretty straightforward:
let courseIdArray = Enrollment.find(
{ UserId: Meteor.userId(), EducatorFlag: false },
{ fields: { CourseID: 1 }).map((e)=>{ return e.CourseID });
let courseNames = Courses.find(
{ _id: { $in: courseIdArray }}).map((c)=>{ return c.courseName });

Mongodb: Find ids $in nested array property

I have the following data structure for my users in my mongodb:
{
_id: "someId",
profile: {
username: "oliv",
friendRequests: [
{ fromUserId: "anId", accepted: false, created: "someDate"},
{ fromUserId: "otherId", accepted: true, created: "otherDate"}
]
}
I'd like to retrieve the user objects that are referenced in my logged user's friendsRequested.
So I tried something like this:
Meteor.users.find({_id: {$in: Meteor.user().profile.friendRequests.fromUserId}});
// FYI: Meteor.users is the collection and Meteor.user() retrieves the current user
But it's not working. I'm assuming it's because of the nested array.
Is there any way of telling mongo to iterate through the fromUserId or something?
Thanks
Change your query to:
Meteor.users.find({_id: {$in: _.pluck(Meteor.user().profile.friendRequests, 'fromUserId') }});
Reasoning:
friendRequests is an array of objects, and $in wants an array of strings(the ids), using _.pluck you're able to pass an array of objects, and tell _ to only return the field fromUserId for each object in the array.
Question in comment ("what if I only want to get the ids from friend requests where "accepted" is false?"):
_.pluck(
_.filter(Meteor.user().profile.friendRequests, function (req) {
return !req.accepted;
}),
'fromUserid'
);
Underscore filter docs

How can I count all dupe values in a JSON collection?

I would like to count all the companies in the following JSON string. I was first planning on doing it manually with loops but it seems like this is a good chance for me to learn to use map/reduce... How can return something that returns {company: 2}?
[
{
_id: '123',
company: 'Acme'
}
{
_id: '123',
company: 'Innatrode'
}
{
_id: '123',
company: 'Acme'
}
]
If you want to get the number of unique company names, then
use _.pluck to get the company attribute out of the list of company objects
Find the unique values out of them with _.uniq, which will return an array.
Compose a new object with the key `com
console.log({company: _.uniq(_.pluck(companies, "company")).length});
# { company: 2 }

Categories

Resources