Mongoose does not update values - node.js

I am trying to update a field's value in my MongoDB with mongoose. However, it does not update it correctly.
Here is what I have so far:
Test.findById(987456, function(err, doc) {
if (doc) {
var map = doc.data;
map['2019-07-07'] = {
TAS: "111",
TWS: "222",
TSWD: "333"
}
doc.set('data', map)
doc.save((err, doc1) => {
if(err) console.log(err);
else{
console.log(doc1)
}
});
}
})
This is my Schema
var test = new Schema({
data: { type: Schema.Types.Mixed, default: {} },
})
var Test = mongoose.model('test', test);
The data prior to updating inside the data field is { '2019-06-06': { TWS: '4', TAS: '27', TSWD: '33' }
The code does not throw any errors and console.log(doc1) inside the save callback prints the correct value { '2019-06-06': { TWS: '4', TAS: '27', TSWD: '33' },'2019-07-07': { TAS: '111', TWS: '222', TSWD: '333' }}
However, when I check MongoDB Atlas, the value is not changed at all.

Just use findOneAndUpdate:
let query = { id: 987456 } // or whatever your id / _id is
let update = { data: { TAS: "111", TWS: "222", TSWD: "333" }}
Test.findOneAndUpdate(query, update, function(err, doc) {
console.log(doc)
})

Related

merge aggregation and find results in MongoDB

I have this model:
const recordSchema = new Schema({
user: {
type: Schema.ObjectId,
ref: 'Person',
required: true
},
date: {
type: Date,
default: Date.now()
},
time: {
type: Date,
default: Date.now()
}
});
So, when I make a HTTP Get request I receive an array of records:
[{/*record1*/}, {/*record2*/}, ...]
The point is that I'm using aggregation to get the number of records of each user (I got that cover), but I would like merge this with the find results to receive something like this:
{
"records": [{/*record1*/}, {/*record2*/}, ...],
"stats": [
{
"_id" : ObjectId("5b6393f2a1d3de31d9547f63"),
"count" : 3.0
},
{
"_id" : ObjectId("5b5d22d8b6195d1b6a5d2574"),
"count" : 17.0
}
]
}
So, how do I get this?
Note: I'm using this for data for some charts, should I handle this on node or on the front-end?
This can be done in the back-end and if you're using MongoDB Server version 3.4.4 or greater in your backend, $facet aggregate pipeline should cover your needs.
Consider the following example which runs two aggregate queries in the same aggregate pipeline using $facet: one returns the records for today and the other returns the counts for each user in the collection:
let start = new Date();
start.setHours(0,0,0,0);
let end = new Date();
end.setHours(23,59,59,999);
Record.aggregate([
{ '$facet': {
'records': [
{ '$match': {
'date': {
'$gte': start,
'$lte': end
}
} }
],
'stats': [
{ '$group': {
'_id': '$user',
'count': { '$sum': 1 }
} }
]
} }
]).exec((err, results) => {
if (err) {
console.error(err);
throw new Error(err);
}
const data = results[0];
console.log(JSON.stringify(data, null, 4));
})
For MongoDB 3.2 and below
1. Using Promises
const recordsQuery = Record.find({ 'date': {
'$gte': start, // date object representing start of today
'$lte': end // date object representing end of today
} }).lean().exec();
const statsQuery = Record.aggregate([
{ '$group': {
'_id': '$user',
'count': { '$sum': 1 }
} }
]).exec();
Promise.all([ recordsQuery, statsQuery ]).then(([ recordsData, statsData ]) => {
const records = recordsData[0];
const stats = statsData[0];
const data = { records, stats };
console.log(JSON.stringify(data, null, 4));
}).catch(err => console.error(err));
2. Using async/await
(async () => {
try {
const recordsQuery = await Record.find({ 'date': {
'$gte': start, // date object representing start of today
'$lte': end // date object representing end of today
} }).lean().exec();
const statsQuery = await Record.aggregate([
{ '$group': {
'_id': '$user',
'count': { '$sum': 1 }
} }
]).exec();
const records = recordsQuery[0];
const stats = statsQuery[0];
const data = { records, stats };
console.log(JSON.stringify(data, null, 4));
} catch (err) {
console.error(err);
}
})();
You can use the $lookup operator to link the original records for the users by Id
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}

