Advanced search - allow queries for timestamps in work item index
What does this MR do and why?
This MR adds date filtering support for GLQL date fields (created, updated, closed, due) in Elasticsearch. The implementation supports all comparison operators (=, !=, <, <=, >, >=).
On API level, we receive a Time object, but I am converting it to Not needed anymore since I learned it's already being handled on GraphQL level in .iso8601 when sending to ES.::Types::TimeType.
Below is the mapping of GLQL date queries to Glql::WorkItemsFinder parameters and their Elasticsearch filter equivalents:
Created Date Queries
| GLQL Query | WorkItems Finder | ES Filter Name |
|---|---|---|
created < -1w |
created_before: "2025-07-25 00:00:00 +0200" |
created_before: "2025-07-25 00:00:00 +0200" |
created > -1w |
created_after: "2025-07-25 23:59:00 +0200" |
created_after: "2025-07-25 23:59:00 +0200" |
created = -1w |
created_before: "2025-07-25 23:59:00 +0200", created_after: "2025-07-25 00:00:00 +0200" |
created_before: "2025-07-25 23:59:00 +0200", created_after: "2025-07-25 00:00:00 +0200" |
created >= -1w |
created_after: "2025-07-25 00:00:00 +0200" |
created_after: "2025-07-25 00:00:00 +0200" |
created <= -1w |
created_before: "2025-07-25 23:59:00 +0200" |
created_before: "2025-07-25 23:59:00 +0200" |
created > 2025-01-01 and created < 2025-01-31 |
created_before: "2025-01-31 00:00:00 +0100", created_after: "2025-01-01 23:59:00 +0100" |
created_before: "2025-01-31 00:00:00 +0100", created_after: "2025-01-01 23:59:00 +0100" |
Due Date Queries
| GLQL Query | WorkItems Finder | ES Filter Name |
|---|---|---|
due > 2025-01-01 |
due_after: "2025-01-01 23:59:00 +0100" |
due_after: "2025-01-01 23:59:00 +0100" |
due < 2025-01-31 |
due_before: "2025-01-31 00:00:00 +0100" |
due_before: "2025-01-31 00:00:00 +0100" |
due = 2025-01-01 |
due_before: "2025-01-01 23:59:00 +0100", due_after: "2025-01-01 00:00:00 +0100" |
due_before: "2025-01-01 23:59:00 +0100", due_after: "2025-01-01 00:00:00 +0100" |
due >= 2025-01-01 |
due_after: "2025-01-01 00:00:00 +0100" |
due_after: "2025-01-01 00:00:00 +0100" |
due <= 2025-01-01 |
due_before: "2025-01-01 23:59:00 +0100" |
due_before: "2025-01-01 23:59:00 +0100" |
due > 2025-01-01 and due < 2025-01-31 |
due_before: "2025-01-31 00:00:00 +0100", due_after: "2025-01-01 23:59:00 +0100" |
due_before: "2025-01-31 00:00:00 +0100", due_after: "2025-01-01 23:59:00 +0100" |
Closed Date Queries
| GLQL Query | WorkItems Finder | ES Filter Name |
|---|---|---|
closed > 2025-01-01 |
closed_after: "2025-01-01 23:59:00 +0100" |
closed_after: "2025-01-01 23:59:00 +0100" |
closed < 2025-01-31 |
closed_before: "2025-01-31 00:00:00 +0100" |
closed_before: "2025-01-31 00:00:00 +0100" |
closed = 2025-01-01 |
closed_before: "2025-01-01 23:59:00 +0100", closed_after: "2025-01-01 00:00:00 +0100" |
closed_before: "2025-01-01 23:59:00 +0100", closed_after: "2025-01-01 00:00:00 +0100" |
closed >= 2025-01-01 |
closed_after: "2025-01-01 00:00:00 +0100" |
closed_after: "2025-01-01 00:00:00 +0100" |
closed <= 2025-01-01 |
closed_before: "2025-01-01 23:59:00 +0100" |
closed_before: "2025-01-01 23:59:00 +0100" |
closed > 2025-01-01 and closed < 2025-01-31 |
closed_before: "2025-01-31 00:00:00 +0100", closed_after: "2025-01-01 23:59:00 +0100" |
closed_before: "2025-01-31 00:00:00 +0100", closed_after: "2025-01-01 23:59:00 +0100" |
Updated Date Queries
| GLQL Query | WorkItems Finder | ES Filter Name |
|---|---|---|
updated > 2025-01-01 |
updated_after: "2025-01-01 23:59:00 +0100" |
updated_after: "2025-01-01 23:59:00 +0100" |
updated < 2025-01-31 |
updated_before: "2025-01-31 00:00:00 +0100" |
updated_before: "2025-01-31 00:00:00 +0100" |
updated = 2025-01-01 |
updated_before: "2025-01-01 23:59:00 +0100", updated_after: "2025-01-01 00:00:00 +0100" |
updated_before: "2025-01-01 23:59:00 +0100", updated_after: "2025-01-01 00:00:00 +0100" |
updated >= 2025-01-01 |
updated_after: "2025-01-01 00:00:00 +0100" |
updated_after: "2025-01-01 00:00:00 +0100" |
updated <= 2025-01-01 |
updated_before: "2025-01-01 23:59:00 +0100" |
updated_before: "2025-01-01 23:59:00 +0100" |
updated > 2025-01-01 and updated < 2025-01-31 |
updated_before: "2025-01-31 00:00:00 +0100", updated_after: "2025-01-01 23:59:00 +0100" |
updated_before: "2025-01-31 00:00:00 +0100", updated_after: "2025-01-01 23:59:00 +0100" |
Combined Date Range Queries
| GLQL Query | WorkItems Finder | ES Filter Name |
|---|---|---|
updated > -1w and created > -1m and due > today() and closed > today() |
created_after: "2025-07-05 23:59:00 +0200", updated_after: "2025-07-29 23:59:00 +0200", due_after: "2025-08-05 23:59:00 +0200", closed_after: "2025-08-05 23:59:00 +0200" |
created_after: "2025-07-05 23:59:00 +0200", updated_after: "2025-07-29 23:59:00 +0200", due_after: "2025-08-05 23:59:00 +0200", closed_after: "2025-08-05 23:59:00 +0200" |
References
Screenshots or screen recordings
| Before | After |
|---|---|
How to set up and validate locally
- Follow this guide to have ES enabled locally for GDK
- GLQL relies on
crypto.subtle, which is unavailable in insecure contexts (except forlocalhost), it won’t work if you're using a custom URL likehttp://gdk.test:3000locally. To resolve this, one of the options is to enable HTTPS in GDK by following this link. - Enable the following feature flags in
rails c:
=> Feature.enable(:glql_integration)
=> Feature.enable(:glql_work_items)
=> Feature.enable(:glql_es_integration)
- Navigate to any issue comment or description field where Markdown is supported
- Add the following GLQL query into the field:
```glql
display: table
fields: title, labels, created, updated
query: group = "gitlab-org" and created <= -1w and updated >= today()
```
- Make sure to have a couple work items indexed that have are closed, that were recently updated and have due dates set. Then you can follow the scenarios from this MR description and tests different dates variations.
Note: Sometimes the changes to work items are not indexed properly locally. Restarting sidekiq helps gdk restart rails-background-jobs. Also, I have Kibana running with docker, it helps with verifying the data via dev console http://localhost:5601/app/dev_tools#/console
$ docker run -d --name kibana -p 5601:5601 \
-e ELASTICSEARCH_HOSTS=http://host.docker.internal:9200 \
-v kibana_data:/usr/share/kibana/data \
docker.elastic.co/kibana/kibana:8.7.0
$ docker start kibana
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Related to #540802 (closed)