I'm struggling with the syntaxis to updateOne a specified value inside an object inside an array.
This is my array of objects from my model
nombre:{type:String},
MaterialesProductos:[{Descripcion:{type:String},cantidad:{type:Number},codigo:{type:String},preciounitario:{type:Number},familia:{type:String}}]
This is how I insert values
await Producto.updateOne({nombre:req.body.ProductoAEditar}, { $push: {MaterialesProductos: {cantidad:req.body['MaterialesProductos[cantidad]'][a]}}});
But I would like to $set for example:
Producto.updateOne({"name:req.body.nameOfTheDocument", {InThisObject:{WhereCode:req.body.code},$set:{value:req.body.NewValue}});
await Producto.updateOne({nombre:req.body.ProductoAEditar},{MaterialesProductos:{codigo:req.body['MaterialesProductos[codigo]'][a]},$set: {cantidad:req.body['MaterialesProductos[cantidad]'][a]}});
This is how my data looks in my mongo atlas
nombre:"Aaron",
MaterialesProductos: Array
0:Object
Descripcion:
"Angulo 1/8" x 1 1/4" de 6.10 mts. (1.50 kg/mt)"
cantidad:0
codigo:"AA-03"
preciounitario:260.84
familia:"Aceros"
I think you want to use arrayfilters:
db.collection.updateOne({
nombre: "Aaron"
},
{
$set: {
"MaterialesProductos.$[item]": {
Descripcion: "Angulo 1/8 x 1 1/4 de 6.10 mts. (1.50 kg/mt)",
cantidad: 7,
codigo: "AA-03",
preciounitario: 460.84,
familia: "Aceros"
}
}
},
{
arrayFilters: [
{
"item.codigo": "AA-03"
}
]
})
See how it works on the playground example
Related
I want to update progress of the particular course by finding userId and coursename. I have seen all the MongoDB queries for that but still not getting the desired output. Sometimes got an empty array while data exist in DB. I am not getting if I have to add value inside the progress array then how I will apply the MongoDB query on that:
{
userId: "218u092ue029ie",
ABC:{
"courseName": "course1",
"progress": [
1,2,3
]
},
XYZ:{
"courseName": "course2",
"progress": [
1,2
]
},
pqr:{
"courseName": "course3",
"progress": [
1,2,3,4,5
]
}
}
Try like this:
db.yourCollection.updateOne(
{ userId: "218u092ue029ie", "ABC.courseName": "course1" },
{ $set: { "ABC.progress.$": [1, 2, 3, 4] } }
);
I am using a Mongo aggregated framework, suppose if I am having collection structure like this
{
{
_id: ObjectId(123)
name: john,
sessionDuration: 29
},
{
_id: ObjectId(456)
name: moore,
sessionDuration: 45
},
{
_id: ObjectId(789)
name: cary,
sessionDuration: 25
},
}
I want to query and create a pipeline such that it return something like this:
{
durationsArr: [29, 49, 25, '$sessionDuration_Field_From_Document' ];
}
I am doing this because I want to get average of durations from all the documents, so first adding all of it into an array, then I will add last stage where I do the $avg operation.
Any idea of how can I get the array of sessionDurationField. or do you have any other best approach to calculate the sessionDuration Average from the collection? please thoroughly explain am new to mongo aggregation.
$group - Group all documents.
1.1. $avg - Calculate the average of sessionDuration for all documents.
db.collection.aggregate([
{
$group: {
_id: null,
avgSessionDuration: {
$avg: "$sessionDuration"
}
}
}
])
Demo # Mongo Playground
I have an mongodb doc with an array of 100 elements and I want to get multiple elements from this array at given indexes given in query array.
example :
let query = [2,3,5,6,7,4,44,32,71];
So, I want to get elements in array in mongodb doc at indexes given in query array.
If you want filter data on mongo side, you can do like this.
db.getCollection('feed').find({
"_id" : {
"$in" : [
ObjectId("55880c251df42d0466919268"),
ObjectId("55bf528e69b70ae79be35006")
]
}
});
If not,
const filteredResult = items.filter(item => query.includes(item._id));
console.log(filteredResult);
there's no built-in mongodb operator that can support your requirement out of the box but... you can achieve it with a very difficult to read aggregation pipeline like this:
var query = [1, 3, 5]
db.Collection.aggregate(
[
{
$match: { "_id": ObjectId("5fd33ddd23505e1538b96116") }
},
{
$set: {
Array: {
$map: {
input: {
$filter: {
input: {
$map: {
input: "$Array",
as: "x",
in: {
Position: { $add: [{ $indexOfArray: ["$Array", "$$x"] }, 1] },
Value: "$$x"
}
}
},
as: "xx",
cond: { $in: ["$$xx.Position", query] }
}
},
as: "xxx",
in: "$$xxx.Value"
}
}
}
}
])
https://mongoplayground.net/p/_b1hzeUPlmu
I need to push multiple values into an array in mongoose using one call. I tried doing it using a smaller array but the array is getting inserted as a sub-array.
var kittySchema = new mongoose.Schema({
name: String,
values: [Number]
});
var Kitten = db.model('Kitten', kittySchema);
Kitten.update({name: 'fluffy'},{$push: {values:[2,3]}},{upsert:true},function(err){
if(err){
console.log(err);
}else{
console.log("Successfully added");
}
});
The result of the calling the above code thrice gives the below result:
{ "_id" : ObjectId("502b0e807809d79e84403606"), "name" : "fluffy", "values" : [ [ 2, 3 ], [ 2, 3 ], [ 2, 3 ] ] }
Whereas what I want is something like this:
{ "_id" : ObjectId("502b0e807809d79e84403606"), "name" : "fluffy", "values" : [ 2, 3 ,2 ,3, 2, 3] }
Another thing I noticed was that the type in the array (values) is specified as Number, then wouldnt the 'strict' option ensure that anything other than Numbers are not inserted ? In this case another array is being allowed to be inserted.
(Dec-2014 update) Since MongoDB2.4 you should use:
Kitten.update({name: 'fluffy'}, {$push: {values: {$each: [2,3]}}}, {upsert:true}, function(err){
if(err){
console.log(err);
}else{
console.log("Successfully added");
}
});
Deprecated see other solution below using $push $each
Your example is close, but you want $pushAll rather than $push to have each value added separately (rather than pushing another array onto the values array):
var Kitten = db.model('Kitten', kittySchema);
Kitten.update({name: 'fluffy'},{$pushAll: {values:[2,3]}},{upsert:true},function(err){
if(err){
console.log(err);
}else{
console.log("Successfully added");
}
});
Or use the $each modifier with $addToSet:
https://docs.mongodb.com/manual/reference/operator/update/addToSet/#each-modifier
// Existing tags array
{ _id: 2, item: "cable", tags: [ "electronics", "supplies" ] }
// Add "camera" and "accessories" to it
db.inventory.update(
{ _id: 2 },
{ $addToSet: { tags: { $each: [ "camera", "accessories" ] } } }
)
Currently, the updated doc doesn't support $pushAll. It seems to have been deprecated.
Now the good choice is to use the combination of $push & $each
an example:
//User schema: {uid: String, transaction: [objects] }
const filter = {"uid": uid};
const update = {
$push: {
transactions: {$each: dataarr}
}
}
User.updateOne(filter, update, {upsert:true}, (err) => {
if(err){
console.log(err)
}
})
pass {upsert: true} at options to insert if the filter returns false.
Using MongoDB, I want to find all documents in one collection who's _id shows up in an array of sub-documents in another collection. Using the $in operator doesn't really work here, because I'm only trying to match against a single value in the sub-document.
Suppose I have the following document from db.foos:
{ _id: 1, foo: [ { bar_id: 1 }, { bar_id: 3 } ] }
and the following collection of db.bars:
{ _id: 1, foo: "bar" }
{ _id: 2, foo: "abr" }
{ _id: 3, foo: "rab" }
I want to find all documents in db.bars who's _id can be found in the foo array (returning db.bars with _id 1 and 3, in this case). Something like this:
var foos = db.foos.findOne( { _id: 1 } )
db.bars.find( _id: { $in: foos.foo.bar_id } )
Of course, that won't work. How would I go about accomplishing this?
You can use the collection.distinct method to get distinct _id values from the foo
db.bars.find({ '_id': { '$in': db.foos.distinct('foo.bar_id', {'_id': 1}) }})
Demo:
> db.foos.distinct('foo.bar_id', {'_id': 1})
[ 1, 3 ]
> db.bars.find({ '_id': { '$in': db.foos.distinct('foo.bar_id', {'_id': 1})}})
{ "_id" : 1, "foo" : "bar" }
{ "_id" : 3, "foo" : "rab" }