mongoDB find, update and pull in One Query

I want to do all the find the data from the collection and then want to update some field as well as depending on want to empty the array.
const addCityFilter = (req, res) => {
if (req.body.aCities === "") {
res.status(409).jsonp({ message: adminMessages.err_fill_val_properly });
return false;
} else {
var Cities = req.body.aCities.split(","); // It will make array of Cities
const filterType = { "geoGraphicalFilter.filterType": "cities", "geoGraphicalFilter.countries": [], "geoGraphicalFilter.aCoordinates": [] };
/** While using $addToset it ensure that to not add Duplicate Value
* $each will add all values in array
*/
huntingModel
.update(
{
_id: req.body.id,
},
{
$addToSet: {
"geoGraphicalFilter.cities": { $each: Cities }
}
},
{$set:{filterType}},
).then(function(data) {
res.status(200).jsonp({
message: adminMessages.succ_cityFilter_added
});
});
}
};
Collection
geoGraphicalFilter: {
filterType: {
type:String,
enum: ["countries", "cities", "polygons"],
default: "countries"
},
countries: { type: Array },
cities: { type: Array },
aCoordinates: [
{
polygons: { type: Array }
}
]
}
But as result, the only city array is getting an update. No changes in filterType.
You appear to be passing the $set of filterType as the options argument, not the update argument.
huntingModel
.update(
{
_id: req.body.id,
},
{
$addToSet: {
"geoGraphicalFilter.cities": { $each: Cities }
},
$set: {
filterType
}
}
).then(function(data) {
res.status(200).jsonp({
message: adminMessages.succ_cityFilter_added
});
});

Mongoose returning Object not Array

I've struggling trying to make my mongoose query return an array, since I need to:
Find 0..N docs from one collection;
Save this found array in another nested doc collection;
My code:
CarIndex.find({ '_id': { $in: ids } }, 'carID carBrand carModel location')
.then(collections => {
const out = []
collections.map( (doc) => {
const {carID ,carBrand ,carModel ,location} = doc
const car = {carID ,carBrand ,carModel ,location};
out.push(car)
})
console.log(out)
console.log(out.length)
console.log(typeof out)
return CarCollection.findOneAndUpdate({ '_id': collectionId }, { $addToSet: { carCollection: { $each: { out } } } })
});
The output error:
[04/01/2018 11:04:48.980] [LOG]
[ { carID: 'd82e41b0-f14f-11e7-b845-990cb852c2b3',
carBrand: 'Peugeot',
carModel: '207 Sed. Passion XR Sport 1.4 Flex 8V 4p',
location: [-23.539727799999998,-46.5111749] },
{ carID: 'd82f2c10-f14f-11e7-b845-990cb852c2b3',
carBrand: 'Nissan',
carModel: 'Sentra 2.0/ 2.0 Flex Fuel 16V Mec.',
location: [-23.607240972099525,-46.72912079051677] } ]
[04/01/2018 11:04:48.982] [LOG] 2
[04/01/2018 11:04:48.983] [LOG] object
[04/01/2018 11:04:48.997] [ERROR] MongoError: The argument to $each in
$addToSet must be an array but it was of type object
you can do like this
CarIndex.find({ '_id': { $in: ids } }, 'carID carBrand carModel location')
.then(collections => {
const out = []
collections.map( (doc) => {
const {carID ,carBrand ,carModel ,location} = doc
const car = {carID ,carBrand ,carModel ,location};
out.push(car)
})
console.log(out)
console.log(out.length)
console.log(typeof out)
return CarCollection.findOneAndUpdate({ '_id': collectionId }, { $addToSet: { carCollection: { $each: out } } })
});

