Mongoose does not update my array in the database - arrays

I'm trying to update my collection with mongoose.
This is my Schema:
var FamilySchema = mongoose.Schema({
construction: {
type: Array,
default: [
["foundry", 0],
["farm", 0],
["sawmill", 0]
]
}
});
And this is my code:
app.put('/construction/updateConstruction/:id', (req, res) => {
let id = req.params.id;
Family.findById(id, (err, familiaDB) => {
if (err) {
return res.status(500).json({
ok: false,
err
});
}
if (!familiaDB) {
return res.status(400).json({
ok: false,
err
});
}
// I want to update the value of the posicion 0 in the array.
familiaDB.construction[0][1] = 1;
familiaDB.save();
console.log(familiaDB);
});
});
Result in console.log after making the request:
Escuchando puerto: 3000
Base de datos ONLINE
{ state: true,
construction:
[ [ 'foundry', 1 ],
[ 'farm', 0 ],
[ 'sawmill', 0 ],
_id: 5bb8d69c604625211c572ada,
__v: 0 }
In console.log everything is fine and updated, but in my db it is not updated. I have checked it many times in robomongo and never updates it.

The quickest way to do this would be with findOneAndUpdate:
Family.findOneAndUpdate(
{ _id: mongoose.Types.ObjectId("YOURID") },
{ $set: { 'construction.0.1': 'YourValue' }}
)
This will do it in one statement.
Now instead of doing this by index you can do it with $elemMatch and update the correct one via:
Family.findOneAndUpdate(
{_id: ObjectId("YOURID"), 'cons': { $elemMatch: { '0': 'foundry' }}},
{ $set: { 'cons.$.1': 'YourValue' } }
)

Related

How to update object inside array inside object?

I have the following Mongooose schema:
{
_id: {
type: String,
required: true
},
semesters: [
{
_id: {
type: String,
required: true
},
grades: [
{
subject: String,
literalGrade: String,
grade: Number,
credits: Number
}
]
}
]
}
I want to be able to update one grade that is inside semester's grades object using its id. I tried using MongoDb new multiple positional operator to no avail.
This is my current snippet:
User.findOneAndUpdate(
{
_id: req.params.user_id,
"semesters._id": req.params.semester_id
},
{
$set: {
"semesters.$[x].grades.$[y].subject": req.body.grades.subject,
"semesters.$[x].grades.$[y].literalGrade": req.body.grades.literalGrade,
"semesters.$[x].grades.$[y].grade": req.body.grades.grade,
"semesters.$[x].grades.$[y].credits": req.body.grades.credits
}
},
{
arrayFilters: [
{ "x._id": req.params.semester_id },
{ "y._id": req.params.grade_id }
]
},
(err, user) => {
if (err) return res.json(err);
res.send({
message: "Updated grade",
data: user
});
}
);
Couldn't get any results with the MongoDb positional operator, but found a way to programmatically do it with the help of Naing Lin Aung's answer. Here is the solution:
User.findOne(
{
_id: req.params.user_id,
"semesters.grades._id": req.params.grade_id
},
{ "semesters.$.grades": 1 },
(err, user) => {
if (err) return res.json(err);
let grades = user.semesters[0].grades;
let index = null;
for (let t in grades) {
if (grades[t]._id == req.params.grade_id) {
index = t;
break;
}
}
let grade = grades[index];
grade.subject = req.body.grades.subject;
grade.literalGrade = req.body.grades.literalGrade;
grade.grade = req.body.grades.grade;
grade.credits = req.body.grades.credits;
user.save(function(err) {
if (err) return res.json(err);
res.json({
message: "Updated grade",
data: user
});
});
}
);
You can take advantage of $[] syntax with arrayFilters
refer this link : https://docs.mongodb.com/manual/reference/operator/update/positional-all
db.col.update(
{ _id: req.params.user_id },
{ $set: { "semesters.$[cond1].grades.$[cond2].subject": req.body.grades.subject } },
{ arrayFilters: [ { "cond1._id": req.params.semester_id }, { "cond2._id": req.params.grade_id } ] })
You can similarly update other fields in $set

Remove id from array of objects in mongodb

I try to delete ObjectID in array of ObjectId.
My model:
let directoryCollection = new Schema(
{
email: { type: String },
directory: [{
name: { type: String },
list: [ {type: Schema.ObjectId} ]
}]
},
{collection: 'directory'}
);
I have a array of ObjectID in list.
My code for delete index in my array:
let id = mongoose.Types.ObjectId(req.body.id);
directoryModel.update({'email': email, 'directory.name': oldDirectory}, {$pull: {'directory.list': id} }, function (req, result) {
console.log(result);
res.json('ok');
});
But the result is:
{ ok: 0, n: 0, nModified: 0 }
Email variable and oldDirectory variable ara correct.
My ID is: 5b5e5f34cfcd3906c8e6aa20
Same in my database:
What is the problem ?
Thanks you !
Try this, Correct syntax to $pull from array of objects
directoryModel.update(
{ "email": email, "directory": { "$elemMatch": { "name": oldDirectory } } },
{ "$pull": { "directory.$.list": id } }
})

