How to increase duration for multiple documents in mongoDB? - node.js

I have many documents in a collection of mongoDB. I want to increase the start_dateTime field by the given duration in minutes and the given user_id.
But that collection contains multiple documents for the given user_id. So I want to increase all start_dateTime by the given duration and the given user_id.
I got the following error
MongoError: Cannot increment with non-numeric argument:
{start_datetime: new Date(1570701481175)}
function delayworkTime(req,res,next)
{
const usrId = req.body.user_id;
var delays_by = req.body.delays_by;
try
{
Works.updateMany( {user_id: usrId},
{$inc: {start_datetime : moment().add(delays_by, 'minutes')}}
)
.then(function (delays)
{
console.log(delaysss);})
.catch(function (err)
{
console.error(err);
});
}
catch (err)
{
return res.status(500).json(err);
}
}

Related

MongoDB: query greater than value of x by a specfic value

I have a MongoDB database with documents representing locations on a map, the document structure is below.
I'am trying to query for documents with sw_x and sw_y value that is 1000 more or 1000 less than the value of the user location which i get from another post request.
This is my get request:
router.get('/getdata', (req, res) =>{
mongoose.connect(url, function(err, db) {
if (err) throw err;
db.collection("mArGo").find({}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
db.close();
});
})
})
Currently this returns all documents in the database, i just need to figure out how to filter them.
So in other words i need my query to return docs with sw_x, sw_y values that are greater than or less than the user location value by 1000
DB document example:
{
_id: new ObjectId("6172a1dcb5ce25759cd9506b"),
epsg: 25832,
filename: 'dom_657000_5354000_500.sfb',
offset_x: -650000,
offset_y: -5360000,
size_x: 500,
size_y: 500,
x_sw: 657000,
y_sw: 5354000
}
In the code, you can calculate min, max of x_sw and y_sw and pass it to query:
db.collection.find({
x_sw: { $gt: 656000, $lt: 658000 },
y_sw: { $gt: 5353000, $lt: 5355000 }
})

How can I filter arrays in mongodb using mongoose?

I have created database with two collections. Each of these collections connected with relations.
Here I want to pass one item _id and check whether it passed to other collection as foreign key. If it's passed, I want to filter all items which consist as _id. How can I do that. Here my mongoose query and screenshot of db. Thank you
route.get("/:id",(req,res)=>{
Vehicles.find({
categories: [req.params.id]
}, (err, data)=>{
if(err){
console.log(err);
}else{
console.log(data);
}
});
PS: For an example I want to get all vehicles which have category id "60c58c2dcf82de0780051378" inside categories array.
Following the mongo document, you can query for all documents where categories is an array that contains the objectId req.params.id as one of its elements.
Vehicles.find({
categories: req.params.id,
}, (err, data) => {
if (err) {
console.log(err);
} else {
console.log(data);
}
});

how to find a single field in mongoDB instead of entire document

I want to achieve the result as obtained by
SELECT AGE FROM COLL WHERE NAME="AYUSH";
I took the following approach
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("new");
//var query = { name:'ayush' };
//var age = {age : 1, _id:0};
dbo.collection("coll").find(
{ name:'ayush' },
{ age : 1, _id:0}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
db.close();
});
});
the result that i am getting is
[ { _id: 5a818b71d2029813505d736a,
name: 'ayush',
age: '22',
sex: 'm' } ]
From MongoDB documentation : Project Fields to Return from Query
Return the Specified Fields and the _id Field Only
A projection can explicitly include several fields by setting the
<field> to 1 in the projection document. The following operation
returns all documents that match the query. In the result set, only
the item, status and, by default, the _id fields return in the
matching documents.
db.inventory.find( { status: "A" }, { item: 1, status: 1 } )
The operation corresponds to the following SQL statement:
SELECT _id, item, status from inventory WHERE status = "A"
In your case, if you only want the field age, you have to suppress the other fields _id, name and sex as following :
dbo.collection("coll").find({ name:'ayush' },{age:1, _id:0, name:0, sex:0})...
The easiest way to do this would be to convert the result in to an array and then send that array as the response.
The code would look like:
dbo.collection("coll").find(
{ name:'ayush' },
{ age : 1, _id:0}).toArray(function(err, result) {
if (err) throw err;
var array = [];
array.push(result[0].age);
res.send(array);});
Moreover don't use mongoClient,use mongoose instead.its easier and better

