Where condition with Mongoose Paginate - node.js

I am applying Mongoose Paginate on a page that was previously just displaying all records. My original code in my controller looks like this:
let allEvents = await Event.find(queryObject).where('date').gte(todayFormatted).sort({'date': 1, 'startTime': 1}).populate("vendors");
Applying the pagination, the new code looks like this:
const events = await Event.paginate(queryObject, {
page: req.query.page || 1,
limit: 30,
populate: 'vendors likes',
sort: { 'date': 1, 'startTime': 1 }
});
However, I still need to apply the condition 'where date is greater than or equal to todayFormatted'. But it seems that Paginate does not natively support where conditions; can anyone please advise how I could add a similar condition to filter the records (i.e. not display events with a date in the past)?
Thanks

you can always write it this way, you will be able to paginate with page (default of 1) and per (default of 30)
const { per, page } = req.query
const limit = parseInt(per || 30)
const skip = parseInt(per || 30) * ((parseInt(page) || 1) - 1)
queryObject.date = { $gte: todayFormatted }
let events = await Event
.find(queryObject)
.limit(limit)
.skip(skip)
.sort({ 'date': 1, 'startTime': 1 })
.populate("vendors");
if you are already filtering by date in the query, you can add $and
https://docs.mongodb.com/manual/reference/operator/query/and/

Related

Implementing mongodb pagination along with match query?

I have user document as this
users = [
{
_id:'',
name:'jay',
email:'jay#gmail.com',
role: 'actor',
status: true // isActive
},
{
_id:'',
name:'ram',
email:'ram123#gmail.com',
role: 'electrician',
status: false // isActive
},
...... so on
]
I want to apply pagination and also some filters to retrieve data
filter = {
role: 'actor',
order: -1 //descending sort,
sortOn: 'name' // apply sort on name field
search: 'ja', // match the string starting with 'ja',
status: true,
size:25,
page: 1 // means documents from 1-25, page2 means 26-50
}
How can this be achieved?
I am using mongoose as well.
Using your filter object you can do something like this:
Use these steps to ensure a good pagination:
Sort by any value (to ensure not get random positions)
Skip by the number of pages
Limit by the number of elements into page
So, the query will be something like (not tested but you can see the idea):
const elementsPerPage = filter.size
const nSkip = elementsPerPage * filter.page
const sort = {[filter.sortOn]:filter.order}
YourModel.find({/*yourquery*/})
.limit(elementsPerPage)
.skip(nSkip)
.sort(sort)
Also, you can use filter values into your query, something like:
YourModel.find({
role: filter.role,
status:filter.status,
name:{ $regex: filter.search}
})
This query is like this example.
Also, is not defined what calues do you want to use, the condition etc, so, with this, you can use if/else to add or not values into query.
For example:
var query = {}
if(filter.search){
query.name = {$regex: filter.search}
}
So all together can be:
const elementsPerPage = filter.size
const nSkip = elementsPerPage * filter.page
const sort = {[filter.sortOn]:filter.order}
var query = {}
if(filter.search){
query.name = {$regex: filter.search}
}
if(filter.role){
query.role = filter.role
}
if(filter.status){
query.status = filter.status
}
YourModel.find(query)
.limit(elementsPerPage)
.skip(nSkip)
.sort(sort)
Note that this has not been tested, but as I've said before you can see the idea with this example.

TypeORM : Generate query with nested AND and OR