How to increment property's value(integer) inside .update() and $set mongoose?

I'm trying to find a document in my database using findOne() and then search that document for options array that contains objects. Then I check object's property if it's equal to pollOption then I want to increment that object's another property votes by 1, but I can't get that property's value so I can increment it. Please help.
Routes.js
router.post('/submitVote', function(req, res){
const {pollId, pollOption} = req.body;
Polls.findOne({_id: pollId}
).update({'options.option': pollOption}, {'$set': {
'options.$.votes': '', // INCREMENT BY 1 //
}}, function(err){
if(err){
return console.log(err);
} else {
return res.send('success');
}
});
});
Sample Model:
{
"_id": {
"$oid": "5b2ec4852a51d06734f71e79"
},
"options": [
{
"option": "Amazing!",
"votes": 0
},
{
"option": "Good.",
"votes": 0
}
],
"creator": "Guest",
"name": "Rate this website!",
"__v": 0
}
Polls.js - Schema
var mongoose = require('mongoose');
const Poll = new mongoose.Schema({
name: { type: String, required: true },
options: { type: Array, required: true },
creator: { type: String, default: 'Guest' }
});
const Polls = mongoose.model('Polls', Poll);
module.exports = Polls;

Express Response: Sending an Array as JSON

I'm having an issue trying to get data from my backend express api. I'm using mongodb and mongoose too. Here's my code:
Code:
const show = (req, res) => {
const product = {}
product.array = new Array()
console.log(req.cart.product[1])
for (let i = 0; i < req.cart.product.length; i++) {
Product.find({_id: ObjectId(req.cart.product[i])},function(err,products){
if (err) {
res.sendStatus(500)
} else {
product.array.push(products)
console.log(product.array)
}
})
}
req.cart.product = product.array
res.json({
cart: req.cart.toJSON({ virtuals: true, user: req.user })
})
}
Console.logs:
[ [ { _id: 5952b57ea52d092b8d34c6b0,
name: 'test00000',
price: 0,
description: 'test',
__v: 0 } ] ]
[ [ { _id: 5952b57ea52d092b8d34c6b0,
name: 'test00000',
price: 0,
description: 'test',
__v: 0 } ],
[ { _id: 5952b57ea52d092b8d34c6b0,
name: 'test00000',
price: 0,
description: 'test',
__v: 0 } ] ]
URL Response:
{
"cart": {
"_id": "5953b153d2108941d15a7fe9",
"updatedAt": "2017-06-28T13:38:27.406Z",
"createdAt": "2017-06-28T13:38:27.406Z",
"owner": "595153ad6f18427ef38c416b",
"__v": 0,
"product": [],
"id": "5953b153d2108941d15a7fe9",
"editable": false
}
}
Everything in the console logs is what I want to return in the products array for my response but it won't populate the array when I push it. Any thoughts?
You are trying to call asynchronous code, (e.g. Db query) inside the synchronous code (e.g. for-loop). That's why it returns data to client once it gets the data for the first time. You can async or promise.all to solve the problem.
var async = require('async')
const show = (req, res) => {
const product = {}
product.array = new Array()
console.log(req.cart.product[1])
async.each(req.cart.product, function(id, cb){
Product.find({_id: ObjectId(id)},function(err,products){
if (err) {
cb(err)
} else {
product.array.push(products)
console.log(product.array)
cb()
}
})
}, function(err){
if (err) {
return res.sendStatus(500)
} else {
req.cart.product = product.array
return res.json({
cart: req.cart.toJSON({ virtuals: true, user: req.user })
})
}
})
}
Promise based solution:
const show = (req, res) => {
const product = {}
product.array = new Array()
console.log(req.cart.product[1])
const promises = []
req.cart.product.forEach(function(id){
promises.push(Product.find({_id: ObjectId(req.cart.product[i])}))
})
Promise.all(req.cart.product.map(function(id) {
return Product.find({_id: ObjectId(id)})
})).then(function(products){
req.cart.product = product.array
return res.json({
cart: req.cart.toJSON({ virtuals: true, user: req.user })
})
}).catch(function(err){
return res.sendStatus(500)
})
}

