influxdb-client-java
influxdb-client-java copied to clipboard
Should the Flux DSL support Flux as an open langauge?
The DSL API presents a convenient way for users to build Flux queries without having worry about the mechanics of constructing the query.
I have a question about its design and intended use cases. Currently the implementation requires that a Java class be constructed to mirror every function in the Flux standard library. Should the DSL support the addition of other custom functions? Said another way Flux is an open language, meaning users can create their own functions etc and use those. As the DSL is currently written it is not convenient to work with those kinds of functions since there are no types to create them.
For example a user could create this Flux code:
mydata = (start) =>
from(bucket: "mybucket")
|> range(start: start)
|> filter(fn: (r) => r._measurement == "temp")
mydata(start: -1m)
|> sum()
|> yield(name: "last_minute")
mydata(start: -1d)
|> sum()
|> yield(name: "last_day")
There is no way to express the same thing in the DSL currently (without the use of the expression()
function).
I don't really have a solution to this problem rather open to ideas and wanting to start a discussion around a way we could address the openness of the Flux language from the DSL.
Users are able to create custom operator for function that are missing in the DSL: https://github.com/influxdata/influxdb-client-java/tree/master/flux-dsl#custom-operator
Create an operator for their own function is also possible, but it is no so easy:
package com.example.flux;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import com.influxdb.Arguments;
import com.influxdb.query.dsl.Flux;
import com.influxdb.query.dsl.functions.AbstractParametrizedFlux;
import com.influxdb.query.dsl.functions.YieldFlux;
import com.influxdb.query.dsl.functions.restriction.Restrictions;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
@RunWith(JUnitPlatform.class)
class MyDataTest {
@Test
void query() {
Flux myData = new MyData();
YieldFlux last_minute = new MyData()
.withStart("-1m")
.sum()
.yield("last_minute");
YieldFlux last_day = new MyData()
.withStart("-1d")
.sum()
.yield("last_day");
String query = Stream.of(myData, last_minute, last_day)
.map(Flux::toString)
.collect(Collectors.joining("\n\n"));
System.out.println(query);
}
public static class MyData extends AbstractParametrizedFlux {
@Nonnull
@Override
protected String operatorName() {
return "mydata";
}
/**
* @param start Specifies the oldest time to be included in the results
* @return this
*/
@Nonnull
public MyData withStart(@Nonnull final String start) {
Arguments.checkDuration(start, "Start");
this.withPropertyValue("start", start);
return this;
}
@Nonnull
@Override
public String toString() {
Flux filter = Flux.from("my-bucket")
.range()
.withPropertyValue("start", "start")
.filter(Restrictions.measurement().equal("temp"));
return operatorName() + " = (start) => \n" + filter;
}
}
}
mydata = (start) =>
from(bucket:"my-bucket")
|> range(start:start)
|> filter(fn: (r) => r["_measurement"] == "temp")
mydata(start:-1m)
|> sum()
|> yield(name:"last_minute")
mydata(start:-1d)
|> sum()
|> yield(name:"last_day")
but the better support will be useful.
Regards