count number of order every hour with loopback4 - postgresql

Salem,
I have tried to return the number of order per hour, so i need to extract the hour in the property createdAt in my order Model that's why i think to use The getHours() method returns the hour for the specified date.
My method:
#get('/orders/count-perHour/{date}', {
responses: {
'200': {
description: 'Order model count',
content: { 'application/json': { schema: CountSchema } },
},
},
})
async countPerHour(
#param.path.string('date') date: string): Promise<any> {
let dateStart=new Date(date) ;
dateStart.setSeconds(0);
dateStart.setMinutes(0);
let dateEnd=new Date(date) ;
dateEnd.setSeconds(59);
dateEnd.setMinutes(59);
return await this.orderRepository.count(
{
createdAt: {
lte: dateEnd
,
gte: dateStart
}
}
);
}
the property createdAt in mu model order:
#property({type: 'date',})createdAt?: string;
Error: it return false comparison, for example if i have one order at hour:10 it return 6

Related

Date range filter and One-to-Many relation query syntax

I am trying to filter booked rooms to find all available rooms:
model Room {
id Int #id #default(autoincrement())
roomNumber String #unique
hotel String
bookings Booking[]
}
model Booking {
id Int #id #default(autoincrement())
hotel String
startDate DateTime
endDate DateTime
roomId Int
room Room #relation(fields: [roomId], references: [id])
##map("bookings")
}
I don't get the syntax of a prisma findMany query that would check, given two booking dates, all available rooms.
The mathematical logic to find if a room is not available is (i.e. if one booking interval crosses or contains the dates given) :
(startDate <= dto.startDate && dto.startDate < endDate) ||
(startDate < dto.endDate && dto.endDate <= endDate) ||
(dto.startDate <= startDate && dto.endDate >= endDate)
I would appreciate any help as I don't understand quite well the order of logic filters in prisma...
You can use none:
prisma.room.findMany({
where: {
bookings: {
none: {
// ...
},
},
},
});
and specify the condition for a booking that would case a conflict (i.e. make the room not available) or use every:
prisma.room.findMany({
where: {
bookings: {
every: {
//...
},
},
},
});
and specify the condition that bookings have to meet to not cause a conflict.
The condition you've specified seems unnecessary complex to me. Every booking that meets this condition should be a conflict:
(dto.startDate <= endDate && dto.endDate >= startDate)
(might need some adjustment depending on how you want to treat edge cases)
All together:
prisma.room.findMany({
where: {
bookings: {
none: {
endDate: { lte: dto.startDate },
startDate: { gte: dto.endDate },
},
},
},
});
Just in case you want to specify more complex conditions using OR you can do like this:
prisma.room.findMany({
where: {
bookings: {
none: {
OR: [
{
// (startDate <= dto.startDate && dto.startDate < endDate)
startDate: { lte: dto.startDate },
endDate: { gt: dto.startDate },
},
{
// (startDate < dto.endDate && dto.endDate <= endDate)
startDate: { lt: dto.endDate },
endDate: { gte: dto.endDate },
},
{
// (dto.startDate <= startDate && dto.endDate >= endDate)
startDate: { gte: dto.startDate },
endDate: { lte: dto.endDate },
},
],
},
},
},
});

Count or Include filtered relations prisma

