More advanced conditional math expressions in a map() function

I’m trying to do some slightly more advanced mathematics within conditional expressions of a map() function.

I’m using Influx 1.7.8 (i.e. the latest) running on Ubuntu 18.04.1 LTS

Below is a slightly redacted copy of my query, which just returns [object Object] in Chronograf:

from(bucket: "my_bucket")
  |> range(start: dashboardTime)
  |> filter(fn: (r) => r.controller_id == "304511028a28" and (r._field == "bms_batt_v" or r._field == "bms_batt_a" or r._field == "bms_soc" or r._field == "bms_soh" or r._field == "rectifier_1_v" or r._field == "rectifier_1_a" or r._field == "rectifier_2_v" or r._field == "rectifier_2_a"))
  |> last()
  |> keep(columns: ["_time", "_value", "_field"])
  |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
  |> map(fn: (r) => ({
      _time: r._time,
      _value:
        if r.bms_batt_a < 0 then
          (100.0 * (r.bms_soh / 100.0) * (r.bms_soc / 100.0)) / (r.bms_batt_a * 0.95 * -1.0)
        else
          (100.0 * (r.bms_soh / 100.0) * (r.bms_soc / 100.0)) / ((((r.rectifier_1_a * r.rectifier_1_v) + (r.rectifier_2_a * r.rectifier_2_v))/r.bms_batt_v) * 0.95)
     }))

If I remove the condition then everything works perfectly:

from(bucket: "my_bucket")
  |> range(start: dashboardTime)
  |> filter(fn: (r) => r.controller_id == "304511028a28" and (r._field == "bms_batt_v" or r._field == "bms_batt_a" or r._field == "bms_soc" or r._field == "bms_soh" or r._field == "rectifier_1_v" or r._field == "rectifier_1_a" or r._field == "rectifier_2_v" or r._field == "rectifier_2_a"))
  |> last()
  |> keep(columns: ["_time", "_value", "_field"])
  |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
  |> map(fn: (r) => ({
      _time: r._time,
      _value: (100.0 * (r.bms_soh / 100.0) * (r.bms_soc / 100.0)) / (r.bms_batt_a * 0.95 * -1.0)
     }))

If I simplify the calculations within the conditional statement then the query works too.

from(bucket: "my_bucket")
  |> range(start: dashboardTime)
  |> filter(fn: (r) => r.controller_id == "304511028a28" and (r._field == "bms_batt_v" or r._field == "bms_batt_a" or r._field == "bms_soc" or r._field == "bms_soh" or r._field == "rectifier_1_v" or r._field == "rectifier_1_a" or r._field == "rectifier_2_v" or r._field == "rectifier_2_a"))
  |> last()
  |> keep(columns: ["_time", "_value", "_field"])
  |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
  |> map(fn: (r) => ({
      _time: r._time,
      _value:
        if r.bms_batt_a < 0 then
          1.0 * 2.0
        else
          3.0 + 4.0
     }))

But if I put brackets around those 2 simple statements then the query doesn’t work, once again returning [object Object]

from(bucket: "my_bucket")
  |> range(start: dashboardTime)
  |> filter(fn: (r) => r.controller_id == "304511028a28" and (r._field == "bms_batt_v" or r._field == "bms_batt_a" or r._field == "bms_soc" or r._field == "bms_soh" or r._field == "rectifier_1_v" or r._field == "rectifier_1_a" or r._field == "rectifier_2_v" or r._field == "rectifier_2_a"))
  |> last()
  |> keep(columns: ["_time", "_value", "_field"])
  |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
  |> map(fn: (r) => ({
      _time: r._time,
      _value:
        if r.bms_batt_a < 0 then
          (1.0 * 2.0)
        else
          (3.0 + 4.0)
     }))

I have also tried calling a custom function for each condition but this also returns [object Object]

All help is greatly appreciated :pray:

I have exact same problem here…did you managed to fix this?

Hi @migo. Unfortunately, I haven’t yet found a solution, no.

I thought I’d first post my findings here and if it is a real issue I’ll then raise one on GitHub.

I have logged an issue in Github:

It might be worth validating the query using the InfluxDB 2.0 alpha – that version of Flux is rev’ing a bit faster. Alpha 18 is on Flux 0.49.x…

InfluxDB 1.7.9 will receive an update to at least 0.49.x when it rolls out shortly.

1 Like

Hey all,
The syntax has changed a little.
Here is an example of using a conditional with a map function

|> map(fn: (r) => ({
        r with heatIndex:
            if  (_steadman(t: r.temperature, h: r.humidity) + r.temperature)/2.0 < 80.0  then _steadman(t: r.temperature, h: r.humidity)
            else if ( r.humidty < 13.0 and r.temperature > 80.0) then (_rothfusz(t: r.temperature, h: r.humidity) - (((13.0-r.humidity)/4.0)*math.sqrt(x: ((17.0-math.abs(x: (r.temperature-95.0))/17.0)))))
            else if r.humidity > 85.0 and r.temperature >= 80.0 and r.temperature <= 87.0 then (_rothfusz(t: r.temperature, h: r.humidity) + (( r.humidity-85.0 )/10.0) *((87.0-r.temperature)/5.0))
            else (_rothfusz(t: r.temperature, h: r.humidity))
    }))

You have to specify r with _value because to specify the output table column from the input table because of the use of with.

1 Like

What I found out from creating a Github issue is that the error doesn’t lie with the FluxQL interpreter, but rather with Chronograf (v1.7.14), which is having a hard time interpreting the more complex mathematical expression. If I just run it in the terminal then all works fine.

Thanks for this input @Anaisdg. I tried doing this with my query but it fails. Is this syntax change only valid for FluxQL versions > 0.36.2?

1 Like