How to perform update in mongoose

I am trying to update my record,but its not happening in my case and i am not sure about the case where it went rong,can any one suggest me help.Thanks
My mongoose code,
exports.updatestudent = function (req, res) {
var student = new Student(req.body);
var data = {};
var id = req.params;
var params = req.body;
var item = {
'name': params.name,
'rollnumber': params.rollnumber,
'class': params.class,
'city': params.city
};
Student.update({ _id: id },{ $set: item }, function (err, result) {
if (err) {
console.log('err');
}
if (result) {
data = { status: 'success', error_code: 0, result: result, message: 'Article updated successfully' };
res.json(data);
}
});
};
my schema,
var StudentSchema = new Schema({
name: {
type: String
},
rollnumber: {
type: String
},
class: {
type: String
},
city: {
type: String
},
status: {
type: String
},
_id: {
type: Schema.ObjectId
}
});
/**
* Hook a pre validate method to test the local password
*/
mongoose.model('student', StudentSchema, 'student');
my result in postman,
{
"status": "success",
"error_code": 0,
"result": {
"ok": 0,
"n": 0,
"nModified": 0
},
"message": "Article updated successfully"
}
I am trying to update my record,but its not happening in my case and i am not sure about the case where it went rong,can any one suggest me help.Thanks
It seems you forgot to specify the key.
Replace
var id = req.params;
By
var id = req.params.id;
Make sure that you are getting your id in var id = req.params;
And I am sure you will not get your id like this
check your req.params; values and give your correct id in the query
Update
var item = {};
if (params.name) {
item.name = params.name;
}
if (params.rollnumber) {
item.rollnumber = params.rollnumber
}
Student.update({
_id: id
}, {
$set: item
}, function(err, result) {
if (err) {
console.log('err');
}
if (result) {
data = {
status: 'success',
error_code: 0,
result: result,
message: 'Article updated successfully'
};
res.json(data);
}
});

elasticsearch search text return full array issue

I am using mongoosastic for elasticsearch. and i done all setup and its working fine. but problem is result are not getting properly.
FILE:- mongoose and mongoosastic.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var medicineSchema = require('./search')
var mongoosastic = require("mongoosastic");
var UserProfileSchema = new Schema({
userId: String,
username: String,
address: String,
number: Number,
task: [{
name: {
type: String,
es_boost: 2.0 // or es_indexed:true
},
taskCode: String,
}]
});
UserProfileSchema.plugin(mongoosastic);
UserProfileSchema.plugin(mongoosastic, {
host: "localhost",
port: 9200,
// ,curlDebug: true
});
UserProfile = module.exports = mongoose.model('UserProfile', UserProfileSchema);
UserProfile.createMapping(function(err, mapping) {
if (err) {
console.log('error creating mapping (you can safely ignore this)');
console.log(err);
} else {
console.log('mapping created!');
console.log(mapping);
}
});
And my search Query:
var UserProfileSchema = require('../../app/models/user');
UserProfileSchema.search({
query_string: {
query: name
}
}, function(err, result) {
if (err) {
callback({
RESULT_CODE: '-1',
MESSAGE: 'System error'
});
} else {
callback({
RESULT_CODE: '1',
DATA: result
});
}
});
Now my problem is if task array has 3 object and when i search for task string i.e "abc" it will return full collection. with all task But i want only searched string object from task array. i.e name :abc object
......
"task" [{
name: 'abc',
taskCode: 123
},{
name: 'xyz',
taskCode: 123
},{
name: 'cdx',
taskCode: 123
}]
The good thing is that your task field is already of type nested in your schema, which is a pre-condition for achieving what you expect.
Now in order to achieve what you want you need to use inner_hits in your query.
UserProfileSchema.search({
"query": {
"nested": {
"path": "task",
"query": {
"match": {
"task.name": name
}
},
"inner_hits": {} <--- this does the magic
}
}
}, ...

Resources