I am currently stuck on a problem with my prisma queries.
I have an asset which has a 1 to Many relationship to views. I am trying to perform a findMany() on assets which returns either;
The asset with a list of views created within the last day
Or the asset with a count of views created in the last day
Finally I need to be able to orderBy this count or the count of views in my include statement. (this is what I am stuck on)
return await prisma.asset.findMany({
take: parseInt(pageSize),
skip: (pageSize * pageNumber),
include: {
_count: {
select: {
views: true
},
},
views: {
where: {
createdAt: dateFilter
},
},
likes: {
where: {
createdAt: dateFilter
}
},
transactions: true,
},
orderBy: { views: { _count: 'desc' } }
My queries does correctly return only views in my date range but how do I go about ordering the assets based on the count of these views. I have been stuck for quite some time on this. My raw SQL is not strong enough to write it from scratch at the moment.
If anyone has any ideas, thanks.
Will something like this work?
// First we group the views, with pagination
const groupedViews = await prisma.view.groupBy({
take: 10,
skip: 0,
by: ['postId'],
where: { createdAt: dateFilter },
_count: { postId: true },
orderBy: { _count: { postId: 'desc' } },
});
// Fetch the posts from the grouped views
const _posts = await prisma.post.findMany({
where: {
id: { in: groupedViews.map(({ postId }) => postId) },
},
include: {
_count: { select: { views: true } },
views: { where: { createdAt: dateFilter } },
},
});
// Map the fetched posts back for correct ordering
const posts = groupedViews.map(({ postId }) =>
_posts.find(({ id }) => id === postId)
);
Model:
model Post {
id String #id #default(cuid())
views View[]
}
model View {
id String #id #default(cuid())
createdAt DateTime #default(now())
postId String
post Post #relation(fields: [postId], references: [id])
}
This uses 2 separate queries, but does not require raw sql

Update document that contain TTL with reseting the TTL

I'm trying to create a document, that last 120 seconds, and as soon as i call this method i want the TTL to restart.
At the moment i can"t update my document, after 120 sc .. the document get deleted and re-created instead of being always updated.
There is my collection :
LaptopConnections = new Mongo.Collection('laptopConnection');
let LaptopConnectionSchema = new SimpleSchema({
creationDate: {
type: Date,
label: "Date when the laptop was created",
defaultValue: Date.now
},
"state.date": {
type: Date,
label: "time when the laptop was updated",
autoValue: function () {
return new Date;
}
}
}
, { timestamps: true }
)
LaptopConnections.attachSchema(LaptopConnectionSchema)
And there is my method :
Meteor.startup(() => {
LapConnections._ensureIndex({ creationDate: 1 }, { expireAfterSeconds: 120 });// Will delete the collection after ~~ two minutes,
});
Meteor.methods({
create_lapconnection(lap_id) {
check(lap_id, String);
if (!LapConnections.findOne({ _id: lap_id })) {
console.log('workiiing',lap_id)
LaptopConnections.insert({
_id: box_id,
creationDate: Date.now(),
});
} else {
console.log('updated',lap_id)
LaptopConnections.update({ _id: lap_id }, { upsert: true }, {
$set: {
"state.date": Date.now(),
}
}
);
}
}
})
You are updating the state.date field while your index sits on the creationDate field. Once you update creationDate or change your index to use the state.date field instead it should work.

get first and last values for each condition

I have a collection like this:
{
_id: ObjectId('534343df3232'),
date: ISODate('2016-01-08T00:00:00Z'),
item_type: "book",
book_id: ObjectId('534343df3232fdf'),
user_id: ObjectId('534343df3232fdf23'),
rating: 6
},
{
_id: ObjectId('534343df3232'),
date: ISODate('2016-01-05T00:00:00Z'),
item_type: "movie",
movie_id: ObjectId('534343df3232fdf'),
user_id: ObjectId('534343df3232fdfa'),
rating: 5
},
{
_id: ObjectId('534343df3232'),
date: ISODate('2016-01-010T00:00:00Z'),
item_type: "song",
song_id: ObjectId('534343df3232fdf'),
user_id: ObjectId('534343df3232fdf13'),
rating: 9
}
There can be only one rating per item per user per day.
I would like to check how the ratings evolve between a period of time for a selection of users and items. I need only the first and the last rating for each book/movie/song.
I have no idea on how I could do this the most efficient way.
As for now, I'm retrieving all the ratings for all the users, and then parsing them with PHP.
db.ratings.find({user_id:{$in:[...]}, $or:[book_id:{$in:[...]}, song_id:{$in:[...]}, movie_id:{$in:[...]}, ], date:{$gte:.., $lte..} });
This is obviously unefficient but I don't know how to handle this case.
You can do it with mongodb mapReduce. So at first you need to filter your data on date range, selection of users and selection of items(query part). Then group by item(map part) and for each item select first and last days with corresponding ratings(reduce part).
Try the following query:
var query = {
user_id: {$in:[...]}
date: { $gte: dateFrom, $lt:dateTo},
$or: [
{book_id: {$in:[...]}},
{song_id:{$in:[...]}},
{movie_id:{$in:[...]}}
]
}
var map = function () {
emit(this.item_type, {
first : {rating: this.rating, date: this.date},
last: {rating: this.rating, date: this.date}
})
}
var reduce = function (key, values) {
var res = values[0];
for (var i=1; i<values.length; i++ ) {
if (values[i].first.date < res.first.date)
res.first = values[i].first;
if (values[i].last.date > res.last.date)
res.last = values[i].last;
}
return res;
}
db.collection.mapReduce( map , reduce , { out: { inline : true }, query: query } )

How can I query for documents where date is greater than a provided date?

I have a collection of events that contain the date of the event stored in this format: YYYY-MM-DD. I want to query for all events that are greater than a provided date. This is what I have so far:
var eventSchema = mongoose.Schema({
title : String,
details : String,
start_date : String,
company: {
type: String,
ref: 'Company'
}
});
eventSchema.methods.getUpcomingEvents = function(company_id, cb) {
var date = utils.dateToday(); // returns e.g., '2015-02-26'
return this.model('Event')
.find({ company: company_id, start_date : {$gte: date} })
.sort({start_date: 'asc'})
.exec(function (err, data) {
if (err) {
console.log('ERROR = ' + err);
cb(false, err);
} else {
cb(null, data);
}
})
};
The problem is that this query is return events that occur before the provided 'date'. What am I doing wrong?
start_date is String, make it Date if you want to perform date comparisons.
change the schema to something like this;
var eventSchema = mongoose.Schema({
title : String,
details : String,
start_date : Date,
company: {
type: String,
ref: 'Company'
}
});