I have to show a chart in frontend which takes an array of numbers (7 for a week, 12 for months and 5 for years as shown as shown in the image).
In backend I had a document for everyday which stores and updates on daily basis as unique for a day storing total energy delivered.
Currently I have timestamps in epoch time but I can change it to anything which fulfils my needs.
I want to write queries for obtaining data based on selection using bPID. Suppose I select week it queries last 7 document for a particular bPID and return it to me so that I can filter it out. Suppose I select months so it returns me 31 collections for Jan and 28 for Feb which I would process it in my backend and get an array of 12 for a month. How to query this so that in the end I end up getting array of 7 documents for a week, 12 for a month, 5 for a year.
My current collection:
const analyticSchema = new Schema(
{
bPID: String, // unique for every document
todaysTimeStamp: Number, // epoch time for 12:00 am
energyConsumed: Number
},
{
timestamps: true
}
);
You can get last 7 document for a week, for months you have to query based on this month and get last 365/366 documents. Filter it out based on months. For years you have to get it as mentioned above.
Supposing a collection of a large number of documents like this:
{
createdAt: 1630789008561, // timestamp
count: 5
},
{
createdAt: 1630788666511, // timestamp
count: 50
},
...
I would like to query the 50 documents with the highest count that were created after a certain timestamp.
One simple solution is to query all documents after this certain timestamp and then order them yourself. But I can't since my database is too large.
My first query attempt was:
db.collection("docs")
.where("createdAt", ">", timestamp)
.orderBy("count", "desc")
.limit(50)
.get();
This query does not work in Firestore and throws:
Error: 3 INVALID_ARGUMENT: inequality filter property and first sort order must be the same: createdAt and count`
I then tried:
db.collection("docs")
.where("createdAt", ">", timestamp)
.orderBy("createdAt", "desc")
.orderBy("count", "desc")
.limit(50)
.get()
This query will not work for me since what it does is taking 50 documents after the timestamp and then order these by count in case they have the same timestamp, which is not what I want.
Edit on why this query does not work:
If I have 150 documents:
50 created on day 1 with a count of 1
50 created on day 2 with a count of 2
50 created on day 3 with a count of 1
If I use this query with a timestamp of 0, I would get back the 50 documents last created (because I am using .orderBy("createdAt", "desc")) which have a count of 1 and are obviously not the ones with the highest count.
If you use asc instead, you get the first documents, which still have not the highest count.
I would like a query that for a timestamp of 0 would give me the 50 documents with the count of 2.
How can I achieve what I want?
EDIT on solution I am currently using (which I'd like to change):
Since my time range is a day, I add a day field in every documents like this:
{
day: '2021-09-06',
createdAt: 1630789008561, // timestamp
count: 5
},
{
day: '2021-09-05',
createdAt: 1630788666511, // timestamp
count: 50
},
...
I can then do an equality check like this:
db
.collection("docs")
.where("day", "==", '2021-09-05')
.orderBy("count", "desc")
.limit(50)
.get();
This works but this is not great since everytime my time range changes I need to update my db schema and update every documents with the new field.
Return the first 50 docs sorted by count. Then you filter by timestamp on the device.
QuerySnapshot<Map<String, dynamic>> query = await db
.collection("docs")
.orderBy("count", "desc")
.limit(50)
.get();
List docs = query.docs.map((e) => e.data()).toList();
// then filter by timestamp on the device
docs.removeWhere((element) => element['createdAt'] < timestamp);
This cannot be done by using where query because there is no way around this limitation.
If you include a filter with a range comparison (<, <=, >, >=), your first ordering must be on the same field:
this is the right query.
db.collection("docs")
.where("createdAt", ">", timestamp)
.orderBy("createdAt", "desc")
.orderBy("count", "desc")
.limit(50)
.get()
But you need to set Firestore Composite Indexes.
in the database I have a column called,
edited date. I need to write a query.
where: {
lastEditedDateTime:!moment().subtract(10, 'days').toDate()
}
I need to write query that finds the last edited date is greater than 10 days.
I think this is what you're looking for.
where: {
lastEditedDateTime: {
[Op.lte]: moment().subtract(10, 'days').toISOString()
}
}
Here are the search operators in Sequelize: https://sequelizedocs.fullstackacademy.com/search-operators/.
So I have this code line here:
let advertisements = await Advertisement.find({created_at: {$lt: moment().valueOf()}});
This is what it does:
created_at: returns a timestamp when post was created at: 1551198203488.0
moment.valueOf() return me a current timestamp for example: 1551198203488.0
Now I need to write this code line that it only finds ads that are 1 hour old. Is is possible somehow ?
Also I storing and group2_date which store current timestamp BUT with 1 hour added to it like this: moment().add(1, 'h')
You can subtract one hour from the moment using .subtract function and then use $gte operator to obtain only the greater values/documents from the subtracted hours and less then from the current time.
let advertisements = await Advertisement.find({
"created_at": {
"$lte": moment().toDate(),
"$gte": moment().subtract(1, 'hours').toDate()
}
})
Context
I'm building a query where a user can enter a range of dates to search for 'Player' documents. The query should return any players whose start and end dates overlap with the queried dates. I'm doing this by using an OR condition where either the player's end date is after the query's start date or the player's start date is before the query's end date. Both dates in the query are optional, allowing the user to specify only an end date or a start date, or neither to return all relevant documents.
Problem
The query works when only one of the two query dates are specified (see screenshots below). However, it returns all documents if both dates are specified (functionally ignoring both query parameters).
Code
let query = Player.find({'casino': user.casino});
let queryArray = [];
if(req.body.startDate) {
queryArray.push({playerEndDtm: {$gt: moment(req.body.startDate).toDate()}});
}
if(req.body.endDate) {
queryArray.push({playerStartDtm: {$lt: moment(req.body.endDate).endOf('day').toDate()}});
}
if(queryArray.length > 0) {
query.or(queryArray);
}
Screenshots
When both query dates are specified:
Results:
When only 1 query date is specified:
Results:
Can anyone help me determine what I'm doing wrong? Thanks!
if(req.body.endDate) {
queryArray.push({playerStartDtm: {$lt:
moment(req.body.endDate).endOf('day').toDate()}});
}
In the above query you are justing checking less then the end date. You need to check range between dates:
({ playerStartDtm : { $gt : expression, $lt : expression}})