Let's say I have a event schema below
eventSchema = new Schema({
name: { type: String },
startDate: {type: Date },
endDate: {type: Date }
});
And I have a set of data:
{ name: 'Event 1'
startDate: '2017-06-23 09:58:03.759Z'
endDate: '2017-07-02 09:58:03.759Z'
},
{ name: 'Event 2'
startDate: '2017-07-05 09:58:03.759Z'
endDate: '2017-07-10 09:58:03.759Z'
}
{ name: 'Event 3'
startDate: '2017-07-23 09:58:03.759Z'
endDate: '2017-08-01 09:58:03.759Z'
}
{ name: 'Event 4'
startDate: '2017-08-03 09:58:03.759Z'
endDate: '2017-08-05 09:58:03.759Z'
}
How to write a query to find the events that occurred within 2017-07-01 to 2017-07-31?
Which means I need to get the data set of Event 1, 2 and 3.
Here is what I done so far:
Event.find({
$and: [
{ startDate: { $gte: start } },
{ endDate: { $lte: end } },
]
}, (err, events) => {
if (err) return next(err);;
res.send({ success: true, events: events });
});
Related
I have this mongoose schema, it stores user's salary
const salarySchema = new mongoose.Schema(
{
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true,
trim: true,
},
amount: {
type: String,
required: true,
trim: true,
},
paymentType: {
type: String,
required: true,
enum: [PAYMENT_TYPE],
default: PAYMENT_TYPE.MONTHLY,
},
startDate: {
type: Date,
required: true,
},
endDate: {
type: Date,
required: false,
default: null,
},
}
);
If I have a time frame given I want to query all salaries applicable to that time frame using startDate and endDate attributes.
This is the graphical representation of all possible combinations, The given time frame is April to March,
APRIL MARCH
| —------------FILTER--------------- |
| —-------- |
| —-------------------------------------------------- |
| —--------------------- |
| —------------------------- |
| —----- |
| —------- |
The final two should not be included in the result because it's not applicable to the given time frame.
And the there can be salary the endDate can be null and it represent the user active salary,
Basicaly I am storing the salary history also using start,end date.
{
$or: [
// DB record range is completely within provided range
{
startDate: { $gte: start, $lte: end },
endDate: { $gte: start, $lte: end },
},
// Provided range is completely within DB record range
{
startDate: { $lte: start },
$or: [{ endDate: { $gte: end } }, { endDate: null }],
},
// Left intersection
{
startDate: { $lte: start },
endDate: { $lte: end, $gte: start },
},
// Right intersection
{
startDate: { $gte: start, $lte: end },
$or: [{ endDate: { $gte: end } }, { endDate: null }],
},
],
},
Here is an example of the data I am working with:
// group
{
name: 'Group 1',
phases: [ {name: 'Period 1', startDate: "some date", endDate: "someDate", schedules: [{startTime: '1:00', endTime: '2:00', schedule: 'mongoIdRef'}]}, { name: 'Period 2', startDate: "some date", endDate: "someDate", schedules: []}, { name: 'Period 3', startDate: "some date", endDate: "someDate", schedules: []}, { name: 'Period 4', startDate: "some date", endDate: "someDate", schedules: [] } ]
}
// schedule
{
condition: 'active',
tz: 'US/Mountain',
daysOfWeek: [{startTime: 9, endTime: 22, days: [2,3,4,5]}, {startTime: 2, endTime: 5, days: [2,5,6]}]
}
The group's nested "schedule" property needs to get populated. I am doing this successfully here:
Group.statics.findForDate = function (date) {
date = moment(date);
return this.findForDate({
phases: {
$elemMatch: {
startDate: {$lte: date},
endDate: {$gte: date }
}
}
}).populate( {
{
path: 'phases.schedules.schedule',
match: {'daysOfWeek': { $elemMatch: {days: date.day() } } }
}
})
}
However, the match doesn't match properly. I want to return only groups that have a schedule that has the date.day() (which is a number 0-6) in the days array. How can I get .match to do this? Is there another approach?
I'm quite new to Mongoose (NoSQL) so I wonder how to calculate the number of users based on the date (updated).
Currently, I can get the total number of customers but I don't know how to get the number of users based on (today, this week or this month). In MySQL we can just put all the queries to get the information but I don't know how to do it in Mongoose in one query.
Here's the code
Customer Schema/Model
const customerSchema = Schema({
_id: Schema.Types.ObjectId,
fullname: {
type: String,
},
phone: {
type: String,
},
address: {
type: String,
},
updated: { type: Date, default: Date.now },
adminId: { type: String, required: true },
});
API
router.post("/getcustomer/:adminId", (req, res, next) => {
const adminId = req.params.adminId;
Customer.find({ adminId: adminId })
.sort({ updated: "descending" })
.exec()
.then((docs) => {
const response = {
count: docs.length,
customer_info: docs.map((doc) => {
return {
fullname: doc.fullname,
phone: doc.phone,
address: doc.address,
updated: doc.updated,
adminId: doc.adminId,
_id: doc._id,
};
}),
};
res.status(200).json(response);
})
.catch((err) => {
console.log(err);
res.status(500).json({
error: err,
});
});
});
You can group the customers by date using aggregation:
Customers.aggregate([{$group: { _id: { $dateToString: { format: "%Y-%m-%d", date: "$updated" }}, count:{$sum:1} }}])
I have these collections, stats and items. Stats has one item as subdocument:
var ItemSchema = new Schema({
type: String,
created_at: Date,
updated_at: {
type: Date,
default: Date.now()
}
});
var StatsSchema = new Schema({
item: {
type: Schema.ObjectId,
ref: 'Item'
},
url: String,
date: Date,
action: String,
hourly: Number
});
I'd like to aggregate Stats grouping by item.type. Is it possible?
I tried something like this but without luck:
db.stats.aggregate(
{ $project: { _id: 1, hourly: 1, action: 1, item: 1, type: '$item.type' } },
{ $group: { _id: { action: '$action', type: '$item.type' }, total: { $sum: '$hourly' } } }
)
You should not need the $project part of the pipeline.
You should be get what you need from the $group stage
db.stats.aggregate({ $group: { _id: "$item.type" , total: { $sum: '$hourly' } } });
I have the following structure:
var UserSchema = new Schema({
name: String,
email: { type: String, lowercase: true },
offers: [],
});
var OfferSchema = new Schema({
dateFrom: Date,
dateTill: Date,
destination: String,
budget: String,
currency: {},
dateCreated: {type: Date, default: Date.now}
});
I make an aggregations:
User.aggregate(
{ $project: {"offers": 1, _id: 0}},
{ $unwind: "$offers" },
{ $sort: {"offers.dateCreated": -1} },
function (err, result) {
if (!err) {
}
);
And the result is ok, but I want every element to include its parent fields (ex: _id and other fields).
How can I do it?
Just remove the $project stage:
User.aggregate(
{ $unwind: "$offers" },
{ $sort: {"offers.dateCreated": -1} },
function (err, result) {
if (!err) {
}
);