I am using NodeJS + TypeORM + PostgreSQL
I find it difficult to generate queries based on my requirements.
I need to generate the following query:
select * from clinics where status = 1 and (last_sync_date < x or last_sync_date is null)
Here x is current date - 10 days.
I tried the following query:
let now = Date();
now.setDate(now.getDate() - 10);
let clinics = await clinicRepo.find({
where: [
{ status: 1, last_sync_date: LessThan(now) },
{ last_sync_date: IsNull() }
]
});
But the result is this:
select * from clinics where (status = 1 and last_sync_date < x) or last_sync_date is null;
What do I need to change in the code above?
I want to use find so that I can load relations as well.
You can solve this by creating the query with js conditions and then assign it to the FindConditions.
For example:
const whereCondition = testResultId ?
{patientId, id: Not(testResultId), clinicId} :
{patientId, clinicId}
const tr = await TestResult.findOne({
where: whereCondition,
})
Or you can use Raw operator:
let clinics= await clinicRepo.find({
where : [
{status: 1,
last_sync_date: Raw(alias => `(${alias} < ${now} OR ${alias} IS NULL)`}
]
});

mongoose .find with pagination returning 0 elements

I'm trying to get pagination working properly, but for some reason, mongoose is returning zero items.
Here's the relevant code in nodejs:
if (req.query.name) {
match.name = req.query.name;
}
// initial pageSize is 2
// initial page is 1
pageSize = parseInt(req.query.pagesize);
page = parseInt(req.query.page);
const foods = await Food.find({ match })
.skip(pageSize * (page - 1))
.limit(pageSize);
res.send({
foods,
});
Now, I've used this same technique using .populate with a different route and have gotten the result I'm looking for like so:
await req.user
.populate({
path: 'pets',
options: {
limit: req.query.pagesize,
skip: req.query.pagesize * (req.query.page - 1),
},
})
.execPopulate();
I can't figure out what's wrong. There's 20 items in the database. If I remove the .limit and .skip and just have the .find, I retrieve all the items.
It seems like you are pasting in the wrong value to .find()
Shouldn't you place .find({name: req.query.name}) or .find(match) in your case??
Now it says ({match: {name: req.query.name}}) wich doesn't work I believe

Node Js sequelize select query by month

Am new in Node Js, In my Node Js project am using sequelize ORM with MySql database.
This is my query i want to write select query by month.
This is my query SELECT * FROM cubbersclosure WHERE MONTH(fromDate) = '04'
Here fromDate field type is date
This my code:
var fromDate = '2019-04-01'
var fromDateMonth = new Date(fromDate);
var fromMonth = (fromDateMonth.getMonth()+ 1) < 10 ? '0' + (fromDateMonth.getMonth()+1) : (fromDateMonth.getMonth()+1);
CubbersClosure.findAll({
where:{
// select query with Month (04)... //fromMonth
}
}).then(closureData=>{
res.send(closureData);
}).catch(error=>{
res.status(403).send({status: 'error', resCode:200, msg:'Internal Server Error...!', data:error});
});
Here fromMonth get only month from date, so i want to write code select query by month.
I'm not sure but what about try this?
where: {
sequelize.where(sequelize.fn("month", sequelize.col("fromDate")), fromMonth)
}
for those of you looking for postgres, this is a somewhat hacky way to make this work (make sure to unit test this):
const results = await models.users.findAll({
where: this.app.sequelize.fn('EXTRACT(MONTH from "createdAt") =', 3)
});
you can also take this a step further and query multiple attributes like so:
const results = await models.table.findAll({
where: {
[Op.and] : [
this.app.sequelize.fn('EXTRACT(MONTH from "createdAt") =', 3),
this.app.sequelize.fn('EXTRACT(day from "createdAt") =', 3),
]
}
});

How to make pagination with mongoose

I want to make a pagination feature in my Collection. How can find a documents with 'start' and 'limit' positions and get total document number in a single query?
You can't get both results in one query; the best you can do is to get them both using one Mongoose Query object:
var query = MyModel.find({});
query.count(function(err, count) {...});
query.skip(5).limit(10).exec('find', function(err, items) {...});
Use a flow control framework like async to cleanly execute them in parallel if needed.
You can use the plugin Mongoose Paginate:
$ npm install mongoose-paginate
After in your routes or controller, just add :
Model.paginate({}, { page: 3, limit: 10 }, function(err, result) {
// result.docs
// result.total
// result.limit - 10
// result.page - 3
// result.pages
});
If you plan to have a lot of pages, you should not use skip/limit, but rather calculate ranges.
See Scott's answer for a similar question: MongoDB - paging
UPDATE :
Using skip and limit is not good for pagination. Here is the discussion over it.
#Wes Freeman, Gave a good answer. I read the linked pose, you should use range query. n = 0; i = n+10; db.students.find({ "id" : { $gt: n, $lt: (n+i)} } );
OLD ANSWER (don't use this)
use something like
n = db.students.find().skip(n).limit(10);
//pass n dynamically, so for page 1 it should be 0 , page 2 it should be 10 etc
more documentation at http://www.mongodb.org/display/DOCS/Advanced+Queries
user.find({_id:{$nin:friends_id},_id:{$ne:userId}},function(err,user_details){
if (err)
res.send(err);
response ={
statusCode:200,
status:true,
values:user_details
}
res.json(response);
}).skip(10).limit(1);
I am using this function,
You can check if prev and next data is available or not.
async (req, res) => {
let { page = 1, size = 10 } = req.query
page = parseInt(page)
size = parseInt(size)
const query = {}
const totalData = await Model.find().estimatedDocumentCount()
const data = await Model.find(query).skip((page - 1) * size).limit(size).exec()
const pageNumber = Math.ceil(totalData / size)
const results = {
currentPage: page,
prevPage: page <= 1 ? null : page - 1,
nextPage: page >= pageNumber ? null : page + 1,
data
}
res.json(results) }
To know more estimatedDocumentCount

Resources