Remove Object from Array in MongoDB given ID - javascript

I am making an application that works with playlists. I am using MongoDB with mongoose and storing videos in each playlist via an array, like so:
{
_id: ObjectId("61ca1d0ddb66b3c5ff93df9c")
name: "Playlist A"
videos: [
{
title: "Video 1",
url: "www.YouTube.com/video1",
startTime: "20",
endTime: "40",
_id: ObjectId("61ca1d1ddb66b3c5ff93e0ba")
},
...
]
}
I want to be able to remove a video from a playlist based on the _id of a video. I have tried looking online for solutions but the solutions I've found don't work. This is what I am trying:
Playlist.updateOne(
{ _id: req.params.playlistId },
{ $pull: { videos: { _id: req.params.vidId } } }
)
When I run the code above and log the result I get the following (not sure if this is relevant):
{
acknowledged: true,
modifiedCount: 1,
upsertedId: null,
upsertedCount: 0,
matchedCount: 1
}
Please let me know if you need any more information this is my first time posting a question :)

This is a TypeError req.params.vidId returns a string and mongoose is looking for Type ObjectId. The solution is to convert the string literal (req.params.vidId) to an ObjectId, like so:
Playlist.updateOne(
{ _id: req.params.playlistId },
{ $pull: { videos: { _id: mongoose.Types.ObjectId(req.params.vidId) } } }
)

Related

Update boolean value inside of nested array Mongoose

I have a Schema that holds an array of objects for comments and I would like to update the boolean value of the flagged comments accordingly, I have tried updateOne and aggregate but it isn't working out at this point, I have also tried to use $elemMatch but it isn't working.
The comment _id is being pulled from the front end element that has an ID that is the same as the id that needs to be pulled from MongoDB.
Comments Array within the question Schema:
comments: [
{
user: {
type: Object,
},
commentDate: {
type: Date,
default: Date.now()
},
flagged: {
type: Boolean,
default: false
},
flaggedDate:{type: Date},
comment: String,
}
],
function I tried to run last.
const id = req.params.id
const updateFlag = Question.updateOne(
{
comments: [
{
_id: id
}
]
},
{
$set: {
comments: [
{
flagged: req.body.flagged
}
]
}
}
)
Any help would be appreciated!
You can do it with positional operator - $:
db.collection.update({
"comments._id": "3"
},
{
"$set": {
"comments.$.flagged": true
}
})
Working example

Edit multiple objects in array using mongoose (MongoDB)

So I tried several ways, but I can't, I can modify several objects with the same key but I can't modify any with different keys, if anyone can help me is quite a complex problem
{
id: 123,
"infos": [
{ name: 'Joe', value: 'Disabled', id: 0 },
{ name: 'Adam', value: 'Enabled', id: 0 }
]
};
In my database I have a collection with an array and several objects inside which gives this.
I want to modify these objects, filter by their name and modify the value.
To give you a better example, my site returns me an object with the new data, and I want to modify the database object with the new object, without clearing the array, the name key never changes.
const object = [
{ name: 'Joe', value: 'Hey', id: 1 },
{ name: 'Adam', value: 'None', id: 1 }
];
for(const obj in object) {
Schema.findOneAndUpdate({ id: 123 }, {
$set: {
[`infos.${obj}.value`]: "Test"
}
})
}
This code works but it is not optimized, it makes several requests, I would like to do everything in one request, and also it doesn't update the id, only the value.
If anyone can help me that would be great, I've looked everywhere and can't find anything
My schema structure
new Schema({
id: { "type": String, "required": true, "unique": true },
infos: []
})
I use the $addToSet method to insert objects into the infos array
Try This :
db.collection.update({
id: 123,
},
{
$set: {
"infos.$[x].value": "Value",
"infos.$[x].name": "User"
}
},
{
arrayFilters: [
{
"x.id": {
$in: [
1
]
}
},
],
multi: true
})
The all positional $[] operator acts as a placeholder for all elements in the array field.
In $in you can use dynamic array of id.
Ex :
const ids = [1,2,..n]
db.collection.update(
//Same code as it is...
{
arrayFilters: [
{
"x.id": {
$in: ids
}
},
],
multi: true
})
MongoPlayGround Link : https://mongoplayground.net/p/Tuz831lkPqk
Maybe you look for something like this:
db.collection.update({},
{
$set: {
"infos.$[x].value": "test1",
"infos.$[x].id": 10,
"infos.$[y].value": "test2",
"infos.$[y].id": 20
}
},
{
arrayFilters: [
{
"x.name": "Adam"
},
{
"y.name": "Joe"
}
],
multi: true
})
Explained:
You define arrayFilters for all names in objects you have and update the values & id in all documents ...
playground

