Skip to content

Commit c6be6c7

Browse files
committed
WIP - Upgrade to the new Elasticsearch client
1 parent a4b976f commit c6be6c7

24 files changed

+313
-301
lines changed

src/Foundatio.Parsers.ElasticQueries/ElasticMappingResolver.cs

+103-74
Large diffs are not rendered by default.

src/Foundatio.Parsers.ElasticQueries/ElasticQueryParser.cs

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Threading.Tasks;
5+
using Elastic.Clients.Elasticsearch;
6+
using Elastic.Clients.Elasticsearch.Aggregations;
7+
using Elastic.Clients.Elasticsearch.QueryDsl;
58
using Foundatio.Parsers.ElasticQueries.Extensions;
69
using Foundatio.Parsers.ElasticQueries.Visitors;
710
using Foundatio.Parsers.LuceneQueries;
811
using Foundatio.Parsers.LuceneQueries.Extensions;
912
using Foundatio.Parsers.LuceneQueries.Nodes;
1013
using Foundatio.Parsers.LuceneQueries.Visitors;
11-
using Nest;
1214
using Pegasus.Common;
1315

1416
namespace Foundatio.Parsers.ElasticQueries;
@@ -158,7 +160,7 @@ public async Task<QueryValidationResult> ValidateQueryAsync(string query, QueryV
158160
return context.GetValidationResult();
159161
}
160162

