Skip to content

Commit 423f513

Browse files
committed
Migrated from the deprecated Elasticsearch client library (NEST)
1 parent 6e251b6 commit 423f513

19 files changed

Lines changed: 259 additions & 227 deletions

integration-tests/Definitions/GeneratedSampleAggregateRawElasticsearchQuery.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"aggs": {
1515
"by_country": {
1616
"terms": {
17-
"field": "CountryCode.keyword",
17+
"field": "CountryCode",
1818
"size": 100
1919
},
2020
"aggs": {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"QueryCount": 100,
3+
"QueryParallelism": 1
4+
}

src/DatabaseBenchmark/DatabaseBenchmark.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
<PackageReference Include="MonetDB" Version="2.1.2" />
3030
<PackageReference Include="MongoDB.Driver" Version="3.5.0" />
3131
<PackageReference Include="MySqlConnector" Version="2.4.0" />
32-
<PackageReference Include="NEST" Version="7.17.5" />
32+
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="9.2.2" />
3333
<PackageReference Include="Npgsql" Version="9.0.4" />
3434
<PackageReference Include="Octonica.ClickHouseClient" Version="3.1.3" />
3535
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="23.26.0" />
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
using DatabaseBenchmark.Databases.Common.Interfaces;
22
using DatabaseBenchmark.Model;
3-
using Nest;
3+
using Elastic.Clients.Elasticsearch;
4+
using Elastic.Clients.Elasticsearch.IndexManagement;
45

56
namespace DatabaseBenchmark.Databases.Elasticsearch
67
{
78
public class ElasticsearchDataMetricsProvider : IDataMetricsProvider
89
{
9-
private readonly IElasticClient _client;
10+
private readonly ElasticsearchClient _client;
1011
private readonly Table _table;
1112

1213
private IndicesStatsResponse _stats;
1314

14-
public ElasticsearchDataMetricsProvider(IElasticClient client, Table table)
15+
public ElasticsearchDataMetricsProvider(ElasticsearchClient client, Table table)
1516
{
1617
_client = client;
1718
_table = table;
@@ -20,22 +21,22 @@ public ElasticsearchDataMetricsProvider(IElasticClient client, Table table)
2021
public long GetRowCount()
2122
{
2223
EnsureStats();
23-
return _stats.Stats.Primaries.Documents.Count;
24+
return _stats.Indices[_table.Name].Primaries.Docs.Count;
2425
}
2526

2627
public IDictionary<string, double> GetMetrics()
2728
{
2829
EnsureStats();
2930
return new Dictionary<string, double>
3031
{
31-
[Common.Metrics.TotalStorageBytes] = _stats.Stats.Total.Store.SizeInBytes
32+
[Common.Metrics.TotalStorageBytes] = (double)_stats.Indices[_table.Name].Total.Store.SizeInBytes
3233
};
3334
}
3435

3536
private void EnsureStats()
3637
{
37-
_client.Indices.Refresh(_table.Name);
38-
_stats ??= _client.Indices.Stats(_table.Name);
38+
_client.Indices.RefreshAsync(_table.Name).GetAwaiter().GetResult();
39+
_stats ??= _client.Indices.StatsAsync(s => s.Indices(_table.Name)).GetAwaiter().GetResult();
3940
}
4041
}
4142
}

src/DatabaseBenchmark/Databases/Elasticsearch/ElasticsearchDatabase.cs

Lines changed: 33 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
using DatabaseBenchmark.Databases.Elasticsearch.Interfaces;
66
using DatabaseBenchmark.DataSources.Interfaces;
77
using DatabaseBenchmark.Model;
8-
using Nest;
8+
using Elastic.Clients.Elasticsearch;
9+
using Elastic.Clients.Elasticsearch.Mapping;
910
using System.Text;
1011
using RawQuery = DatabaseBenchmark.Model.RawQuery;
1112

@@ -33,16 +34,16 @@ public void CreateTable(Table table, bool dropExisting)
3334

3435
if (dropExisting)
3536
{
36-
var exists = client.Indices.Exists(table.Name);
37-
if (exists.Exists)
37+
var existsResponse = client.Indices.ExistsAsync(table.Name).GetAwaiter().GetResult();
38+
if (existsResponse.Exists)
3839
{
39-
client.Indices.Delete(table.Name);
40+
client.Indices.DeleteAsync(table.Name).GetAwaiter().GetResult();
4041
}
4142
}
4243

43-
client.Indices.CreateAsync(table.Name, ci => ci
44-
.Map(md => md
45-
.Properties(pd => BuildProperties(table, pd)))).Wait();
44+
client.Indices.CreateAsync(table.Name, c => c
45+
.Mappings(m => m
46+
.Properties(BuildProperties(table)))).GetAwaiter().GetResult();
4647
}
4748

4849
public IDataImporter CreateDataImporter(Table table, IDataSource source, int batchSize)
@@ -58,7 +59,7 @@ public IDataImporter CreateDataImporter(Table table, IDataSource source, int bat
5859
.Environment(_environment)
5960
.Customize((container, lifestyle) =>
6061
{
61-
container.Register<IElasticClient>(CreateClient, lifestyle);
62+
container.Register<ElasticsearchClient>(CreateClient, lifestyle);
6263
})
6364
.Build();
6465
}
@@ -74,32 +75,34 @@ public IQueryExecutorFactory CreateInsertExecutorFactory(Table table, IDataSourc
7475

7576
public void ExecuteScript(string script) => throw new InputArgumentException("Custom scripts are not supported for Elasticsearch");
7677

77-
private ElasticClient CreateClient()
78+
private ElasticsearchClient CreateClient()
7879
{
79-
var connectionSettings = new ConnectionSettings(new Uri(ConnectionString))
80+
var settings = new ElasticsearchClientSettings(new Uri(ConnectionString))
8081
.ThrowExceptions();
8182

8283
if (_environment.TraceQueries || _environment.TraceResults)
8384
{
84-
connectionSettings.EnableDebugMode(response =>
85+
settings.EnableDebugMode(details =>
8586
{
86-
if (_environment.TraceQueries && response.RequestBodyInBytes != null)
87+
if (_environment.TraceQueries && details.RequestBodyInBytes != null)
8788
{
88-
_environment.WriteLine(Encoding.UTF8.GetString(response.RequestBodyInBytes));
89+
_environment.WriteLine(Encoding.UTF8.GetString(details.RequestBodyInBytes));
8990
}
9091

91-
if (_environment.TraceResults && response.ResponseBodyInBytes != null)
92+
if (_environment.TraceResults && details.ResponseBodyInBytes != null)
9293
{
93-
_environment.WriteLine(Encoding.UTF8.GetString(response.ResponseBodyInBytes));
94+
_environment.WriteLine(Encoding.UTF8.GetString(details.ResponseBodyInBytes));
9495
}
9596
});
9697
}
9798

98-
return new ElasticClient(connectionSettings);
99+
return new ElasticsearchClient(settings);
99100
}
100101

101-
private PropertiesDescriptor<object> BuildProperties(Table table, PropertiesDescriptor<object> propertiesDescriptor)
102+
private Properties BuildProperties(Table table)
102103
{
104+
var properties = new Properties();
105+
103106
foreach (var column in table.Columns)
104107
{
105108
if (column.DatabaseGenerated)
@@ -108,47 +111,22 @@ private PropertiesDescriptor<object> BuildProperties(Table table, PropertiesDesc
108111
continue;
109112
}
110113

111-
switch (column.Type)
114+
IProperty property = column.Type switch
112115
{
113-
case ColumnType.Boolean:
114-
propertiesDescriptor.Boolean(bpd => bpd
115-
.Name(column.Name)
116-
.Index(column.Queryable));
117-
break;
118-
case ColumnType.Guid:
119-
case ColumnType.String:
120-
propertiesDescriptor.Keyword(kpd => kpd
121-
.Name(column.Name)
122-
.Index(column.Queryable));
123-
break;
124-
case ColumnType.Double:
125-
propertiesDescriptor.Number(npd => npd
126-
.Name(column.Name)
127-
.Type(NumberType.Double)
128-
.Index(column.Queryable));
129-
break;
130-
case ColumnType.Integer:
131-
propertiesDescriptor.Number(npd => npd
132-
.Name(column.Name)
133-
.Type(NumberType.Integer)
134-
.Index(column.Queryable));
135-
break;
136-
case ColumnType.Text:
137-
propertiesDescriptor.Text(tpd => tpd
138-
.Name(column.Name)
139-
.Index(column.Queryable));
140-
break;
141-
case ColumnType.DateTime:
142-
propertiesDescriptor.Date(dpd => dpd
143-
.Name(column.Name)
144-
.Index(column.Queryable));
145-
break;
146-
default:
147-
throw new InputArgumentException($"Unknown column type \"{column.Type}\"");
148-
}
116+
ColumnType.Boolean => new BooleanProperty { Index = column.Queryable },
117+
ColumnType.Guid => new KeywordProperty { Index = column.Queryable },
118+
ColumnType.String => new KeywordProperty { Index = column.Queryable },
119+
ColumnType.Double => new DoubleNumberProperty { Index = column.Queryable },
120+
ColumnType.Integer => new IntegerNumberProperty { Index = column.Queryable },
121+
ColumnType.Text => new TextProperty { Index = column.Queryable },
122+
ColumnType.DateTime => new DateProperty { Index = column.Queryable },
123+
_ => throw new InputArgumentException($"Unknown column type \"{column.Type}\"")
124+
};
125+
126+
properties.Add(column.Name, property);
149127
}
150128

151-
return propertiesDescriptor;
129+
return properties;
152130
}
153131

154132
private static Table NormalizeNames(Table table)
Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
using DatabaseBenchmark.Core.Interfaces;
22
using DatabaseBenchmark.Model;
3-
using Nest;
3+
using Elastic.Clients.Elasticsearch;
4+
using Elastic.Clients.Elasticsearch.Aggregations;
45

56
namespace DatabaseBenchmark.Databases.Elasticsearch
67
{
78
public class ElasticsearchDistinctValuesProvider : IDistinctValuesProvider
89
{
9-
private readonly ElasticClient _client;
10+
private readonly ElasticsearchClient _client;
1011

11-
public ElasticsearchDistinctValuesProvider(ElasticClient client)
12+
public ElasticsearchDistinctValuesProvider(ElasticsearchClient client)
1213
{
1314
_client = client;
1415
}
@@ -18,19 +19,24 @@ public object[] GetDistinctValues(string tableName, IValueDefinition column, boo
1819
const int maxBuckets = 10000;
1920
const string bucketName = "distinct";
2021

21-
var result = _client.Search<object>(sd => sd
22-
.Index(tableName)
22+
var result = _client.SearchAsync<object>(s => s
23+
.Indices(tableName)
2324
.Size(0)
2425
.Aggregations(a => a
25-
.Terms(bucketName, td => td
26-
.Field(column.Name)
27-
.Size(maxBuckets))));
26+
.Add(bucketName, agg => agg
27+
.Terms(t => t
28+
.Field(column.Name)
29+
.Size(maxBuckets))))).GetAwaiter().GetResult();
2830

29-
return result.Aggregations
30-
.Terms<object>(bucketName)
31-
.Buckets
32-
.Select(i => i.Key)
33-
.ToArray();
31+
var aggregate = result.Aggregations[bucketName];
32+
33+
return result.Aggregations[bucketName] switch
34+
{
35+
StringTermsAggregate stringTerms => stringTerms.Buckets.Select(b => (object)b.Key.Value).ToArray(),
36+
LongTermsAggregate longTerms => longTerms.Buckets.Select(b => (object)b.Key).ToArray(),
37+
DoubleTermsAggregate doubleTerms => doubleTerms.Buckets.Select(b => (object)b.Key).ToArray(),
38+
_ => throw new InvalidOperationException($"Unsupported aggregate type: {aggregate.GetType()}")
39+
};
3440
}
3541
}
3642
}

src/DatabaseBenchmark/Databases/Elasticsearch/ElasticsearchInsertExecutor.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
using DatabaseBenchmark.Databases.Elasticsearch.Interfaces;
22
using DatabaseBenchmark.Databases.Common.Interfaces;
33
using DatabaseBenchmark.Model;
4-
using Nest;
4+
using Elastic.Clients.Elasticsearch;
55

66
namespace DatabaseBenchmark.Databases.Elasticsearch
77
{
88
public sealed class ElasticsearchInsertExecutor : IQueryExecutor
99
{
10-
private readonly IElasticClient _client;
10+
private readonly ElasticsearchClient _client;
1111
private readonly Table _table;
1212
private readonly IElasticsearchInsertBuilder _insertBuilder;
1313

1414
public ElasticsearchInsertExecutor(
15-
IElasticClient client,
15+
ElasticsearchClient client,
1616
Table table,
1717
IElasticsearchInsertBuilder insertBuilder)
1818
{

src/DatabaseBenchmark/Databases/Elasticsearch/ElasticsearchInsertExecutorFactory.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
using DatabaseBenchmark.Databases.Elasticsearch.Interfaces;
44
using DatabaseBenchmark.DataSources.Interfaces;
55
using DatabaseBenchmark.Model;
6-
using Nest;
6+
using Elastic.Clients.Elasticsearch;
77
using SimpleInjector;
88

99
namespace DatabaseBenchmark.Databases.Elasticsearch
1010
{
1111
public class ElasticsearchInsertExecutorFactory : QueryExecutorFactoryBase
1212
{
1313
public ElasticsearchInsertExecutorFactory(
14-
Func<ElasticClient> createClient,
14+
Func<ElasticsearchClient> createClient,
1515
Table table,
1616
IDataSource source,
1717
int batchSize)
@@ -24,7 +24,7 @@ public ElasticsearchInsertExecutorFactory(
2424

2525
Container.RegisterSingleton<IDataSourceReader, DataSourceReader>();
2626

27-
Container.Register<IElasticClient>(createClient, Lifestyle);
27+
Container.Register<ElasticsearchClient>(createClient, Lifestyle);
2828
Container.Register<IElasticsearchInsertBuilder, ElasticsearchInsertBuilder>(Lifestyle);
2929
Container.Register<IQueryExecutor, ElasticsearchInsertExecutor>(Lifestyle);
3030
}

src/DatabaseBenchmark/Databases/Elasticsearch/ElasticsearchPreparedInsert.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
using DatabaseBenchmark.Databases.Common.Interfaces;
22
using DatabaseBenchmark.Model;
3-
using Nest;
3+
using Elastic.Clients.Elasticsearch;
44

55
namespace DatabaseBenchmark.Databases.Elasticsearch
66
{
77
public sealed class ElasticsearchPreparedInsert : IPreparedQuery
88
{
9-
private readonly IElasticClient _client;
9+
private readonly ElasticsearchClient _client;
1010
private readonly Table _table;
1111
private readonly IEnumerable<object> _documents;
1212

@@ -15,7 +15,7 @@ public sealed class ElasticsearchPreparedInsert : IPreparedQuery
1515
public IQueryResults Results => null;
1616

1717
public ElasticsearchPreparedInsert(
18-
IElasticClient client,
18+
ElasticsearchClient client,
1919
Table table,
2020
IEnumerable<object> documents)
2121
{
@@ -27,9 +27,9 @@ public ElasticsearchPreparedInsert(
2727
public int Execute()
2828
{
2929
//TODO: make refresh parameter configurable
30-
var response = _client.Bulk(b => b
30+
var response = _client.BulkAsync(b => b
3131
.Index(_table.Name.ToLower())
32-
.IndexMany(_documents));
32+
.IndexMany(_documents)).GetAwaiter().GetResult();
3333

3434
return response.Items.Count;
3535
}

src/DatabaseBenchmark/Databases/Elasticsearch/ElasticsearchPreparedQuery.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
using DatabaseBenchmark.Databases.Common.Interfaces;
2-
using Nest;
2+
using Elastic.Clients.Elasticsearch;
33

44
namespace DatabaseBenchmark.Databases.Elasticsearch
55
{
66
public sealed class ElasticsearchPreparedQuery : IPreparedQuery
77
{
8-
private readonly ElasticClient _client;
8+
private readonly ElasticsearchClient _client;
99
private readonly SearchRequest _request;
1010

1111
private ElasticsearchQueryResults _results;
@@ -14,15 +14,15 @@ public sealed class ElasticsearchPreparedQuery : IPreparedQuery
1414

1515
public IQueryResults Results => _results;
1616

17-
public ElasticsearchPreparedQuery(ElasticClient client, SearchRequest request)
17+
public ElasticsearchPreparedQuery(ElasticsearchClient client, SearchRequest request)
1818
{
1919
_client = client;
2020
_request = request;
2121
}
2222

2323
public int Execute()
2424
{
25-
var response = _client.Search<Dictionary<string, object>>(_request);
25+
var response = _client.SearchAsync<Dictionary<string, object>>(_request).GetAwaiter().GetResult();
2626
_results = new ElasticsearchQueryResults(response);
2727

2828
return 0;

0 commit comments

Comments
 (0)