How to publish single document of a collection for a group of fields with common values in meteor - mongodb

I want to create a publication which should return documents which have a different value for a set of fields. For example, if have a collection called 'User' with below transactions:
{
userId: 1,
date: '12-1-15',
amount: 450
}
{
userId: 1,
date: '12-1-15',
amount: 250
}
{
userId: 2,
date: '12-1-15',
amount: 100
}
{
userId: 2,
date: '11-1-15',
amount: 200
}
Then i need to create a query which will publish only the below documents, i.e, single document for each day and if a day has multiple documents then i want to publish only the document with highest amount.
[{
userId: 1,
date: '12-1-15',
amount: 450
},
{
userId: 2,
date: '12-1-15',
amount: 100
}
{
userId: 2,
date: '11-1-15',
amount: 200
}]
Thanks in advance. :)

Related

How to find data by funcion in mongoose?

I have a collection in mongodb using mongoose packages like below
[
{
_id: new ObjectId("62ae97b6be08b688f93f2c07"),
reportId: '1',
method: 'A1',
category: 'B2',
date: '2022-06-19',
time: '22:55',
emergency: 'normal',
__v: 0
},
{
_id: new ObjectId("62ae97b6be08b688f93f2c08"),
reportId: '2',
method: 'A3',
category: 'B5',
date: '2022-06-18',
time: '23:05',
emergency: 'normal',
__v: 0
},
{
_id: new ObjectId("62ae97b6be08b688f93f2c09"),
reportId: '3',
method: 'A5',
category: 'B1',
date: '2022-06-19',
time: '23:55',
emergency: 'urgent',
__v: 0
}
]
and I want to filter this data, and here is my find function()
const options = [
{ method: { $in: ['A1','A2'] } },
{ emergency: { $in: data.emergency } },
{ category: { $in: data.category } }
];
const response = await Report.find({ $or: options,});
Until now, it works perfectly, but I still got one more filter: the date and time (They are all int type String).
I want to search for the range date and time between last night after 23 o'clock to 23 o'clock tonight.
But I have no idea how to write the query, please help me figure it out, thanks!!!
Here is my testing query:
date: {
$where: function () {
const yesterday = moment().subtract(1, 'days').format('YYYYMMDD') + '2300';
const date = moment(this.date).format('YYYYMMDD') + this.time.replace(':', '');
const today = moment().format('YYYYMMDD') + '2300';
return yesterday < date && date <= today;
},
},
I would recommend you to first save dates in a format that supports comparators (lt, gt, etc.) such as a Timestamp or even a plain number. That way you can use MongoDB filters like this:
let filter = {
date: { $gt: new Date(..), $lt: new Date(..) }
}
// This can be executed directly in the Mongo shell.
{
created_on: {
$gt: ISODate("1972-12-12"),
$lt: ISODate('2022-06-019')
}
}
But if you insist on using strings, then you would need to filter all your documents, and then parse each one to do your comparison.

Mongodb - multi-stages query - calculate, compare and return results

I have mongodb documents as follows:
[
{
_id: '5e839a223552e431fxd3c979',
dateTime: '2020-03-31T19:29:41.259Z',
regionId: 'eg',
transId: 'serviceFee',
revenue: 30,
details: {
serviceId: 'serv_a'
}
},
{
_id: '5e839a223559e431fxd3c979',
dateTime: '2020-03-31T19:29:42.259Z',
regionId: 'eg',
transId: 'serviceFee',
revenue: 10,
details: {
serviceId: 'serv_b'
}
},
{
_id: '5e839a223552ed82fxd3c979',
dateTime: '2020-03-31T19:29:43.259Z',
regionId: 'eg',
transId: 'serviceFee',
revenue: 15,
details: {
serviceId: 'serv_a'
}
},
{
_id: '5e8902223552e431fxd3c979',
dateTime: '2020-03-31T19:29:44.259Z',
regionId: 'eg',
transId: 'serviceFee',
revenue: 55,
details: {
serviceId: 'serv_a'
}
},
{
_id: '5e839a223552e43jjid3c979',
dateTime: '2020-03-31T19:29:45.259Z',
regionId: 'eg',
transId: 'serviceFee',
revenue: 7,
details: {
serviceId: 'serv_b'
}
},
{
_id: '5e839a223552e431fx0c3979',
dateTime: '2020-03-31T19:29:46.259Z',
regionId: 'eg',
transId: 'serviceFee',
revenue: 120,
details: {
serviceId: 'serv_c'
}
},
{
_id: '5e839a22ggt2e431fxd3c979',
dateTime: '2020-03-31T19:29:47.259Z',
regionId: 'us',
transId: 'serviceFee',
revenue: 500,
details: {
serviceId: 'serv_a'
}
},
]
looking to the documents we can say:
there are two regions, as per regionId: [eg,us],
there are three services, as per serviceId: [serv_a, serv_b, serv_c],
each document shows the revenue of a particular service in a particular region.
now here is what I want:
I want to know the best performing service (with highest total revenue) in a particular region (ex. eg).
I also want to know the worst performing service in the same region.
So expected result should be:
Best performing service in region 'eg' is: serv_c
Worst performing service in the region is: serv_b
So from my basic understanding, I think I need to find a way to calculate the total revenues of each service in the region (ex. eg) and then compare between the totals to decide which is the highest and which is the lowest! I think I should use mongodb aggregate function, but I don't know how to use it in this case.
I think I figured this out.
Here is an example in javascript showing how did I do it:
var bestPerformingService = 'ph_besterviceId'; // <-- value placeholder
var worstPerformingService = 'ph_worstServiceId' // <-- value placeholder
var trId = 'serviceFee'; // <-- selected transId
var regId = 'eg'; // <-- selected regionId
var resultArray = await records_revenues_model.aggregate([
{
$match: {
regionId: regId,
transId: trId,
}
},
{
$group: {
_id: '$details.serviceId',
totalRevenues: { $sum: '$revenue' },
}
},
{
$sort: { totalRevenues: -1 }
},
]).exec() || [];
try {
bestPerformingService = resultArray[0]._id;
worstPerformingService = resultArray[resultArray.length - 1]._id;
} catch (error) {
methods.log(`safed error : ${error}`);
}
console.log(`best performing service: ${bestPerformingService}`);
console.log(`worst performing service: ${worstPerformingService}`);
// expected outcome:
// best performing service: serv_c
// worst performing service: serv_b
I hope this can be useful to someone someday.

