Skip to content
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## 6.7.0 [unreleased]

### Features
1. [#439](https://github.com/influxdata/influxdb-client-java/pull/439): Added `FluxRecord.getRow()` which stores response data in a list

### Dependencies
Update dependencies:

Expand Down
13 changes: 12 additions & 1 deletion client-core/src/main/java/com/influxdb/query/FluxRecord.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import java.io.Serializable;
import java.time.Instant;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -50,6 +51,8 @@ public final class FluxRecord implements Serializable {
*/
private LinkedHashMap<String, Object> values = new LinkedHashMap<>();

private ArrayList<Object> row = new ArrayList<>();

public FluxRecord(@Nonnull final Integer table) {

Arguments.checkNotNull(table, "Table index");
Expand Down Expand Up @@ -121,6 +124,14 @@ public Map<String, Object> getValues() {
return values;
}

/**
* @return record's columns
*/
@Nonnull
public ArrayList<Object> getRow() {
return row;
}

/**
* Get FluxRecord value by index.
*
Expand Down Expand Up @@ -168,7 +179,7 @@ public boolean equals(final Object o) {
}
final FluxRecord that = (FluxRecord) o;
return Objects.equals(table, that.table)
&& Objects.equals(values, that.values);
&& Objects.equals(values, that.values);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
Expand Down Expand Up @@ -276,7 +277,11 @@ private FluxRecord parseRecord(final int tableIndex, final FluxTable table, fina

String strValue = csvRecord.get(fluxColumn.getIndex() + 1);

record.getValues().put(columnName, toValue(strValue, fluxColumn));
Object value = toValue(strValue, fluxColumn);

record.getValues().put(columnName, value);

record.getRow().add(value);
}
return record;
}
Expand Down Expand Up @@ -398,6 +403,15 @@ private void addColumnNamesAndTags(@Nonnull final FluxTable table, @Nonnull fina
String columnName = columnNames.get(i);
fluxColumn.setLabel(columnName);
}

HashSet<Object> seen = new HashSet<>();
columnNames.removeIf(seen::add);

if (!columnNames.isEmpty()) {
System.out.printf("The response contains columns with duplicated names: %s)%n", columnNames);
System.out.println("You should use the \"FluxRecord.getRow()\" to access your data instead of "
+ "\"FluxRecord.getValues()\".");
}
}

@Nonnull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,25 @@ public void parseInf() throws IOException {
Assertions.assertThat(tables.get(0).getRecords().get(11).getValueByKey("le")).isEqualTo(Double.NEGATIVE_INFINITY);
}

@Test
public void parseDuplicateColumnNames() throws IOException {
String data = "#datatype,string,long,dateTime:RFC3339,dateTime:RFC3339,dateTime:RFC3339,string,string,double\n" +
"#group,false,false,true,true,false,true,true,false\n" +
"#default,_result,,,,,,,\n" +
" ,result,table,_start,_stop,_time,_measurement,location,result\n" +
",,0,2022-09-13T06:14:40.469404272Z,2022-09-13T06:24:40.469404272Z,2022-09-13T06:24:33.746Z,my_measurement,Prague,25.3\n" +
",,0,2022-09-13T06:14:40.469404272Z,2022-09-13T06:24:40.469404272Z,2022-09-13T06:24:39.299Z,my_measurement,Prague,25.3\n" +
",,0,2022-09-13T06:14:40.469404272Z,2022-09-13T06:24:40.469404272Z,2022-09-13T06:24:40.454Z,my_measurement,Prague,25.3\n";

List<FluxTable> tables = parseFluxResponse(data);
Assertions.assertThat(tables).hasSize(1);
Assertions.assertThat(tables.get(0).getRecords()).hasSize(3);
Assertions.assertThat(tables.get(0).getColumns()).hasSize(8);
Assertions.assertThat(tables.get(0).getRecords().get(0).getValues().size()).isEqualTo(7);
Assertions.assertThat(tables.get(0).getRecords().get(0).getRow().size()).isEqualTo(8);
Assertions.assertThat(tables.get(0).getRecords().get(0).getRow().get(7)).isEqualTo(25.3);
}

@Nonnull
private List<FluxTable> parseFluxResponse(@Nonnull final String data) throws IOException {

Expand Down
2 changes: 2 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ This directory contains Java, Kotlin and Scala examples.
### Others
- [InvokableScripts.java](src/main/java/example/InvokableScripts.java) - How to use Invokable scripts Cloud API to create custom endpoints that query data
- [InfluxDBEnterpriseExample.java](src/main/java/example/InfluxDBEnterpriseExample.java) - How to use `consistency` parameter for InfluxDB Enterprise
- [RecordRowExample.java](src/main/java/example/RecordRowExample.java) - How to use FluxRecord.getRow() (List) instead of FluxRecord.getValues() (Map),
in case of duplicity column names

## Kotlin

Expand Down
83 changes: 83 additions & 0 deletions examples/src/main/java/example/RecordRowExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package example;

import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.InfluxDBClientFactory;
import com.influxdb.client.QueryApi;
import com.influxdb.client.WriteApiBlocking;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.query.FluxRecord;
import com.influxdb.query.FluxTable;

import java.util.List;

public class RecordRowExample {

public static void main(final String[] args) throws Exception {

final char[] token = "my-token".toCharArray();
final String org = "my-org";
final String bucket = "my-bucket";

InfluxDBClient influxDBClient = InfluxDBClientFactory.create("http://localhost:9999", token, org, bucket);

//
// Prepare Data
//
WriteApiBlocking writeApi = influxDBClient.getWriteApiBlocking();
for (int i = 1; i <= 5; i++)
writeApi.writeRecord(WritePrecision.NS, String.format("point,table=my-table result=%d", i));

//
// Query data
//
String fluxQuery = String.format("from(bucket: \"%s\")\n", bucket)
+ " |> range(start: -1m)"
+ " |> filter(fn: (r) => (r[\"_measurement\"] == \"point\"))"
+ " |> pivot(rowKey:[\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")";

QueryApi queryApi = influxDBClient.getQueryApi();

//
// Query data
//
List<FluxTable> tables = queryApi.query(fluxQuery);
System.out.println("--------------------------------- FluxRecord.getValues() --------------------------------");
for (FluxTable fluxTable : tables) {
List<FluxRecord> records = fluxTable.getRecords();
for (FluxRecord fluxRecord : records) {
System.out.println(fluxRecord.getValues());
}
}

System.out.println("---------------------------------- FluxRecord.getRow() ----------------------------------");
for (FluxTable fluxTable : tables) {
List<FluxRecord> records = fluxTable.getRecords();
for (FluxRecord fluxRecord : records) {
System.out.println(fluxRecord.getRow());
}
}

influxDBClient.close();
}
}