mongoose push nested subdocument array

i need to push data in nested subdocument array:
this is my Json:
[
{
_id: "56cbe9727bab33a413216dd4",
company_name: "Star",
__v: 0,
created_at: "2016-02-23T05:09:06.754Z",
plan: [
{
plan_name: "Mediclassic",
plan_type: "Individual",
_id: "56cbe9727bab33a413216dd5",
created_at: "2016-02-23T05:09:06.756Z",
rate_card: [
{
zone: "zone-2",
suminsured: 150000,
premium: 2874,
size: "1A",
_id: "56cbe9727bab33a413216dd6",
benefits: {
hospitals: true,
copay: true,
cashless_hospital: true,
existing_disease_cover: true
},
age: {
min: "5M",
max: 35
}
}
]
}
]
}
]
I need to push my data in rate_card, i have tried something but its not working
below is my code:
AngularController.js
$scope.RateCardCreateAction = function(){
$scope.params = $routeParams.id;
console.log($scope.insurance.plan.rate_card);
$http.put('/auth/insurance-list/plan/new/rate_card/' + $scope.params, $scope.insurance.plan.rate_card).success(function(response){
console.log(response);
refresh();
});
};
mainRoutes.js
// New Rate Card
router.put('/secure/insurance-list/plan/new/rate_card/:id', function(req, res){
var id = req.params.id;
Insurance.update({'plan._id':id}, {$push :
{
'rate_card' : {
'zone' : req.body.zone,
'suminsured' : req.body.suminsured,
'premium' : req.body.premium,
'size' : req.body.size,
'age' : {
'min' : req.body.age.min,
'max' : req.body.age.max
},
'benefits' : {
'hospitals' : req.body.benefits.hospitals,
'cashless_hospital' : req.body.benefits.cashless_hospital,
'copay' : req.body.benefits.copay,
'existing_disease_cover' : req.body.benefits.existing_disease_cover
}
}
}
}, {upsert: true}, function(err, docs){
res.json(docs);
console.log(docs);
});
});
Here i need to push data to rate_card, but data is not storing in subdocument array, here am getting plan id and trying to push but is not working
in server response am getting this { ok: 0, n: 0, nModified: 0 }
Try this, i hope this will help you
router.put('/secure/insurance-list/plan/new/rate_card/:id/:id2', function(req, res){
var id = req.params.id;
var id2 = req.params.id2;
Insurance.update({_id:id, 'plan._id':id2}, {$push :
{'plan.$.rate_card' : req.body}
}, {upsert: true}, function(err, docs){
res.json(docs);
console.log(docs);
});
});
If somehow your inserted value is not present then it would be great to use $addToSet.
var updateArr = {
'roomUsers':{
userId:req.session.userInfo._id,
requestDate:Date.now(),
status:1
}
};
roomInfo.findOneAndUpdate({_id:roomId}, {$addToSet:updateArr}, (err, result) => {
if (!err && result) {
res.send({
status:true
});
}
else{
res.send({
status:false
});
}
});
I got it done using below update query:
db.insurance.updateOne(
{
_id: ObjectId('60659595afcb710627e3fad7')
},
{
$push: {
"plan.$[element].rate_card": {
$each: [
{ _id: ObjectId('6062bd90c5a1d66fdd2c91bc'), premium: 2874, size: "1A" },
{ _id: ObjectId('6062bd90c5a1d66fdd2c91bc'), premium: 2874, size: "1A" }]
}
}
},
{
arrayFilters: [{ "element._id": ObjectId('6065a35ee1e5f1153504e861') }]
}
);
In $each you need to add your array of object.
element._id is your subdocument id (above case is plan _id).

Resources