Elastic Search Date Math Issue, unsure of bounds - javascript

I'm trying to query an amount of records from a database but am a little bit confused about date math. Here's an example of one of my blocks:
var searchParams = {
"query": {
"bool" : {
"must" : [
{ "term": { } },
{ "term": { } },
{ "range": {
"dateUTC": {
"gt": "now-7d/d",
"lt": "now/d",
"format": "basic_date_time"
}
}
}
]
}
}
};
Now if I wanted to query all the result from only today, would I use gt: now-1d/d, lt: now/d. Or would I use gt: now-2d/d, lt: now/d, like the edges around one day? The program I'm trying to make is meant to query all the results from today, yesterday, etc. from the second that the day starts to the Midnight of that day, would I have to switch my date math for that?
Thanks

I think this post answers it pretty clearly: https://discuss.elastic.co/t/several-date-math-questions/27453/3
To answer your questions though:
"to query all the result from only today": gt: now/d, lt:now
from today midnight to 2 days ago midnight: gt:now - 2d/d, lt:now/d
The /d here takes the day calculated in the formula, and adjust time to midnight, so if now is the 18th of July 00:31:43, now/d yields the 18th of July 00:00:00

Related

How to bucket JSON data for a range?

I'm new to programming so appreciate any help and patience here. :)
We have some data that we're trying to sort by buckets (days of the month in this case) to create smaller sets of data like so:
export const Weather = [
{
city: "STL",
month: "july",
daysbucket: "1 to 10",
percentages: {
sunny: "45.5",
rainy: "20.5",
cloudy: "10.8",
partlycloudy: "23.2",
},
},
Is there a better way than using string like daysbucket: "1 to 10"?
The idea is to run some forecast simulations using a probability function that pulls the percentage of the past weather for a certain day without having to list these percentages for each day of the month. So far I planned to get the day of the month and then do some if statements to slot it into a string for 1-10, 11-20, etc. but wanted to see if there was a better way before I get too far. I have several data sets with a variety of buckets stored as strings but I also have control over the data so can change it as needed. All of the data is stored in MongoDB.
Thanks in advance!!!
To be able to make calculations and comparisons with the daysbucket better to defined it like this:
export const Weather = [
{
city: "STL",
month: "july",
daysbucket: {
from: 1,
to: 10
},
percentages: {
sunny: "45.5",
rainy: "20.5",
cloudy: "10.8",
partlycloudy: "23.2",
},
},
Having this structure you can compare it like:
if (day > daysbucket.from && day < days bucket.to) { ... }
And so on, note that the in order to compare numbers the values should be defined as numbers, not strings, or if string you need to convert them to numbers (use parseInt() or Number())
I would use an object to do that. Something like :
daysbucket: {
min:1,
max: 10
}

Finding Time of any Country using Vanilla JavaScript

I want to know each and every country's Date, Time, Month, Year, Day, Hours and Minutes, using only Vanilla JavaScript. Given that I know country's name, its country code(like 'IN' for India) and Timezone Number(eg: 19800 for Delhi), which I got from OpenWeatherAPI. Please help me how can I achieve this.
i think the toLocaleDateString might help , it accepts two argument , first one is locales and the second one is options that have some timeZone stuff
read the documentations for more info
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString
You can get the current time for a given UTC offset by adding this to the current UTC time. We can do this using the Date constructor and the various getUTC..() functions to get the time components.
We have to be careful with using fixed UTC offsets for many locations such as New York. The UTC offset will vary due to Daylight Saving Time, so we have to use the right UTC offset for a given moment in time.
So, when you get a time back from an API with a UTC Offset (or Timezone Number), you should not make the assumption that the UTC offset is fixed for that location.
function getTimeComponentsFromUTCOffset(timeMillis, utcOffsetSeconds) {
const d = new Date(timeMillis + utcOffsetSeconds * 1000);
return {
year: d.getUTCFullYear(),
month: d.getUTCMonth() + 1,
day: d.getUTCDate(),
hour: d.getUTCHours(),
minute: d.getUTCMinutes(),
second: d.getUTCSeconds()
};
}
// NB: timeZoneNumber or UTC offset will vary according to local DST rules...
const inputs = [
{ timeZoneNumber: +28800, location: 'Perth' },
{ timeZoneNumber: +19800, location: 'Delhi' },
{ timeZoneNumber: +3600, location: 'London' },
{ timeZoneNumber: -14400, location: 'New York' },
]
console.log('Location'.padEnd(12), 'Year ', 'Month ', 'Day ', 'Hour ', 'Minute', 'Second');
for(let input of inputs) {
let time = getTimeComponentsFromUTCOffset(Date.now(), input.timeZoneNumber);
console.log(input.location.padEnd(12), ...Object.values(time).map(s => (s + '').padStart(2, '0').padEnd(6)));
}
.as-console-wrapper { max-height: 100% !important; }

Mongodb aggregation query by date difference

I am trying to make a cron job which syncs my documents. It should try to do it x amount of times but only after 2h have passed since the last try. On each document I have "lastSyncAt" field which I can use.
{
"_id" : ObjectId("628d8c4ddb65027a2cfd1019"),
"calculatedAt" : "",
"count" : 0,
"createdAt" : "2022-05-25 01:54:21",
"lastSyncAt" : "2022-05-25 03:54:21"
}
How should I approach this?
Should I get the lastSyncAt value in pipeline and calculate difference between currentDate? How do I get only the hours portion of that in my pipeline?
Should I convert lastSyncAt into unix and get currentDate in unix substract them and divide by 7200 to see if it is greater than 2?
Or should I take another approach?
I'm not even sure what approach to take. Not looking for code but an idea how to handle this.
Thx
Update:
Thanks to #derek-menénedez I managed to get it working as shown below:
[
// Stage 1
{
$addFields: {
lastSyncAt: {
$dateDiff: {
startDate: {$dateFromString: {
dateString: "$lastSyncAt",
timezone: "Europe/Zagreb"
}},
endDate: "$$NOW",
unit: "minute",
timezone: "Europe/Zagreb"
}
}
}
},
// Stage 2
{
$match: {
lastSyncAt: {
$gt: 120
}
}
}
]
You can use the aggregation framework to achieve the things that you want:
https://mongoplayground.net/p/1RzPCYbeHEP
You can try to remove the projection on the example to validate the number of hours.
$dateFromString operator helps you to create a date from a string
$dateDiff operator helps you to extract the diff of two dates

Using ISODate with mongodb query and node.js

I am creating a string -
queryString - {"Project": "Serenity","DateOfWalkin": {"$gte": "2022-03-01" ,"$lt": "2022-03-31"} }
then parsing it - queryObject = JSON.parse( queryString )
It is parsing successfully, but when I run the query it does not give me any result.
Now when I update the same query by using ISODate for both dates, and then tried running the query in Mongo compass, it works fine.
I want to use ISODate() but the problem is the way I am building the queryString is based on different conditions from the user input, now if a particular condition is true then and only then I want to query that particular field. For other fields I am searching, which are of type "String" in my db, I am able to get the correct result, but for date I am facing this issue.
startDate and endDate are user inputs using date picker in HTML
TRIAL number 1
queryString = queryString + ,"DateOfWalkin": {"$gte": ISODate("${startDate}")} ,"$lt": { "$date" : ISODate("${endDate}") } }
This will give a parser error saying identifier "I" not found, hence I am not able to parse this string.
To combat this, I tried to use new Date object, tried to convert the date using toISOString, but it didn't work.
TRIAL number 2
queryString = queryString + ,"DateOfWalkin": {"$gte": "ISODate("${startDate}")"} ,"$lt": { "$date" : "ISODate("${startDate}")" } }
If we use double quotes for ISODate as well, it will solve the parser issue but Mongo query will not give any result and it is treating ISODate wrapper as a string literal.
TRIAL number 3
queryString = queryString + ,"DateOfWalkin": {"$gte": "${startDate}"} ,"$lt": { "$date" : "${endDate}" } }
Does not give result
TRIAL number 4
Using new Date() to get the ISODate format
Query becomes -
{
Project: 'Serenity',
DateOfWalkin: {
'$gte': 'Tue Mar 01 2022 05:30:00 GMT+0530 (India Standard Time)',
'$lt': 'Thu Mar 31 2022 05:30:00 GMT+0530 (India Standard Time)'
}
}
Still it doesn't give any result
TRIAL number 5
Query object -
{
Project: 'Serenity',
DateOfWalkin: {
'$gte': { '$date': '2022-03-01' },
'$lt': { '$date': '2022-03-01' }
}
}
Above doesn't give result
Is there any way I can store the value of ISODate("${startDate}") and use that variable in the main queryString?
Or is there a better way to compare dates when I am using the input dates as user input?
I have tried multiple approaches and kinda feeling stuck at this point.
Why do you parse the string?
Apart from your current problem, you also open the door for NoSQL-Injection. You can compose the query object also directly like this:
const queryObject = {};
queryObject["Project"] = "Serenity";
queryObject["DateOfWalkin"] = { $gte: ISODate("2022-03-01"), ["$lt"]: ISODate("2022-03-31") };
const ninDates = [];
ninDates.push(ISODate("2022-03-10"));
ninDates.push(ISODate("2022-03-20"));
queryObject["DateOfWalkin"]["$nin"] = ninDates;
db.collection.find(queryObject)
If you really insist to parse the string, then use ejson
EJSON.parse('{ "Project": "Serenity", "DateOfWalkin": { "$gte": { "$date": "2022-03-01" }, "$lt": { "$date": "2022-03-01" } } }')
Should give desired queryObject. Note, keys and values need to be enclosed by double-quotes (")

How to take the value from the last month using a timestamp?

It's the first time I come here so I hope my question won't be too bad.
I'm trying to pick the data from last day, last week and last month that are stored in a mongo collection.
So actually I did:
if(period.includes("daily")){
//search for 24h before now
DockerStatsToKeep.find({
read: { "$gte": moment(new Date()).subtract(86400, 'second').unix()}
});
}else if (period.includes("weekly")) {
//search for 168h before now (7days)
DockerStatsToKeep.find({
read: { "$gte": moment(new Date()).subtract(604800, 'second').unix()}
});
}else if (period.includes("monthly")) {
//search for last month
DockerStatsToKeep.find({
read: { "$gte": moment(new Date()).subtract(xx, 'second').unix()}
});
}else{
console.error("this is not a valid period format, please use 'daily, weekly or monthly'");
}
But I'm stuck for the last month and I can't find a way to do it. Because month are sometimes 30days or 31days or 29days
In a momentjs you can subtract month as well:
moment(new Date()).subtract(1, 'month').unix()
It will also handle the transition between the years. E.g. subtract 1 month from date in January 2017 will return date in December 2016
See documentation on subtract

Categories