MongoDB Aggregate by date on many fields

I have the following schema (abbreviated!)
{
date: {
_id: false,
day: { type: Number },
month: { type: Number },
year: { type: Number },
},
flightTimes: {
_id: false,
totalTime: Number,
...
},
loggedTimes: {
_id: false,
P1: {
type: Number,
},
P2: {
type: Number,
},
...
},
customFields: [
{
_id: false,
value: String,
type: {
type: String,
enum: ["text", "number", "time", "yesno", "paragraph"],
required: true,
},
},
],
}
I am trying to produce the following output using aggregation, but struggling.
{
total: [10,20,30],
P1: [45, 55, 12],
P2: [0, 12, 15],
}
Where the 1st item in the total array is the sum of any documents where Month = 1 (January), the second is the sum for February etc.
Any suggestions on how to proceed? For bonus points: the array should have a 0 if no documents match the current month. For more bonus points: how could I create an additional array for the sum of values in each custom field where type = time.
Ultimately looking to produce a graph with Charts.JS which shows the sum per month for each category of time.

I need to write the code for size based bucketting in mongo db

my model data is like
{
sensor_id: 12345,
timestamp: ISODate("2019-01-31T10:00:00.000Z"),
temperature: 40
}
{
sensor_id: 12345,
timestamp: ISODate("2019-01-31T10:01:00.000Z"),
temperature: 40
}
{
sensor_id: 12345,
timestamp: ISODate("2019-01-31T10:02:00.000Z"),
temperature: 41
}
and expected output is like:
{
sensor_id: 12345,
start_date: ISODate("2019-01-31T10:00:00.000Z"),
end_date: ISODate("2019-01-31T10:59:59.000Z"),
measurements: [
{
timestamp: ISODate("2019-01-31T10:00:00.000Z"),
temperature: 40
},
{
timestamp: ISODate("2019-01-31T10:01:00.000Z"),
temperature: 40
},
…
{
timestamp: ISODate("2019-01-31T10:42:00.000Z"),
temperature: 42
}
],
transaction_count: 42,
sum_temperature: 2413
}
I have some different data set but actual problem is to use $facet with giving the start time and end time for size based bucketting in mongodb.

How to perform incremental aggregation in mongodb?

I have a collection of user's browsing time.
db.userBrowsing.find()
{ userID: "ed3p6ddk0r", start_time: ISODate('2011-11-03 14:17:00'), time: 75 } );
{ userID: "2bnliaossn", start_time: ISODate('2011-11-03 14:23:00'), time: 10 } );
{ userID: "rhjynj9z8o", start_time: ISODate('2011-11-03 15:02:00'), time: 5 } );
{ userID: "q3wasyu5yp", start_time: ISODate('2011-11-03 16:45:00'), time: 20 } );
By aggregation, I maintained the totalBrowsingTime collection which contains userID and totalTime.
db.userBrowsing.find()
{ userID: "ed3p6ddk0r", totaltTime: 75 } );
{ userID: "2bnliaossn", totalTime: 10 } );
{ userID: "rhjynj9z8o", totalTime: 5 } );
{ userID: "q3wasyu5yp",totalTime: 20 } );
Day by day this collection populate for every user. So I need incremental aggregation to fill userBrowsing collection.
Should I use cronjob for this? or is there any different method for that?
Thanks!