161-
public async Task<QueryContainer> BuildQueryAsync(string query, IElasticQueryVisitorContext context = null)
163+
public async Task<Query> BuildQueryAsync(string query, IElasticQueryVisitorContext context = null)
162164
{
163165
context ??= new ElasticQueryVisitorContext();
164166
context.QueryType = QueryTypes.Query;
@@ -169,7 +171,7 @@ public async Task<QueryContainer> BuildQueryAsync(string query, IElasticQueryVis
169171
return await BuildQueryAsync(result, context).ConfigureAwait(false);
170172
}
171173

172-
public async Task<QueryContainer> BuildQueryAsync(IQueryNode query, IElasticQueryVisitorContext context = null)
174+
public async Task<Query> BuildQueryAsync(IQueryNode query, IElasticQueryVisitorContext context = null)
173175
{
174176
context ??= new ElasticQueryVisitorContext();
175177
var q = await query.GetQueryAsync() ?? new MatchAllQuery();
@@ -195,7 +197,7 @@ public async Task<QueryValidationResult> ValidateAggregationsAsync(string query,
195197
return context.GetValidationResult();
196198
}
197199

198-
public async Task<AggregationContainer> BuildAggregationsAsync(string aggregations, IElasticQueryVisitorContext context = null)
200+
public async Task<Aggregation> BuildAggregationsAsync(string aggregations, IElasticQueryVisitorContext context = null)
199201
{
200202
context ??= new ElasticQueryVisitorContext();
201203
context.QueryType = QueryTypes.Aggregation;
@@ -207,7 +209,7 @@ public async Task<AggregationContainer> BuildAggregationsAsync(string aggregatio
207209
}
208210

209211
#pragma warning disable IDE0060 // Remove unused parameter
210-
public async Task<AggregationContainer> BuildAggregationsAsync(IQueryNode aggregations, IElasticQueryVisitorContext context = null)
212+
public async Task<Aggregation> BuildAggregationsAsync(IQueryNode aggregations, IElasticQueryVisitorContext context = null)
211213
{
212214
if (aggregations == null)
213215
return null;
@@ -227,7 +229,7 @@ public async Task<QueryValidationResult> ValidateSortAsync(string query, QueryVa
227229
return context.GetValidationResult();
228230
}
229231

230-
public async Task<IEnumerable<IFieldSort>> BuildSortAsync(string sort, IElasticQueryVisitorContext context = null)
232+
public async Task<IEnumerable<SortOptions>> BuildSortAsync(string sort, IElasticQueryVisitorContext context = null)
231233
{
232234
context ??= new ElasticQueryVisitorContext();
233235
context.QueryType = QueryTypes.Sort;
@@ -238,7 +240,7 @@ public async Task<IEnumerable<IFieldSort>> BuildSortAsync(string sort, IElasticQ
238240
return await BuildSortAsync(result, context).ConfigureAwait(false);
239241
}
240242

241-
public Task<IEnumerable<IFieldSort>> BuildSortAsync(IQueryNode sort, IElasticQueryVisitorContext context = null)
243+
public Task<IEnumerable<SortOptions>> BuildSortAsync(IQueryNode sort, IElasticQueryVisitorContext context = null)
242244
{
243245
context ??= new ElasticQueryVisitorContext();
244246
return GetSortFieldsVisitor.RunAsync(sort, context);

src/Foundatio.Parsers.ElasticQueries/ElasticQueryParserConfiguration.cs

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Threading.Tasks;
4+
using Elastic.Clients.Elasticsearch;
5+
using Elastic.Clients.Elasticsearch.Mapping;
46
using Foundatio.Parsers.ElasticQueries.Visitors;
57
using Foundatio.Parsers.LuceneQueries;
68
using Foundatio.Parsers.LuceneQueries.Visitors;
79
using Microsoft.Extensions.Logging;
810
using Microsoft.Extensions.Logging.Abstractions;
9-
using Nest;
1011

1112
namespace Foundatio.Parsers.ElasticQueries;
1213

@@ -285,35 +286,35 @@ public ElasticQueryParserConfiguration AddAggregationVisitorAfter<T>(IChainableQ
285286

286287
#endregion
287288

288-
public ElasticQueryParserConfiguration UseMappings<T>(Func<TypeMappingDescriptor<T>, TypeMappingDescriptor<T>> mappingBuilder, IElasticClient client, string index) where T : class
289+
public ElasticQueryParserConfiguration UseMappings<T>(Func<TypeMappingDescriptor<T>, TypeMappingDescriptor<T>> mappingBuilder, ElasticsearchClient client, string index) where T : class
289290
{
290291
MappingResolver = ElasticMappingResolver.Create<T>(mappingBuilder, client, index, logger: _logger);
291292

292293
return this;
293294
}
294295

295-
public ElasticQueryParserConfiguration UseMappings<T>(Func<TypeMappingDescriptor<T>, TypeMappingDescriptor<T>> mappingBuilder, Inferrer inferrer, Func<ITypeMapping> getMapping) where T : class
296+
public ElasticQueryParserConfiguration UseMappings<T>(Func<TypeMappingDescriptor<T>, TypeMappingDescriptor<T>> mappingBuilder, Inferrer inferrer, Func<TypeMapping> getMapping) where T : class
296297
{
297298
MappingResolver = ElasticMappingResolver.Create<T>(mappingBuilder, inferrer, getMapping, logger: _logger);
298299

299300
return this;
300301
}
301302

302-
public ElasticQueryParserConfiguration UseMappings<T>(IElasticClient client)
303+
public ElasticQueryParserConfiguration UseMappings<T>(ElasticsearchClient client)
303304
{
304305
MappingResolver = ElasticMappingResolver.Create<T>(client, logger: _logger);
305306

306307
return this;
307308
}
308309

309-
public ElasticQueryParserConfiguration UseMappings(IElasticClient client, string index)
310+
public ElasticQueryParserConfiguration UseMappings(ElasticsearchClient client, string index)
310311
{
311312
MappingResolver = ElasticMappingResolver.Create(client, index, logger: _logger);
312313

313314
return this;
314315
}
315316

316-
public ElasticQueryParserConfiguration UseMappings(Func<ITypeMapping> getMapping, Inferrer inferrer = null)
317+
public ElasticQueryParserConfiguration UseMappings(Func<TypeMapping> getMapping, Inferrer inferrer = null)
317318
{
318319
MappingResolver = ElasticMappingResolver.Create(getMapping, inferrer, logger: _logger);
319320

src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultAggregationNodeExtensions.cs

+53-42
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Threading.Tasks;
4+
using Elastic.Clients.Elasticsearch;
5+
using Elastic.Clients.Elasticsearch.Aggregations;
46
using Exceptionless.DateTimeExtensions;
57
using Foundatio.Parsers.ElasticQueries.Visitors;
68
using Foundatio.Parsers.LuceneQueries.Extensions;
79
using Foundatio.Parsers.LuceneQueries.Nodes;
810
using Foundatio.Parsers.LuceneQueries.Visitors;
9-
using Nest;
1011

1112
namespace Foundatio.Parsers.ElasticQueries.Extensions;
1213

@@ -15,7 +16,7 @@ public static class DefaultAggregationNodeExtensions
1516
// NOTE: We may want to read this dynamically from server settings.
1617
public const int MAX_BUCKET_SIZE = 10000;
1718

18-
public static Task<AggregationBase> GetDefaultAggregationAsync(this IQueryNode node, IQueryVisitorContext context)
19+
public static Task<Aggregation> GetDefaultAggregationAsync(this IQueryNode node, IQueryVisitorContext context)
1920
{
2021
if (node is GroupNode groupNode)
2122
return groupNode.GetDefaultAggregationAsync(context);
@@ -26,7 +27,7 @@ public static Task<AggregationBase> GetDefaultAggregationAsync(this IQueryNode n
2627
return null;
2728
}
2829

29-
public static async Task<AggregationBase> GetDefaultAggregationAsync(this GroupNode node, IQueryVisitorContext context)
30+
public static async Task<Aggregation> GetDefaultAggregationAsync(this GroupNode node, IQueryVisitorContext context)
3031
{
3132
if (context is not IElasticQueryVisitorContext elasticContext)
3233
throw new ArgumentException("Context must be of type IElasticQueryVisitorContext", nameof(context));
@@ -47,29 +48,34 @@ public static async Task<AggregationBase> GetDefaultAggregationAsync(this GroupN
4748
return GetHistogramAggregation("histogram_" + originalField, field, node.UnescapedProximity, node.UnescapedBoost, context);
4849

4950
case AggregationType.GeoHashGrid:
50-
var precision = GeoHashPrecision.Precision1;
51-
if (!String.IsNullOrEmpty(node.UnescapedProximity))
52-
Enum.TryParse(node.UnescapedProximity, out precision);
51+
var precision = new GeohashPrecision(1);
52+
if (!String.IsNullOrEmpty(node.UnescapedProximity) && Double.TryParse(node.UnescapedProximity, out double parsedPrecision))
53+
{
54+
if (parsedPrecision is < 1 or > 12)
55+
throw new ArgumentOutOfRangeException(nameof(node.UnescapedProximity), "Precision must be between 1 and 12");
56+
57+
precision = new GeohashPrecision(parsedPrecision);
58+
}
5359

54-
return new GeoHashGridAggregation("geogrid_" + originalField)
60+
return new Aggregation("geogrid_" + originalField, new GeohashGridAggregation
5561
{
5662
Field = field,
5763
Precision = precision,
5864
Aggregations = new AverageAggregation("avg_lat", null)
5965
{
60-
Script = new InlineScript($"doc['{node.Field}'].lat")
66+
Script = new Script { Source = $"doc['{node.Field}'].lat" }
6167
} && new AverageAggregation("avg_lon", null)
6268
{
63-
Script = new InlineScript($"doc['{node.Field}'].lon")
69+
Script = new Script { Source = $"doc['{node.Field}'].lon" }
6470
}
65-
};
71+
});
6672

6773
case AggregationType.Terms:
6874
var agg = new TermsAggregation("terms_" + originalField)
6975
{
7076
Field = field,
7177
Size = node.GetProximityAsInt32(),
72-
MinimumDocumentCount = node.GetBoostAsInt32(),
78+
MinDocCount = node.GetBoostAsInt32(),
7379
Meta = new Dictionary<string, object> { { "@field_type", property?.Type } }
7480
};
7581

@@ -85,7 +91,7 @@ public static async Task<AggregationBase> GetDefaultAggregationAsync(this GroupN
8591
return null;
8692
}
8793

88-
public static async Task<AggregationBase> GetDefaultAggregationAsync(this TermNode node, IQueryVisitorContext context)
94+
public static async Task<Aggregation> GetDefaultAggregationAsync(this TermNode node, IQueryVisitorContext context)
8995
{
9096
if (context is not IElasticQueryVisitorContext elasticContext)
9197
throw new ArgumentException("Context must be of type IElasticQueryVisitorContext", nameof(context));
@@ -134,20 +140,25 @@ public static async Task<AggregationBase> GetDefaultAggregationAsync(this TermNo
134140
return GetPercentilesAggregation("percentiles_" + originalField, aggField, node.UnescapedProximity, node.UnescapedBoost, context);
135141

136142
case AggregationType.GeoHashGrid:
137-
var precision = GeoHashPrecision.Precision1;
138-
if (!String.IsNullOrEmpty(node.UnescapedProximity))
139-
Enum.TryParse(node.UnescapedProximity, out precision);
143+
var precision = new GeohashPrecision(1);
144+
if (!String.IsNullOrEmpty(node.UnescapedProximity) && Double.TryParse(node.UnescapedProximity, out double parsedPrecision))
145+
{
146+
if (parsedPrecision is < 1 or > 12)
147+
throw new ArgumentOutOfRangeException(nameof(node.UnescapedProximity), "Precision must be between 1 and 12");
148+
149+
precision = new GeohashPrecision(parsedPrecision);
150+
}
140151

141-
return new GeoHashGridAggregation("geogrid_" + originalField)
152+
return new GeohashGridAggregation("geogrid_" + originalField)
142153
{
143154
Field = aggField,
144155
Precision = precision,
145156
Aggregations = new AverageAggregation("avg_lat", null)
146157
{
147-
Script = new InlineScript($"doc['{node.Field}'].lat")
158+
Script = new Script { Source = $"doc['{node.Field}'].lat" }
148159
} && new AverageAggregation("avg_lon", null)
149160
{
150-
Script = new InlineScript($"doc['{node.Field}'].lon")
161+
Script = new Script { Source = $"doc['{node.Field}'].lon" }
151162
}
152163
};
153164

@@ -156,7 +167,7 @@ public static async Task<AggregationBase> GetDefaultAggregationAsync(this TermNo
156167
{
157168
Field = aggField,
158169
Size = node.GetProximityAsInt32(),
159-
MinimumDocumentCount = node.GetBoostAsInt32(),
170+
MinDocCount = node.GetBoostAsInt32(),
160171
Meta = new Dictionary<string, object> { { "@field_type", property?.Type } }
161172
};
162173

@@ -169,7 +180,7 @@ public static async Task<AggregationBase> GetDefaultAggregationAsync(this TermNo
169180
return null;
170181
}
171182

172-
private static AggregationBase GetPercentilesAggregation(string originalField, string field, string proximity, string boost, IQueryVisitorContext context)
183+
private static Aggregation GetPercentilesAggregation(string originalField, string field, string proximity, string boost, IQueryVisitorContext context)
173184
{
174185
List<double> percents = null;
175186
if (!String.IsNullOrWhiteSpace(proximity))
@@ -189,7 +200,7 @@ private static AggregationBase GetPercentilesAggregation(string originalField, s
189200
};
190201
}
191202

192-
private static AggregationBase GetHistogramAggregation(string originalField, string field, string proximity, string boost, IQueryVisitorContext context)
203+
private static Aggregation GetHistogramAggregation(string originalField, string field, string proximity, string boost, IQueryVisitorContext context)
193204
{
194205
double interval = 50;
195206
if (Double.TryParse(proximity, out double prox))
@@ -198,25 +209,25 @@ private static AggregationBase GetHistogramAggregation(string originalField, str
198209
return new HistogramAggregation(originalField)
199210
{
200211
Field = field,
201-
MinimumDocumentCount = 0,
212+
MinDocCount = 0,
202213
Interval = interval
203214
};
204215
}
205216

206-
private static AggregationBase GetDateHistogramAggregation(string originalField, string field, string proximity, string boost, IQueryVisitorContext context)
217+
private static Aggregation GetDateHistogramAggregation(string originalField, string field, string proximity, string boost, IQueryVisitorContext context)
207218
{
208219
// NOTE: StartDate and EndDate are set in the Repositories QueryBuilderContext.
209220
var start = context.GetDate("StartDate");
210221
var end = context.GetDate("EndDate");
211222
bool isValidRange = start.HasValue && start.Value > DateTime.MinValue && end.HasValue && end.Value < DateTime.MaxValue && start.Value <= end.Value;
212-
var bounds = isValidRange ? new ExtendedBounds<DateMath> { Minimum = start.Value, Maximum = end.Value } : null;
223+
var bounds = isValidRange ? new ExtendedBoundsDate { Min = start.Value, Max = end.Value } : null;
213224

214225
var interval = GetInterval(proximity, start, end);
215226
string timezone = TryConvertTimeUnitToUtcOffset(boost);
216227
var agg = new DateHistogramAggregation(originalField)
217228
{
218229
Field = field,
219-
MinimumDocumentCount = 0,
230+
MinDocCount = 0,
220231
Format = "date_optional_time",
221232
TimeZone = timezone,
222233
Meta = !String.IsNullOrEmpty(boost) ? new Dictionary<string, object> { { "@timezone", boost } } : null,
@@ -247,55 +258,55 @@ private static string TryConvertTimeUnitToUtcOffset(string boost)
247258
return "+" + timezoneOffset.Value.ToString("hh\\:mm");
248259
}
249260

250-
private static Union<DateInterval, Time> GetInterval(string proximity, DateTime? start, DateTime? end)
261+
private static Union<CalendarInterval, Duration> GetInterval(string proximity, DateTime? start, DateTime? end)
251262
{
252263
if (String.IsNullOrEmpty(proximity))
253264
return GetInterval(start, end);
254265

255266
return proximity.Trim() switch
256267
{
257-
"s" or "1s" or "second" => DateInterval.Second,
258-
"m" or "1m" or "minute" => DateInterval.Minute,
259-
"h" or "1h" or "hour" => DateInterval.Hour,
260-
"d" or "1d" or "day" => DateInterval.Day,
261-
"w" or "1w" or "week" => DateInterval.Week,
262-
"M" or "1M" or "month" => DateInterval.Month,
263-
"q" or "1q" or "quarter" => DateInterval.Quarter,
264-
"y" or "1y" or "year" => DateInterval.Year,
265-
_ => new Union<DateInterval, Time>(proximity),
268+
"s" or "1s" or "second" => CalendarInterval.Second,
269+
"m" or "1m" or "minute" => CalendarInterval.Minute,
270+
"h" or "1h" or "hour" => CalendarInterval.Hour,
271+
"d" or "1d" or "day" => CalendarInterval.Day,
272+
"w" or "1w" or "week" => CalendarInterval.Week,
273+
"M" or "1M" or "month" => CalendarInterval.Month,
274+
"q" or "1q" or "quarter" => CalendarInterval.Quarter,
275+
"y" or "1y" or "year" => CalendarInterval.Year,
276+
_ => new Union<CalendarInterval, Duration>(proximity),
266277
};
267278
}
268279

269-
private static Union<DateInterval, Time> GetInterval(DateTime? utcStart, DateTime? utcEnd, int desiredDataPoints = 100)
280+
private static Union<CalendarInterval, Duration> GetInterval(DateTime? utcStart, DateTime? utcEnd, int desiredDataPoints = 100)
270281
{
271282
if (!utcStart.HasValue || !utcEnd.HasValue || utcStart.Value == DateTime.MinValue)
272-
return DateInterval.Day;
283+
return CalendarInterval.Day;
273284

274285
var totalTime = utcEnd.Value - utcStart.Value;
275286
var timePerBlock = TimeSpan.FromMinutes(totalTime.TotalMinutes / desiredDataPoints);
276287
if (timePerBlock.TotalDays > 1)
277288
{
278289
timePerBlock = timePerBlock.Round(TimeSpan.FromDays(1));
279-
return (Time)timePerBlock;
290+
return (Duration)timePerBlock;
280291
}
281292

282293
if (timePerBlock.TotalHours > 1)
283294
{
284295
timePerBlock = timePerBlock.Round(TimeSpan.FromHours(1));
285-
return (Time)timePerBlock;
296+
return (Duration)timePerBlock;
286297
}
287298

288299
if (timePerBlock.TotalMinutes > 1)
289300
{
290301
timePerBlock = timePerBlock.Round(TimeSpan.FromMinutes(1));
291-
return (Time)timePerBlock;
302+
return (Duration)timePerBlock;
292303
}
293304

294305
timePerBlock = timePerBlock.Round(TimeSpan.FromSeconds(15));
295306
if (timePerBlock.TotalSeconds < 1)
296307
timePerBlock = TimeSpan.FromSeconds(15);
297308

298-
return (Time)timePerBlock;
309+
return (Duration)timePerBlock;
299310
}
300311

301312
public static int? GetProximityAsInt32(this IFieldQueryWithProximityAndBoostNode node)

0 commit comments

Comments
 (0)