Needs work
Project:
Facets
Version:
2.0.x-dev
Component:
Code
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Reporter:
Created:
8 May 2019 at 14:20 UTC
Updated:
9 Jun 2022 at 06:42 UTC
Jump to comment: Most recent, Most recent file
Add handling for x time ago dates.

Add additional options in \Drupal\facets\Plugin\facets\query_type\SearchApiDate?
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #35 | facets-time_ago_handling-3053429-35.patch | 17.94 KB | cgoffin |
| #32 | interdiff-3053429-29-32.txt | 1.79 KB | jeroent |
| #32 | 3053429-32.patch | 17.63 KB | jeroent |
| #29 | interdiff-28-29.txt | 2.86 KB | p-neyens |
| #29 | 3053429-29.patch | 16.12 KB | p-neyens |
Comments
Comment #2
borisson_Uploaded the steps I took to get where I ended up as individual patches.
Comment #3
borisson_Final patch of what I ended up with.
Comment #5
borisson_Fix cs errors introduced in the previous attempt + documentation.
Also giving credit to @svdhout and @wouter.h for discussing the approach taken before starting on this.
Comment #7
borisson_Comment #8
borisson_Next steps:
Make this configurable in some (hopefully dynamic) way.
Write tests to ensure that this behavior does not break.
Test the future dates as well (I only tested past now)
Comment #9
borisson_Small bugfix, I couldn't get tests to work in my local env for now. But I've already made sure that future dates work by manually testing them.
Next step is making this configurable.
Comment #10
borisson_Comment #11
borisson_Makes this configurable + adds testcoverage for that as well. Since this also adds a new key in the config schema, we might have to add an upgrade path as well? Not sure about that though.
Comment #12
borisson_Makes older/newer also configurable.
Comment #13
borisson_When not selecting all the inbetween steps, the older facet was not always returning the right results. That should be fixed now. Also fixes a CS problem.
Comment #14
borisson_Bugfix.
Comment #16
legolasboI can already see the feature request to be able to adjust these.
"Please add Last 14 days to the options"
"Please add Coming 9 days to the options"
Instead of going with textual options, we could go with integer values and only use textual options for the older and newer options. People could then use the following format to define the available options:
We're only looking at days, so the exact request time doesn't matter, does it?
Omitting this timestamp allows us to replace all the cloning of $now and then modifying it with just instantiating new DateTime objects.
There is quite a lot of duplication going on here. We could probably reduce duplication by abstracting this out into something like an "IntervalOption" class.
Edit: Even better, switching to numeric options would make this whole thing far simpler.
$far = new DrupalDateTime(- PHP_INT_MAX);would set the date to the oldest possible date.So what if someone has indexed some historical things going back 2000 years?
$far = new DrupalDateTime(- PHP_INT_MAX);would set the date to the oldest possible date.$far = new DrupalDateTime(PHP_INT_MAX);would set the date to the farthest possible date.What if someone has something indexed that describes things into the far future? Say the year 5423?
$far = new DrupalDateTime(PHP_INT_MAX);would set the date to the oldest possible date.Comment #17
borisson_#16
Comment #18
borisson_I tried to make all of this easier by changing the way this is configured but I can't really get it to work. This is making me confused. I have to walk into a meeting for pretty much the rest of the day - so at least posting my intermediate work.
Comment #19
borisson_Comment #21
borisson_Coding standards + comments cleanup. Will still fail tests.
Comment #23
borisson_Tests should be green now.
Comment #24
legolasbo$this->t()
$this->t()
We should probably validate the display_dates to make sure each line is a key|value combination and that all keys are numeric except for the catch-alls
This could (in theory) cause side effects if this class is re-used across multiple facets. Are we sure each facet gets a new instance of this class? Perhaps we should add tests to ensure that the furthest past/future does not bleed through to other facets on the same page.
Code smell, this class seems to violate the open-closed principle. I think we should refactor this class (in a follow up) and introduce the strategy pattern or the plugin pattern to allow for different types.
Comment #25
feyp commentedThank you very much for working on this very useful feature! A few observations on top of #24 from my testing of the configured relative date range feature:
+ * Returns an array that can be passed trough the facet for grouping results.Nit: I guess something like
through toinstead oftrough?+ // Unset $config so it does not bleed trough the next part of the method.Nit: See above.
I think we need to calculate furthestFuture and furthestPast for each interval. Otherwise you may end up in a state, where you have an "older" date or a "newer" date and both properties are still 0, which will mess up the date ranges for "older" and "newer" dates. During my testing, I got two "older" categories with different date ranges for my index. I ended up moving those calculations directly to the start of the foreach loop using a slightly different condition for furthestPast
which seems to work as expected.
+ $modify->modify($this->furthestPast . ' days');furthestPast is an absolute value, so I guess we should prepend a minus sign here.
Apart from that, there is another issue with the facet counts. Since everything except older and newer always starts at the current date, which I think is totally fine and expected, the counts are messed up a little. For example, if I have 30 and 365 configured, events within the next 30 days will be counted in the 30 days date range only, although I would expected them to be counted in the 365 days date range as well, since they will be listed in both categories. Less abstract example: Suppose today is June 3rd, 2019 and you have two dates: June 11, 2019 and August 02, 2019. I would expect a count of 1 to be shown for the next 30 days and 2 for the next 365 days, but although both dates are listed in the 365 days category as expected, the count for the 365 days category is only 1. I din't look into why this happens and how to best fix this, yet.
Comment #26
feyp commentedAnd here's something else I just noticed:
Since the date type contains the label to show, we should set the
typetolabelinstead ofstring, so that the setting will become available in config translation.Comment #27
ekes commentedSo I looked at this and went down the rabbit hole of why Search API Solr wasn't doing the existing date ranges as range queries. This needs another issue - and it's code to go into Search API Solr (
SearchApiSolrBackend::setFacets()). It's quite important as these iterations over all items get more complicated.What needs to be born in mind for this patch in relation to that is these will have to be
facet.intervalrather thanfacet.range.Range allows passing the
facet.range.gapas +1MONTH or whatever, and the start point can be absolute or NOW relative. I think we have that data to pass easily in the info.Interval allows for multiple specified facets in the format:-
I've checked it will work with (2018-06-14T00:00:00Z,2018-07-14T00:00:00Z].
It won't with periods like -1YEAR.It will work with periods, and relative periods like NOW/DAY is now rounded to today, and math can then be applied NOW/DAY-1DAY. If &TZ=full/timezone (like &TZ=Australia/Perth) is applied it will round to the day in the local timezone.
So the patch just needs to take into account that we'll want to send this data in the info to the backend in case they support this.
Update:
#3061897: Support range and interval facets for search_api_date facets for a description of what could happen in Search API Solr.
The next steps in this module would be to add the granularity or intervals array as appropriate to the info that gets passed to the backend. MySQL backend will ignore it (unless someone writes custom handling), Solr will also, until additional range and interval handling for dates is added. But when a backend implements the handling they will return just one item for each gap or interval - with count - so the present code will continue to work, but only iterate over one item (instead of potentially 10000sss).
Update 2:
For elastic this issue #2969137: Date range aggregation references the documentation that includes the data that it would need to provide the facets natively.
Comment #28
ekes commentedLooking into making some reusable code to get the boundaries to send to interval supporting backends I tightened the tests specifically in relation to timezone handling. The previous tests were looking at the far ends of a UTC day. This looks to half an hour into Australia/Sydney days. I'm pretty sure the logic I've used is sound, and it's created breaking tests - and hopefully do so 'consistently' throughout the day.
Comment #29
p-neyens commentedCreated new path with some proposals from comment #25
Comment #30
jeroentComment #32
jeroentComment #33
jeroentI noticed that using the count option wasn't working correctly. e.g.:
Today is
2021-10-11.You have an overview with 3 results with the following dates:
2021-10-11, 2021-10-12 and 2021-10-15.And 3 filters: Today, Tomorrow and This week.
The filter will show the following result:
When filtering on e.g. This week, the actual filter is something like 2021-10-11 00:00:00 - 2021-10-18 23:59:59 and 3 results are shown in the overview.
Imo the expected result should be:
I added an extra check in the
\Drupal\facets\Plugin\facets\query_type\SearchApiDate::build().I sorted the filters on date loop over all filters. When the period of the previous filter is included in the current filter, the count value of the previous filter is added to the current filter.
Comment #35
cgoffin commentedHere a version of the patch to work wit v2.
Comment #36
mkalkbrenner