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 @@
## 4.7.0 [unreleased]

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

### Dependencies
Update dependencies:

Expand Down
5 changes: 5 additions & 0 deletions Client.Core/Flux/Domain/FluxRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public class FluxRecord
/// </summary>
public Dictionary<string, object> Values { get; } = new Dictionary<string, object>();

/// <summary>
/// The record's columns.
/// </summary>
public List<object> Row { get; } = new List<object>();

public FluxRecord(int table)
{
Table = table;
Expand Down
16 changes: 15 additions & 1 deletion Client.Core/Flux/Internal/FluxCsvParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,11 @@ private FluxRecord ParseRecord(int tableIndex, FluxTable table, CsvReader csv)

var strValue = csv[fluxColumn.Index + 1];

record.Values.Add(columnName, ToValue(strValue, fluxColumn));
var value = ToValue(strValue, fluxColumn);

record.Values[columnName] = value;

record.Row.Add(value);
}

return record;
Expand Down Expand Up @@ -389,6 +393,16 @@ private void AddColumnNamesAndTags(FluxTable table, CsvReader columnNames)
var fluxColumn = GetFluxColumn(ii, table);
fluxColumn.Label = columnNames[ii + 1];
}

var duplicates = table.Columns.GroupBy(col => col.Label)
.Where(rec => rec.Count() > 1)
.Select(label => label.Key).ToList();
if (duplicates.Any())
{
Console.WriteLine(
$"The response contains columns with duplicated names: {string.Join(", ", duplicates)}\n" +
"You should use the 'FluxRecord.Row to access your data instead of 'FluxRecord.Values' dictionary.");
}
}

private FluxColumn GetFluxColumn(int columnIndex, FluxTable table)
Expand Down
22 changes: 22 additions & 0 deletions Client.Legacy.Test/FluxCsvParserTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,28 @@ public void ParseWithoutDatatype()
Assert.AreEqual("west", tables[0].Records[0].GetValueByKey("region"));
}

[Test]
public void ParseDuplicateColumnNames()
{
const 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";

_parser = new FluxCsvParser(FluxCsvParser.ResponseMode.OnlyNames);
var tables = ParseFluxResponse(data);
Assert.AreEqual(1, tables.Count);
Assert.AreEqual(8, tables[0].Columns.Count);
Assert.AreEqual(3, tables[0].Records.Count);
Assert.AreEqual(7, tables[0].Records[0].Values.Count);
Assert.AreEqual(8, tables[0].Records[0].Row.Count);
Assert.AreEqual(25.3, tables[0].Records[0].Row[7]);
}

private List<FluxTable> ParseFluxResponse(string data)
{
var consumer = new FluxCsvParser.FluxResponseConsumerTable();
Expand Down
2 changes: 2 additions & 0 deletions Examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
## Others
- [InvokableScripts.cs](InvokableScripts.cs) - How to use Invokable scripts Cloud API to create custom endpoints that query data
- [ParametrizedQuery.cs](ParametrizedQuery.cs) - How to use parameterized Flux queries
- [RecordRowExample.cs](RecordRowExample.cs) - How to use FluxRecord.Row (List) instead of FluxRecord.Values (Dictionary),
in case of duplicity column names
56 changes: 56 additions & 0 deletions Examples/RecordRowExample.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;


namespace Examples
{
public static class RecordRowExample
{
public static async Task Main()
{
const string url = "http://localhost:9999/";
const string token = "my-token";
const string bucket = "my-bucket";
const string org = "my-org";

using var client = InfluxDBClientFactory.Create(url, token.ToCharArray());

//
// Prepare Data
//
var writeApi = client.GetWriteApiAsync();
for (var i = 1; i <= 5; i++)
await writeApi.WriteRecordAsync($"point,table=my-table result={i}", WritePrecision.Ns, bucket, org);

//
// Query data with pivot
//
var queryApi = client.GetQueryApi();
var fluxQuery = $"from(bucket: \"{bucket}\")\n"
+ " |> range(start: -1m)"
+ " |> filter(fn: (r) => (r[\"_measurement\"] == \"point\"))"
+ " |> pivot(rowKey:[\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")";
var tables = await queryApi.QueryAsync(fluxQuery, org);

//
// Write data to output
//
if (tables != null)
{
// using FluxRecord.Values - Dictionary<string,object> - can`t contains duplicity key names
Console.WriteLine("-------------------------------- FluxRecord.Values -------------------------------");
foreach (var fluxRecord in tables.SelectMany(fluxTable => fluxTable.Records))
Console.WriteLine("{" + string.Join(", ",
fluxRecord.Values.Select(kv => kv.Key + ": " + kv.Value).ToArray()) + "}");

// using FluxRecord.Row - List<KeyValuePair<string, object>> - contains all data
Console.WriteLine("--------------------------------- FluxRecord.Row ---------------------------------");
foreach (var fluxRecord in tables.SelectMany(fluxTable => fluxTable.Records))
Console.WriteLine("{" + string.Join(", ", fluxRecord.Row) + "}");
}
}
}
}
5 changes: 4 additions & 1 deletion Examples/RunExamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ public static async Task Main(string[] args)
case "ParametrizedQuery":
await ParametrizedQuery.Main(args);
break;
case "RecordRowExample":
await RecordRowExample.Main();
break;
}
}
else
Expand All @@ -78,7 +81,7 @@ public static async Task Main(string[] args)
"FluxClientPocoExample, PlatformExample, WriteEventHandlerExample, WriteApiAsyncExample, " +
"CustomDomainMapping, PocoQueryWriteExample, CustomDomainMappingAndLinq, " +
"SynchronousQuery, InfluxDB18Example, QueryLinqCloud, ManagementExample, " +
" InvokableScripts, ParametrizedQuery");
" InvokableScripts, ParametrizedQuery, RecordRowExample");
}
}
}
Expand Down