How do I push to the inner arrays in MongoDB?
[
{ emoji1: ['user19', 'user20', 'user21']},
{ emoji5: ['user12', 'user13', 'user14']},
{ emoji9: ['user29', 'user30', 'user34']}
]
I tried:
await Post
.updateOne({ _id: postID }, {
$push: {
[`reactions[0].emoji1`]: 'random user'
}
})
...where Post is my Mongoose Schema and "reactions" is the array above. I think I am doing something wrong in $push.
The result should be:
[
{ emoji1: ['user19', 'user20', 'user21', 'random user']},
{ emoji5: ['user12', 'user13', 'user14']},
{ emoji9: ['user29', 'user30', 'user34']}
]
You can use this query:
db.collection.update({
id: 1,
"reactions.emoji1": {
"$exists": true
}
},
{
"$push": {
"reactions.$.emoji1": "random user"
}
})
Example here
Related
I'm trying to concat two arrays with aggregate. However, output is showing Cannot read properties of undefined (reading 'allAddresses'). And wanted to implement in EJS. How can I achieve that? There is a code below:
app.post('/indexReplaced.html', (req, res) => {
Address.find({}, function(err, item){
const response = Address.aggregate([
{
$group: {
_id: null,
addresses: {
$push: "$addresses"
}
}
},
{
$project: {
allAddresses: {
$reduce: {
input: "$addresses",
initialValue: [],
in: {
"$concatArrays": [
"$$value",
"$$this"
]
}
}
}
}
}
]);
const allAddresses = response[0]["allAddresses"];
res.render("indexCalculated", {
address: item,
allAddresses: allAddresses
})
})
});
P.S: Tried to nest aggregate pipeline into Address.find() to render the collection as well. I hope it doesn't affect the pipelane.
I need to find and update documents with category that corresponding to the query. Array could contain mo than one corresponding id.
Query:
{
"ids": ["61f1cda47018c60012b3dd01", "61f1cdb87018c60012b3dd07"],
"userId": "61eab3e57018c60012b3db3f"
}
I got collection with documents like:
`{
"_id":{"$oid":"61f1cdd07018c60012b3dd09"},
"expenses":[
{"category":"61eafc104b88e154caa58616","price":"1111.00"},
{"category":"61f1cdb87018c60012b3dd07","price":"2222.00"},
{"category":"61f1cda47018c60012b3dd01","price":"1241.00"},
{"category":"61f1cdb87018c60012b3dd07","price":"111.00"}
],
"userId":"61eab3e57018c60012b3db3f"
}`
my method:
async myMethod(ids: [string], userId: string) {
try {
const { ok } = await this.ExpensesModel.updateMany(
{"userId": userId, "expenses.category": { $in: ids }},
{$set: {"expenses.$.category": "newCategoryID"}}
);
return ok
} ........
I path array of ids ["61f1cda47018c60012b3dd01","61f1cdb87018c60012b3dd07","61f1cdb87018c60012b3dd07"] and userId, this code update only 1 category by document.
So can i made it with mongo build in methods? or i need to find matching document and update it it by my self and after that update or insert;
Update with arrayFilters
db.collection.update({
"expenses.category": {
$in: [
"61f1cda47018c60012b3dd01",
"61f1cdb87018c60012b3dd07"
]
}
},
{
$set: {
"expenses.$[elem].category": "61eab3e57018c60012b3db3f"
}
},
{
arrayFilters: [
{
"elem.category": {
$in: [
"61f1cda47018c60012b3dd01",
"61f1cdb87018c60012b3dd07"
]
}
}
]
})
mongoplayground
I have a mongo schema like this.
{
userID:19202,
products:[ { id:020, name:'first' }]
}
I want to pop items from the product array based on id. I used the following command. although it didn't give any error, it also not deleting elements from an array.
userCart.updateOne(
{ userID:userID},
{ $pull: { products: { id:id } } }
)
.then((data) =>
{
if(data)
{
//data is {
"n": 1,
"nModified": 0,
"ok": 1
}
return res.json({
status:true,
message:"cart updated"
})
}
})
Demo - https://mongoplayground.net/p/mh6fXN21vyR
Make sure id and products.id are of the same type as in your document in the database. As your sample, both should be numbers.
if they both are number
db.collection.update({
userID: 19202
},
{
$pull: {
"products": { id: 20 }
}
})
Not Working here - https://mongoplayground.net/p/3zhv8yoH2o9 when "products": { id: "20" }. products.id is a string in the mongo query and in the database in number so mismatched.
Try this one:
db.userCart.update(
{ userID:userID },
{ $pull: { items: { id: 020 } } },
false, // Upsert
true, // Multi
);
I have array of strings like this
let fromHour = ['2.5','3','3.5']
let toHour = ['2.5','3','3.5']
I have an array of object saved in mongoDB
timeRange = [
{
from:'2.5',
to:'3'
},
{
from:'3',
to:'3.5'
}
]
I want to check if any of my array of string value exist in that object value
I have tried this but it give me this error ( Unrecognized expression '$match' )
checkAppoint = await Appointment.aggregate([
{
$project: {
date: myScheduleFinal[k].date,
status: { $in: ['pending', 'on-going'] },
timeRange: {
'$match': {
'from': { $in: fromHolder },
'to': { $in: toHolder },
},
},
},
},
]);
also I have tried this solution and it work for me but it take to much time so I am trying this with aggregate
checkAppoint = await Appointment.findOne({
date: myScheduleFinal[k].date,
status: { $in: ['pending', 'on-going'] },
timeRange:{$elemMatch:{
from:{$in:fromHolder},
to:{$in:toHolder}
}}
});
So anyone have a solution for that
Just try $elemMatch and $in operators,
using find() method
checkAppoint = await Appointment.find({
timeRange: {
$elemMatch: {
from: { $in: fromHour },
to: { $in: toHour }
}
}
})
Playground
using aggregate() method
checkAppoint = await Appointment.aggregate([
{
$match: {
timeRange: {
$elemMatch: {
from: { $in: fromHour },
to: { $in: toHour }
}
}
}
}
])
Playground
So I have found a way around to solve this problem and I will share the solution I used
First I want to minimize my request to mongodb so I am now making just one request that bring all the appointment with the required date
and I want to make it this way because my fromHour and toHour array will change many time through single request
helperArray => contains all the day I want to check it's range
let checkAppoint = await Appointment.find({
date: { $in: helperArray },
status: { $in: ['pending', 'on-going'] },
});
now inside my for loop I will go through that data
checkAppoint.filter((singleAppoint) => {
if (singleAppoint._doc.date === myScheduleFinal[k].date) {
singleAppoint._doc.timeRange.map((singleTime) => {
if (fromHolder.includes(singleTime.from)) {
busy = true;
}
});
}
});
So this is how my document looks like
"donator": [
{
"_id": "5edbd7d182af1f5aceab62bb",
"donatorName": "Niki",
"donationValue": 5000000
},
{
"_id": "5edbd7d182af1f5aceab62bc",
"donatorName": "Brian",
"donationValue": 5000000
}
],
"currentValue" : 1000000
I get my currentValue from donationValue sum in donator array :
donator.reduce((a, { donationValue }) => a + donationValue,0);
and I want to update the document by adding new object in donator array, and automatically updates currentValue field when the data updated.
I tried using aggregate
MyCollection.findByIdAndUpdate(id, [
{
$set: req.body,
$set: { currentValue: { $sum: { $sum: donator.donationValue } } },
},
]);
It's a good practice to sanitise your input and not directly use req.body.
so let's say
const donator = sanitizeDonator(req.body)
Then you can add donator and update currentValue as follows.
Note that _id on donator won't be auto generated by the update query, so it has to be present in the donator object.
MyCollection.findByIdAndUpdate(id, [
{
$set: {
donator: {
$concatArrays: ["$donator", [donator]] // adding donator to the last element
}
}
}, {
$set: {
currentValue: {
$reduce: {
initialValue: 0,
input: "$donator",
in: {
$add: ["$$this.donationValue", "$$value"]
}
}
}
}
}
]);
Relevant APIs
$concatArrays,
$reduce