Get total count along with Mongoose Query skip & limt

I have a json data which contains many objects. I want to limit the data for pagination and I need the total items count. Please help.
Model.find().skip((pageNumber-1)*limit).limit(limit).exec()
I want the count and skipped data in response.
You can use async library for running 2 queries at once. In your case you can run one query to get the number of documents and another for pagination.
Example with 'User' model:
var async = require('async');
var User = require('./models/user');
var countQuery = function(callback){
User.count({}, function(err, count){
if(err){ callback(err, null) }
else{
callback(null, count);
}
}
};
var retrieveQuery = function(callback){
User.find({}).skip((page-1)*PAGE_LIMIT)
.limit(PAGE_LIMIT)
.exec(function(err, doc){
if(err){ callback(err, null) }
else{
callback(null, doc);
}
}
};
async.parallel([countQuery, retrieveQuery], function(err, results){
//err contains the array of error of all the functions
//results contains an array of all the results
//results[0] will contain value of doc.length from countQuery function
//results[1] will contain doc of retrieveQuery function
//You can send the results as
res.json({users: results[1], pageLimit: PAGE_LIMIT, page: page, totalCount: results[0]});
});
async allows you to run a number of queries in parallel depending on the hardware you are using. This would be faster than using 2 independent queries to get count and get the required documents.
Hope this helps.
I have solved it with $facet and aggregate the following way in mongoose v3+:
const [{ paginatedResult, [{ totalCount }] }] = await Model.aggregate([{
$facet: {
paginatedResult: [
{ $match: query },
{ $skip: skip },
{ $limit: limit }
],
totalCount: [
{ $match: query },
{ $count: 'totalCount' }
]
}
}])
where the totalCount refers the total number of records matching the search query while the paginatedResult is only the paginated slice of them.
The problem with these solutions is that for every request you are doing two queries. This becomes problematic when you have a complex data structure and large data set as performance becomes an issue. Consider instead creating a special function that listens for the /resource?count=true or /resource/count GET methods and returns only the count.
You need to perform 2 queries to achieve that. One to get results and another to get total items amount with .count().
For example code you can watch at on of "paginator" for mongoose mongoose-paginate.
To performe only one query, you may use the find() method associated with promises and array slices. A small example would be:
getPaginated(query, skip, limit){
return this.model.find(query)
.lean()
.then((value)=>{
if (value.length === 0) return {userMessage: 'Document not found'};
const count = value.length;
//skip===0 must be handled
const start = parseInt(limit)*parseInt(skip - 1);
const end = start + parseInt(reqQuery.pagesize);
//slicing the array
value = value.slice(start,end);
//could return it another way...
value.push( { 'querySize': count });
return value;
})
.catch((reason)=>{
//...handling code
});
}

Unable to delete a document with passed "email" and "_id" anyhow

I wanted to delete a document with concerned _id and email when I click on "Remove task" in the HTML file.
Following is the code which removes that task:
I've passed value of email and _id(only hexadcemial string value) to the code:
collection.findOneAndDelete({email:email,_id:taskid},function (err, result) {
if (err) {
console.log(err);
} else {
console.log("Removed!");
console.log(result);
callback(result);
}
db.close();
});
But, the function is not recognizing _id that I've passed. The value of "taskid" variable is 566836bd8db43d3d56e23a4a i.e. only strings value from _id:
ObjectId("566836bd8db43d3d56e23a4a")
var taskid=566836bd8db43d3d56e23a4a;
I've tried every possible declaration of taskid to convert it so that the function could recognize the value of _id and match it:
var taskid= "ObjectId("+'"'+req.param('taskid')+'"'+")";
But till now, I am not able to match the _id with the taskid. Any fix?
if you are going to compare with ObjectId then
var ObjectId = require('mongoose').Types.ObjectId
collection.findOneAndDelete({email:email,_id:new ObjectId(taskid)},function (err, result) {
if (err) {
console.log(err);
} else {
console.log("Removed!");
console.log(result);
callback(result);
}
db.close();
});
Should work for you.
If you feel the job too hard for each and every query then you can create an new method.
String.prototype.toObjectId = function() {
var ObjectId = (require('mongoose').Types.ObjectId);
return new ObjectId(this.toString());
};
// Every String can be casted in ObjectId now
console.log('545f489dea12346454ae793b'.toObjectId());

Resources