ES|QL: Add TRANGE ES|QL function#136441
Conversation
Add a new ES|QL function that filters @timestamp values for the given time range. Closes elastic#135599
|
Pinging @elastic/es-analytical-engine (Team:Analytics) |
|
Pinging @elastic/es-storage-engine (Team:StorageEngine) |
|
Hi @leontyevdv, I've created a changelog YAML for you. |
ℹ️ Important: Docs version tagging👋 Thanks for updating the docs! Just a friendly reminder that our docs are now cumulative. This means all 9.x versions are documented on the same page and published off of the main branch, instead of creating separate pages for each minor version. We use applies_to tags to mark version-specific features and changes. Expand for a quick overviewWhen to use applies_to tags:✅ At the page level to indicate which products/deployments the content applies to (mandatory) What NOT to do:❌ Don't remove or replace information that applies to an older version 🤔 Need help?
|
Add a new ES|QL function that filters @timestamp values for the given time range. Closes elastic#135599
|
Thank you, Dima! Is there a reason we don't translate TRANGE to GreaterThanEquals() or BinaryLogicOperation(GreaterThanEquals, LessThanOrEquals)? |
Hi @dnhatn ! Thank you for the review! Initially, I implemented TRANGE as a surrogate and struggled with the tests for quite a while. The issue was with the assertion ("Duplicate name ids are not allowed in layouts"): see Layout. Then, inspired by the StartsWith function, I rewrote it using TranslationAware.SingleValueTranslationAware directly. I have the surrogate version in my stash. We can take a look at it together. Wdyt? |
Fix tests. Closes elastic#135599
# Conflicts: # x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-rate.csv-spec # x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java
Replace asQuery by a surrogate Closes elastic#135599
Replace asQuery by a surrogate Closes elastic#135599
Fix tests Closes elastic#135599
Fix constructor visibility Closes elastic#135599
Fix tests Closes elastic#135599
# Conflicts: # x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java
Yes, this case needs more thought! |
Remove wrong csv test Closes elastic#135599
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/Configuration.java
Outdated
Show resolved
Hide resolved
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/Configuration.java
Outdated
Show resolved
Hide resolved
...sql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java
Outdated
Show resolved
Hide resolved
x-pack/plugin/esql/qa/testFixtures/src/main/resources/k8s-timeseries-rate.csv-spec
Outdated
Show resolved
Hide resolved
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/FieldNameUtils.java
Show resolved
Hide resolved
.../esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/TRange.java
Outdated
Show resolved
Hide resolved
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/Configuration.java
Outdated
Show resolved
Hide resolved
.../esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/TRange.java
Outdated
Show resolved
Hide resolved
...in/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java
Show resolved
Hide resolved
dnhatn
left a comment
There was a problem hiding this comment.
I left two questions, but this looks good. Thanks Dima!
.../esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/TRange.java
Outdated
Show resolved
Hide resolved
.../esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/TRange.java
Outdated
Show resolved
Hide resolved
Address PR review comments Closes elastic#135599
Address PR review comments Closes elastic#135599
dnhatn
left a comment
There was a problem hiding this comment.
Great work, Dima! Thank you for all the iterations. Could you please wait for Bogdan’s approval before merging?
.../esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/TRange.java
Outdated
Show resolved
Hide resolved
Address PR review comments Closes elastic#135599
# Conflicts: # x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java
Address PR review comments Closes elastic#135599
Add Verifier tests Closes elastic#135599
bpintea
left a comment
There was a problem hiding this comment.
Left a set of notes, but LGTM otherwise.
...gin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java
Outdated
Show resolved
Hide resolved
...gin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java
Outdated
Show resolved
Hide resolved
| Literal timestampLiteral = as(Alias.unwrap(eval.fields().getFirst()), Literal.class); | ||
| long expectedTimestamp = DateUtils.asDateTimeWithNanos(timestampValue, DateUtils.UTC).toInstant().toEpochMilli(); | ||
| assertThat(timestampLiteral.fold(FoldContext.small()), equalTo(expectedTimestamp)); | ||
| } |
There was a problem hiding this comment.
We should continue with the inspection of the plan here: what happens here is that since timestampValue is within the intervals passed to TRANGE, the WHERE should fold away (it's always true). The test should confirm that. We usually inspect the plan all the way down to the source (just like in the null folding case, though there's compacter, cause it's folded down to just one node).
Optionally, you could also add a test that folds to false.
BTW, you could add a similar test as a CSV spec, to also check the results. But optional.
There was a problem hiding this comment.
Thanks Bogdan! I added inspection all the way down to the source, also added a test which tests folding to false.
.../esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/TRange.java
Outdated
Show resolved
Hide resolved
.../esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/TRange.java
Outdated
Show resolved
Hide resolved
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java
Outdated
Show resolved
Hide resolved
| } | ||
|
|
||
| if (rangeStart.isAfter(rangeEnd)) { | ||
| throw new InvalidArgumentException("TRANGE rangeStart time [{}] must be before rangeEnd time [{}]", rangeStart, rangeEnd); |
There was a problem hiding this comment.
Can we add a test for this condition?
Ideally for the one above too.
There was a problem hiding this comment.
Done! Added to TRangeErrorTests
.../esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/TRange.java
Outdated
Show resolved
Hide resolved
Address PR review's comments Closes elastic#135599
# Conflicts: # x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java # x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java
Add more error tests Closes elastic#135599
bpintea
left a comment
There was a problem hiding this comment.
Added some notes on instantiating the function. Otherwise all good.
| this(source, new UnresolvedAttribute(source, MetadataAttribute.TIMESTAMP_FIELD), first, second, configuration); | ||
| } | ||
|
|
||
| public TRange(Source source, Expression timestamp, Expression first, Expression second, Configuration configuration) { |
There was a problem hiding this comment.
This should be protected, as then the public one can be called unanbigously directly from the function registry.
There was a problem hiding this comment.
Changed this and removed the bic() method from the function registry.
| def(MonthName.class, MonthName::new, "month_name"), | ||
| def(Now.class, Now::new, "now") }, | ||
| def(Now.class, Now::new, "now"), | ||
| def(TRange.class, bic(TRange::new), "trange") }, |
There was a problem hiding this comment.
Having one public c'tor in TRange will allow this direct call, since we have already a BinaryConfigurationAwareBuilder. The bic method can then be removed.
| def(TRange.class, bic(TRange::new), "trange") }, | |
| def(TRange.class, TRange::new, "trange") }, |
Make constructor protected Closes elastic#135599
Make constructor public Closes elastic#135599
# Conflicts: # x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java # x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java
Add docs Closes elastic#135599
# Conflicts: # x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java
| def(MonthName.class, MonthName::new, "month_name"), | ||
| def(Now.class, Now::new, "now") }, | ||
| def(Now.class, Now::new, "now"), | ||
| def(TRange.class, bic(TRange::new), "trange") }, |
There was a problem hiding this comment.
@leontyevdv, hopefully this will make the call unambiguous and also have EsqlNodeSubclassTests tests pass.
| def(TRange.class, bic(TRange::new), "trange") }, | |
| def(TRange.class, (BinaryConfigurationAwareBuilder<TRange>)TRange::new, "trange") }, |
* ES|QL: Add TRANGE ES|QL function Add a new ES|QL function that filters @timestamp values for the given time range. Closes elastic#135599
Add a new ES|QL function that filters @timestamp values for the given time range. It transforms into a fileter and is pushed down to Lucene.
What is currently supported
What is not supported and requires consideration
Closes #135599