How to conditionally add a field based on match a field with an array Mongo

I'm trying to create a pipeline to add a field based in a condition:
I have a field called helpful which is an array that will contain a list of id's, what I want to do is add a field depending if a given ID is insided that array
an example of the data structure may be this:
{
helpful: [ 5ecd62230a180f0017dc5342 ],
verifiedPurchase: false,
_id: 5f789010e07e4033342c7307,
title: 'text',
body: 'text',
rating: 3,
user: {
_id: 5ecd62230a180f0017dc5342,
name: 'store11',
picture: 'pictureurl'
},
replies: [],
updatedAt: 2020-10-03T18:04:48.026Z,
createdAt: 2020-10-03T14:52:00.410Z,
helpfulCount: 1,
helpfulForMe: false
},
I already tried with this pipeline
{
$addFields:{
helpfulForMe: {
$cond: {
if: {"$in":[user, "$helpful"] } ,
then: true,
else: false,
}
}
}
},
and this one
"$addFields": {
"helpfulForMe" : {
"$in":[
['5ecd62230a180f0017dc5342'], "$helpful"
]
}
}
},
but both returned false even when I set a matching ID
I hope to get a good fix from you guys. Thanks
You can try if your input is array of ids,
$reduce to iterate loop of helpful array and check condition if id in user array then return true otherwise false
let user = ["5ecd62230a180f0017dc5342"];
{
$addFields: {
helpfulForMe: {
$reduce: {
input: "$helpful",
initialValue: false,
in: {
$cond: [{ $in: ["$$this", user] }, true, "$$value"]
}
}
}
}
}
Playground

How to find specific nested objects without knowing the parent key in mongodb

I'm using javascript and the mongoose module.
I have an object like this
my_object = {
ShopName: String,
employees: [String],
info: {
NameEmployee_1: {
age: String,
work: String,
city: String,
},
NameEmployee_2: {
age: String,
work: String,
city: String,
}
}
}
and i want
find all the emoplyees that have a specific age but without knowing the name of the emplyee, is there a way for do this?
I know that you for example i can so something like this
db.collection.find({'info.Max': {$exists: true}})
for find all the Shops that have atleast one employee with name Max
but what if i want all the Shops that have atleast one emplyee that has age 33
db.collection.find({'info.<name>.age': '33'}) ?
You can utilize the $objectToArray (mongoDB 3.4.4 and up), $filter and $project and get something like this:
db.collection.aggregate([
{
$project: {
obj: {
$objectToArray: "$info"
}
}
},
{
$project: {
_id: 0,
obj: {
$filter: {
input: "$obj",
as: "item",
cond: {
$eq: [
"$$item.v.city",
"NY"
]
}
}
}
}
},
{
$project: {
info: {
$arrayToObject: "$obj"
}
}
},
])
You can see it working here
The idea is to break the object to array, filter it and then convert that array back to object.
I filtered on city but I am sure you get the idea.

Find and filter array elements in mongo/meteor

I have some documents like this:
{
_id: "exampleid",
email: "ex#example.pt",
sites:[
{
_id: "site1",
user: "user1",
pass: "pass1",
info: "info1",
date: "date1"
},
{
_id: "site2",
user: "user2",
pass: "pass2",
info: "info2",
date: "date2"
}
]
}
And i want to perform a query that returns all the documents that are in the "site1", but only with the fields _id, user, info and date of that site, so i did this query:
collection.find({ "sites._id": "site2" },{ fields: { "sites.$": 1 } });
So basically i don't want the other sites to be returned but i also don't want the pass of that site to be returned, i tried this:
collection.find({ "sites._id": "site2" },{ fields: { "sites.$.pass": 0 } });
But it says that i can't exclude array elements with the positional operator, so i need to know how else can i remove the "pass" field from the results so that i can return all the documents still in a cursor but without the pass field.

Categories

Resources