diff --git a/src/Foundatio.Parsers.ElasticQueries/ElasticMappingResolver.cs b/src/Foundatio.Parsers.ElasticQueries/ElasticMappingResolver.cs index 67584ba2..5bdf85d2 100644 --- a/src/Foundatio.Parsers.ElasticQueries/ElasticMappingResolver.cs +++ b/src/Foundatio.Parsers.ElasticQueries/ElasticMappingResolver.cs @@ -1,32 +1,35 @@ -using System; +using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Linq; +using Elastic.Clients.Elasticsearch; +using Elastic.Clients.Elasticsearch.IndexManagement; +using Elastic.Clients.Elasticsearch.Mapping; using Exceptionless.DateTimeExtensions; using Foundatio.Parsers.ElasticQueries.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Nest; namespace Foundatio.Parsers.ElasticQueries; public class ElasticMappingResolver { - private ITypeMapping _serverMapping; - private readonly ITypeMapping _codeMapping; + private TypeMapping _serverMapping; + private readonly TypeMapping _codeMapping; private readonly Inferrer _inferrer; private readonly ConcurrentDictionary _mappingCache = new(); private readonly ILogger _logger; public static ElasticMappingResolver NullInstance = new(() => null); - public ElasticMappingResolver(Func getMapping, Inferrer inferrer = null, ILogger logger = null) + public ElasticMappingResolver(Func getMapping, Inferrer inferrer = null, ILogger logger = null) { GetServerMappingFunc = getMapping; _inferrer = inferrer; _logger = logger ?? NullLogger.Instance; } - public ElasticMappingResolver(ITypeMapping codeMapping, Inferrer inferrer, Func getMapping, ILogger logger = null) + public ElasticMappingResolver(TypeMapping codeMapping, Inferrer inferrer, Func getMapping, ILogger logger = null) : this(getMapping, inferrer, logger) { _codeMapping = codeMapping; @@ -37,7 +40,7 @@ public ElasticMappingResolver(ITypeMapping codeMapping, Inferrer inferrer, Func< /// public void RefreshMapping() { - _logger.LogInformation("Mapping refresh triggered."); + _logger.LogInformation("Mapping refresh triggered"); _serverMapping = null; _lastMappingUpdate = null; } @@ -53,7 +56,7 @@ public FieldMapping GetMapping(string field, bool followAlias = false) if (_mappingCache.TryGetValue(field, out var mapping)) { - if (followAlias && mapping.Found && mapping.Property is IFieldAliasProperty fieldAlias) + if (followAlias && mapping.Found && mapping.Property is FieldAliasProperty fieldAlias) { _logger.LogTrace("Cached alias mapping: {Field}={FieldPath}:{FieldType}", field, mapping.FullPath, mapping.Property?.Type); return GetMapping(fieldAlias.Path.Name); @@ -67,11 +70,11 @@ public FieldMapping GetMapping(string field, bool followAlias = false) if (mapping.ServerMapTime >= _lastMappingUpdate && !GetServerMapping()) { - _logger.LogTrace("Cached mapping (not found): {field}=", field); + _logger.LogTrace("Cached mapping (not found): {Field}=", field); return mapping; } - _logger.LogTrace("Cached mapping (not found), got new server mapping."); + _logger.LogTrace("Cached mapping (not found), got new server mapping"); } string[] fieldParts = field.Split('.'); @@ -83,11 +86,11 @@ public FieldMapping GetMapping(string field, bool followAlias = false) { string fieldPart = fieldParts[depth]; IProperty fieldMapping = null; - if (currentProperties == null || !currentProperties.TryGetValue(fieldPart, out fieldMapping)) + if (currentProperties == null || !currentProperties.TryGetProperty(fieldPart, out fieldMapping)) { - // check to see if there is an name match + // check to see if there is a name match if (currentProperties != null) - fieldMapping = currentProperties.Values.FirstOrDefault(m => + fieldMapping = ((IDictionary)currentProperties).Values.FirstOrDefault(m => { string propertyName = _inferrer.PropertyName(m?.Name); return propertyName != null && propertyName.Equals(fieldPart, StringComparison.OrdinalIgnoreCase); @@ -136,19 +139,19 @@ public FieldMapping GetMapping(string field, bool followAlias = false) _mappingCache.AddOrUpdate(field, resolvedMapping, (_, _) => resolvedMapping); _logger.LogTrace("Resolved mapping: {Field}={FieldPath}:{FieldType}", field, resolvedMapping.FullPath, resolvedMapping.Property?.Type); - if (followAlias && resolvedMapping.Property is IFieldAliasProperty fieldAlias) + if (followAlias && resolvedMapping.Property is FieldAliasProperty fieldAlias) return GetMapping(fieldAlias.Path.Name); return resolvedMapping; } - if (fieldMapping is IObjectProperty objectProperty) + if (fieldMapping is ObjectProperty objectProperty) { currentProperties = objectProperty.Properties; } else { - if (fieldMapping is ITextProperty textProperty) + if (fieldMapping is TextProperty textProperty) currentProperties = textProperty.Fields; else break; @@ -229,13 +232,13 @@ public string GetNonAnalyzedFieldName(string field, string preferredSubField = n if (mapping?.Property == null || !IsPropertyAnalyzed(mapping.Property)) return field; - var multiFieldProperty = mapping.Property as ICoreProperty; + var multiFieldProperty = mapping.Property; if (multiFieldProperty?.Fields == null) return mapping.FullPath; var nonAnalyzedProperty = multiFieldProperty.Fields.OrderByDescending(kvp => kvp.Key.Name == preferredSubField).FirstOrDefault(kvp => { - if (kvp.Value is IKeywordProperty) + if (kvp.Value is KeywordProperty) return true; if (!IsPropertyAnalyzed(kvp.Value)) @@ -265,7 +268,7 @@ public bool IsPropertyAnalyzed(string field) public bool IsPropertyAnalyzed(IProperty property) { - if (property is ITextProperty textProperty) + if (property is TextProperty textProperty) return !textProperty.Index.HasValue || textProperty.Index.Value; return false; @@ -276,7 +279,7 @@ public bool IsNestedPropertyType(string field) if (String.IsNullOrEmpty(field)) return false; - return GetMappingProperty(field, true) is INestedProperty; + return GetMappingProperty(field, true) is NestedProperty; } public bool IsGeoPropertyType(string field) @@ -284,7 +287,7 @@ public bool IsGeoPropertyType(string field) if (String.IsNullOrEmpty(field)) return false; - return GetMappingProperty(field, true) is IGeoPointProperty; + return GetMappingProperty(field, true) is GeoPointProperty; } public bool IsNumericPropertyType(string field) @@ -292,7 +295,16 @@ public bool IsNumericPropertyType(string field) if (String.IsNullOrEmpty(field)) return false; - return GetMappingProperty(field, true) is INumberProperty; + var property = GetMappingProperty(field, true); + return property is ByteNumberProperty + or DoubleNumberProperty + or FloatNumberProperty + or HalfFloatNumberProperty + or IntegerNumberProperty + or LongNumberProperty + or ScaledFloatNumberProperty + or ShortNumberProperty + or UnsignedLongNumberProperty; } public bool IsBooleanPropertyType(string field) @@ -300,7 +312,7 @@ public bool IsBooleanPropertyType(string field) if (String.IsNullOrEmpty(field)) return false; - return GetMappingProperty(field, true) is IBooleanProperty; + return GetMappingProperty(field, true) is BooleanProperty; } public bool IsDatePropertyType(string field) @@ -308,7 +320,7 @@ public bool IsDatePropertyType(string field) if (String.IsNullOrEmpty(field)) return false; - return GetMappingProperty(field, true) is IDateProperty; + return GetMappingProperty(field, true) is DateProperty; } public FieldType GetFieldType(string field) @@ -323,44 +335,62 @@ public FieldType GetFieldType(string field) return property.Type switch { - "geo_point" => FieldType.GeoPoint, - "geo_shape" => FieldType.GeoShape, - "ip" => FieldType.Ip, - "binary" => FieldType.Binary, - "keyword" => FieldType.Keyword, - "string" or "text" => FieldType.Text, - "date" => FieldType.Date, - "boolean" => FieldType.Boolean, - "completion" => FieldType.Completion, - "nested" => FieldType.Nested, - "object" => FieldType.Object, - "murmur3" => FieldType.Murmur3Hash, - "token_count" => FieldType.TokenCount, - "percolator" => FieldType.Percolator, - "integer" => FieldType.Integer, - "long" => FieldType.Long, - "short" => FieldType.Short, - "byte" => FieldType.Byte, - "float" => FieldType.Float, - "half_float" => FieldType.HalfFloat, - "scaled_float" => FieldType.ScaledFloat, - "double" => FieldType.Double, - "integer_range" => FieldType.IntegerRange, - "float_range" => FieldType.FloatRange, - "long_range" => FieldType.LongRange, - "double_range" => FieldType.DoubleRange, - "date_range" => FieldType.DateRange, - "ip_range" => FieldType.IpRange, + "version"=> FieldType.Version, + "token_count"=> FieldType.TokenCount, + "text"=> FieldType.Text, + "sparse_vector"=> FieldType.SparseVector, + "short"=> FieldType.Short, + "shape"=> FieldType.Shape, + "semantic_text"=> FieldType.SemanticText, + "search_as_you_type"=> FieldType.SearchAsYouType, + "scaled_float"=> FieldType.ScaledFloat, + "rank_features"=> FieldType.RankFeatures, + "rank_feature"=> FieldType.RankFeature, + "percolator"=> FieldType.Percolator, + "object"=> FieldType.Object, + "none"=> FieldType.None, + "nested"=> FieldType.Nested, + "murmur3"=> FieldType.Murmur3, + "match_only_text"=> FieldType.MatchOnlyText, + "long_range"=> FieldType.LongRange, + "long"=> FieldType.Long, + "keyword"=> FieldType.Keyword, + "join"=> FieldType.Join, + "ip_range"=> FieldType.IpRange, + "ip"=> FieldType.Ip, + "integer_range"=> FieldType.IntegerRange, + "integer"=> FieldType.Integer, + "icu_collation_keyword"=> FieldType.IcuCollationKeyword, + "histogram"=> FieldType.Histogram, + "half_float"=> FieldType.HalfFloat, + "geo_shape"=> FieldType.GeoShape, + "geo_point"=> FieldType.GeoPoint, + "float_range"=> FieldType.FloatRange, + "float"=> FieldType.Float, + "flattened"=> FieldType.Flattened, + "double_range"=> FieldType.DoubleRange, + "double"=> FieldType.Double, + "dense_vector"=> FieldType.DenseVector, + "date_range"=> FieldType.DateRange, + "date_nanos"=> FieldType.DateNanos, + "date"=> FieldType.Date, + "constant_keyword"=> FieldType.ConstantKeyword, + "completion"=> FieldType.Completion, + "byte"=> FieldType.Byte, + "boolean"=> FieldType.Boolean, + "binary"=> FieldType.Binary, + "alias"=> FieldType.Alias, + "aggregate_metric_double"=> FieldType.AggregateMetricDouble, _ => FieldType.None, }; } - private IProperties MergeProperties(IProperties codeProperties, IProperties serverProperties) + private Properties MergeProperties(Properties codeProperties, Properties serverProperties) { if (codeProperties == null && serverProperties == null) return null; - IProperties mergedCodeProperties = null; + Properties mergedCodeProperties = null; // resolve code mapping property expressions using inferrer if (codeProperties != null) { @@ -369,7 +399,7 @@ private IProperties MergeProperties(IProperties codeProperties, IProperties serv foreach (var kvp in codeProperties) { var propertyName = kvp.Key; - if (_inferrer != null && (String.IsNullOrEmpty(kvp.Key.Name) || kvp.Value is IFieldAliasProperty)) + if (_inferrer != null && (String.IsNullOrEmpty(kvp.Key.Name) || kvp.Value is FieldAliasProperty)) propertyName = _inferrer.PropertyName(kvp.Key) ?? kvp.Key; mergedCodeProperties[propertyName] = kvp.Value; @@ -380,12 +410,12 @@ private IProperties MergeProperties(IProperties codeProperties, IProperties serv // resolve field alias foreach (var kvp in codeProperties) { - if (kvp.Value is not IFieldAliasProperty aliasProperty) + if (kvp.Value is not FieldAliasProperty aliasProperty) continue; mergedCodeProperties[kvp.Key] = new FieldAliasProperty { - LocalMetadata = aliasProperty.LocalMetadata, + Meta = aliasProperty.Meta, Path = _inferrer?.Field(aliasProperty.Path) ?? aliasProperty.Path, Name = aliasProperty.Name }; @@ -397,21 +427,21 @@ private IProperties MergeProperties(IProperties codeProperties, IProperties serv if (mergedCodeProperties == null || serverProperties == null) return mergedCodeProperties ?? serverProperties; - IProperties properties = new Properties(); + Properties properties = new Properties(); foreach (var serverProperty in serverProperties) { var merged = serverProperty.Value; - if (mergedCodeProperties.TryGetValue(serverProperty.Key, out var codeProperty)) + if (mergedCodeProperties.TryGetProperty(serverProperty.Key, out var codeProperty)) merged.LocalMetadata = codeProperty.LocalMetadata; switch (merged) { - case IObjectProperty objectProperty: - var codeObjectProperty = codeProperty as IObjectProperty; + case ObjectProperty objectProperty: + var codeObjectProperty = codeProperty as ObjectProperty; objectProperty.Properties = MergeProperties(codeObjectProperty?.Properties, objectProperty.Properties); break; - case ITextProperty textProperty: - var codeTextProperty = codeProperty as ITextProperty; + case TextProperty textProperty: + var codeTextProperty = codeProperty as TextProperty; textProperty.Fields = MergeProperties(codeTextProperty?.Fields, textProperty.Fields); break; } @@ -421,7 +451,7 @@ private IProperties MergeProperties(IProperties codeProperties, IProperties serv foreach (var codeProperty in mergedCodeProperties) { - if (properties.TryGetValue(codeProperty.Key, out _)) + if (properties.TryGetProperty(codeProperty.Key, out _)) continue; properties.Add(codeProperty.Key, codeProperty.Value); @@ -430,7 +460,7 @@ private IProperties MergeProperties(IProperties codeProperties, IProperties serv return properties; } - private Func GetServerMappingFunc { get; set; } + private Func GetServerMappingFunc { get; set; } private DateTime? _lastMappingUpdate = null; private bool GetServerMapping() { @@ -450,12 +480,12 @@ private bool GetServerMapping() } catch (Exception ex) { - _logger.LogError(ex, "Error getting server mapping: " + ex.Message); + _logger.LogError(ex, "Error getting server mapping: {Message}", ex.Message); return false; } } - public static ElasticMappingResolver Create(Func, ITypeMapping> mappingBuilder, IElasticClient client, ILogger logger = null) where T : class + public static ElasticMappingResolver Create(Func, TypeMapping> mappingBuilder, ElasticsearchClient client, ILogger logger = null) where T : class { logger ??= NullLogger.Instance; @@ -471,7 +501,7 @@ public static ElasticMappingResolver Create(Func, IT }, logger); } - public static ElasticMappingResolver Create(Func, ITypeMapping> mappingBuilder, IElasticClient client, string index, ILogger logger = null) where T : class + public static ElasticMappingResolver Create(Func, TypeMapping> mappingBuilder, ElasticsearchClient client, string index, ILogger logger = null) where T : class { logger ??= NullLogger.Instance; @@ -487,14 +517,13 @@ public static ElasticMappingResolver Create(Func, IT }, logger); } - public static ElasticMappingResolver Create(Func, ITypeMapping> mappingBuilder, Inferrer inferrer, Func getMapping, ILogger logger = null) where T : class + public static ElasticMappingResolver Create(Func, TypeMapping> mappingBuilder, Inferrer inferrer, Func getMapping, ILogger logger = null) where T : class { - var codeMapping = new TypeMappingDescriptor(); - codeMapping = mappingBuilder(codeMapping) as TypeMappingDescriptor; + var codeMapping = mappingBuilder(new TypeMappingDescriptor()); return new ElasticMappingResolver(codeMapping, inferrer, getMapping, logger: logger); } - public static ElasticMappingResolver Create(IElasticClient client, ILogger logger = null) + public static ElasticMappingResolver Create(ElasticsearchClient client, ILogger logger = null) { logger ??= NullLogger.Instance; @@ -510,7 +539,7 @@ public static ElasticMappingResolver Create(IElasticClient client, ILogger lo }, client.Infer, logger); } - public static ElasticMappingResolver Create(IElasticClient client, string index, ILogger logger = null) + public static ElasticMappingResolver Create(ElasticsearchClient client, string index, ILogger logger = null) { logger ??= NullLogger.Instance; @@ -526,7 +555,7 @@ public static ElasticMappingResolver Create(IElasticClient client, string index, }, client.Infer, logger); } - public static ElasticMappingResolver Create(Func getMapping, Inferrer inferrer, ILogger logger = null) + public static ElasticMappingResolver Create(Func getMapping, Inferrer inferrer, ILogger logger = null) { return new ElasticMappingResolver(getMapping, inferrer, logger: logger); } diff --git a/src/Foundatio.Parsers.ElasticQueries/ElasticQueryParser.cs b/src/Foundatio.Parsers.ElasticQueries/ElasticQueryParser.cs index a9abce24..4c410f4a 100644 --- a/src/Foundatio.Parsers.ElasticQueries/ElasticQueryParser.cs +++ b/src/Foundatio.Parsers.ElasticQueries/ElasticQueryParser.cs @@ -1,14 +1,16 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch; +using Elastic.Clients.Elasticsearch.Aggregations; +using Elastic.Clients.Elasticsearch.QueryDsl; using Foundatio.Parsers.ElasticQueries.Extensions; using Foundatio.Parsers.ElasticQueries.Visitors; using Foundatio.Parsers.LuceneQueries; using Foundatio.Parsers.LuceneQueries.Extensions; using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; -using Nest; using Pegasus.Common; namespace Foundatio.Parsers.ElasticQueries; @@ -158,7 +160,7 @@ public async Task ValidateQueryAsync(string query, QueryV return context.GetValidationResult(); } - public async Task BuildQueryAsync(string query, IElasticQueryVisitorContext context = null) + public async Task BuildQueryAsync(string query, IElasticQueryVisitorContext context = null) { context ??= new ElasticQueryVisitorContext(); context.QueryType = QueryTypes.Query; @@ -169,7 +171,7 @@ public async Task BuildQueryAsync(string query, IElasticQueryVis return await BuildQueryAsync(result, context).ConfigureAwait(false); } - public async Task BuildQueryAsync(IQueryNode query, IElasticQueryVisitorContext context = null) + public async Task BuildQueryAsync(IQueryNode query, IElasticQueryVisitorContext context = null) { context ??= new ElasticQueryVisitorContext(); var q = await query.GetQueryAsync() ?? new MatchAllQuery(); @@ -195,7 +197,7 @@ public async Task ValidateAggregationsAsync(string query, return context.GetValidationResult(); } - public async Task BuildAggregationsAsync(string aggregations, IElasticQueryVisitorContext context = null) + public async Task BuildAggregationsAsync(string aggregations, IElasticQueryVisitorContext context = null) { context ??= new ElasticQueryVisitorContext(); context.QueryType = QueryTypes.Aggregation; @@ -207,7 +209,7 @@ public async Task BuildAggregationsAsync(string aggregatio } #pragma warning disable IDE0060 // Remove unused parameter - public async Task BuildAggregationsAsync(IQueryNode aggregations, IElasticQueryVisitorContext context = null) + public async Task BuildAggregationsAsync(IQueryNode aggregations, IElasticQueryVisitorContext context = null) { if (aggregations == null) return null; @@ -227,7 +229,7 @@ public async Task ValidateSortAsync(string query, QueryVa return context.GetValidationResult(); } - public async Task> BuildSortAsync(string sort, IElasticQueryVisitorContext context = null) + public async Task> BuildSortAsync(string sort, IElasticQueryVisitorContext context = null) { context ??= new ElasticQueryVisitorContext(); context.QueryType = QueryTypes.Sort; @@ -238,7 +240,7 @@ public async Task> BuildSortAsync(string sort, IElasticQ return await BuildSortAsync(result, context).ConfigureAwait(false); } - public Task> BuildSortAsync(IQueryNode sort, IElasticQueryVisitorContext context = null) + public Task> BuildSortAsync(IQueryNode sort, IElasticQueryVisitorContext context = null) { context ??= new ElasticQueryVisitorContext(); return GetSortFieldsVisitor.RunAsync(sort, context); diff --git a/src/Foundatio.Parsers.ElasticQueries/ElasticQueryParserConfiguration.cs b/src/Foundatio.Parsers.ElasticQueries/ElasticQueryParserConfiguration.cs index 8b6de9cd..f4c69b2e 100644 --- a/src/Foundatio.Parsers.ElasticQueries/ElasticQueryParserConfiguration.cs +++ b/src/Foundatio.Parsers.ElasticQueries/ElasticQueryParserConfiguration.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch; +using Elastic.Clients.Elasticsearch.Mapping; using Foundatio.Parsers.ElasticQueries.Visitors; using Foundatio.Parsers.LuceneQueries; using Foundatio.Parsers.LuceneQueries.Visitors; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Nest; namespace Foundatio.Parsers.ElasticQueries; @@ -285,35 +286,35 @@ public ElasticQueryParserConfiguration AddAggregationVisitorAfter(IChainableQ #endregion - public ElasticQueryParserConfiguration UseMappings(Func, TypeMappingDescriptor> mappingBuilder, IElasticClient client, string index) where T : class + public ElasticQueryParserConfiguration UseMappings(Func, TypeMappingDescriptor> mappingBuilder, ElasticsearchClient client, string index) where T : class { MappingResolver = ElasticMappingResolver.Create(mappingBuilder, client, index, logger: _logger); return this; } - public ElasticQueryParserConfiguration UseMappings(Func, TypeMappingDescriptor> mappingBuilder, Inferrer inferrer, Func getMapping) where T : class + public ElasticQueryParserConfiguration UseMappings(Func, TypeMappingDescriptor> mappingBuilder, Inferrer inferrer, Func getMapping) where T : class { MappingResolver = ElasticMappingResolver.Create(mappingBuilder, inferrer, getMapping, logger: _logger); return this; } - public ElasticQueryParserConfiguration UseMappings(IElasticClient client) + public ElasticQueryParserConfiguration UseMappings(ElasticsearchClient client) { MappingResolver = ElasticMappingResolver.Create(client, logger: _logger); return this; } - public ElasticQueryParserConfiguration UseMappings(IElasticClient client, string index) + public ElasticQueryParserConfiguration UseMappings(ElasticsearchClient client, string index) { MappingResolver = ElasticMappingResolver.Create(client, index, logger: _logger); return this; } - public ElasticQueryParserConfiguration UseMappings(Func getMapping, Inferrer inferrer = null) + public ElasticQueryParserConfiguration UseMappings(Func getMapping, Inferrer inferrer = null) { MappingResolver = ElasticMappingResolver.Create(getMapping, inferrer, logger: _logger); diff --git a/src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultAggregationNodeExtensions.cs b/src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultAggregationNodeExtensions.cs index dad8290b..6450cb66 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultAggregationNodeExtensions.cs +++ b/src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultAggregationNodeExtensions.cs @@ -1,12 +1,13 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch; +using Elastic.Clients.Elasticsearch.Aggregations; using Exceptionless.DateTimeExtensions; using Foundatio.Parsers.ElasticQueries.Visitors; using Foundatio.Parsers.LuceneQueries.Extensions; using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; -using Nest; namespace Foundatio.Parsers.ElasticQueries.Extensions; @@ -15,7 +16,7 @@ public static class DefaultAggregationNodeExtensions // NOTE: We may want to read this dynamically from server settings. public const int MAX_BUCKET_SIZE = 10000; - public static Task GetDefaultAggregationAsync(this IQueryNode node, IQueryVisitorContext context) + public static Task GetDefaultAggregationAsync(this IQueryNode node, IQueryVisitorContext context) { if (node is GroupNode groupNode) return groupNode.GetDefaultAggregationAsync(context); @@ -26,7 +27,7 @@ public static Task GetDefaultAggregationAsync(this IQueryNode n return null; } - public static async Task GetDefaultAggregationAsync(this GroupNode node, IQueryVisitorContext context) + public static async Task GetDefaultAggregationAsync(this GroupNode node, IQueryVisitorContext context) { if (context is not IElasticQueryVisitorContext elasticContext) throw new ArgumentException("Context must be of type IElasticQueryVisitorContext", nameof(context)); @@ -47,29 +48,34 @@ public static async Task GetDefaultAggregationAsync(this GroupN return GetHistogramAggregation("histogram_" + originalField, field, node.UnescapedProximity, node.UnescapedBoost, context); case AggregationType.GeoHashGrid: - var precision = GeoHashPrecision.Precision1; - if (!String.IsNullOrEmpty(node.UnescapedProximity)) - Enum.TryParse(node.UnescapedProximity, out precision); + var precision = new GeohashPrecision(1); + if (!String.IsNullOrEmpty(node.UnescapedProximity) && Double.TryParse(node.UnescapedProximity, out double parsedPrecision)) + { + if (parsedPrecision is < 1 or > 12) + throw new ArgumentOutOfRangeException(nameof(node.UnescapedProximity), "Precision must be between 1 and 12"); + + precision = new GeohashPrecision(parsedPrecision); + } - return new GeoHashGridAggregation("geogrid_" + originalField) + return new Aggregation("geogrid_" + originalField, new GeohashGridAggregation { Field = field, Precision = precision, Aggregations = new AverageAggregation("avg_lat", null) { - Script = new InlineScript($"doc['{node.Field}'].lat") + Script = new Script { Source = $"doc['{node.Field}'].lat" } } && new AverageAggregation("avg_lon", null) { - Script = new InlineScript($"doc['{node.Field}'].lon") + Script = new Script { Source = $"doc['{node.Field}'].lon" } } - }; + }); case AggregationType.Terms: var agg = new TermsAggregation("terms_" + originalField) { Field = field, Size = node.GetProximityAsInt32(), - MinimumDocumentCount = node.GetBoostAsInt32(), + MinDocCount = node.GetBoostAsInt32(), Meta = new Dictionary { { "@field_type", property?.Type } } }; @@ -85,7 +91,7 @@ public static async Task GetDefaultAggregationAsync(this GroupN return null; } - public static async Task GetDefaultAggregationAsync(this TermNode node, IQueryVisitorContext context) + public static async Task GetDefaultAggregationAsync(this TermNode node, IQueryVisitorContext context) { if (context is not IElasticQueryVisitorContext elasticContext) throw new ArgumentException("Context must be of type IElasticQueryVisitorContext", nameof(context)); @@ -134,20 +140,25 @@ public static async Task GetDefaultAggregationAsync(this TermNo return GetPercentilesAggregation("percentiles_" + originalField, aggField, node.UnescapedProximity, node.UnescapedBoost, context); case AggregationType.GeoHashGrid: - var precision = GeoHashPrecision.Precision1; - if (!String.IsNullOrEmpty(node.UnescapedProximity)) - Enum.TryParse(node.UnescapedProximity, out precision); + var precision = new GeohashPrecision(1); + if (!String.IsNullOrEmpty(node.UnescapedProximity) && Double.TryParse(node.UnescapedProximity, out double parsedPrecision)) + { + if (parsedPrecision is < 1 or > 12) + throw new ArgumentOutOfRangeException(nameof(node.UnescapedProximity), "Precision must be between 1 and 12"); + + precision = new GeohashPrecision(parsedPrecision); + } - return new GeoHashGridAggregation("geogrid_" + originalField) + return new GeohashGridAggregation("geogrid_" + originalField) { Field = aggField, Precision = precision, Aggregations = new AverageAggregation("avg_lat", null) { - Script = new InlineScript($"doc['{node.Field}'].lat") + Script = new Script { Source = $"doc['{node.Field}'].lat" } } && new AverageAggregation("avg_lon", null) { - Script = new InlineScript($"doc['{node.Field}'].lon") + Script = new Script { Source = $"doc['{node.Field}'].lon" } } }; @@ -156,7 +167,7 @@ public static async Task GetDefaultAggregationAsync(this TermNo { Field = aggField, Size = node.GetProximityAsInt32(), - MinimumDocumentCount = node.GetBoostAsInt32(), + MinDocCount = node.GetBoostAsInt32(), Meta = new Dictionary { { "@field_type", property?.Type } } }; @@ -169,7 +180,7 @@ public static async Task GetDefaultAggregationAsync(this TermNo return null; } - private static AggregationBase GetPercentilesAggregation(string originalField, string field, string proximity, string boost, IQueryVisitorContext context) + private static Aggregation GetPercentilesAggregation(string originalField, string field, string proximity, string boost, IQueryVisitorContext context) { List percents = null; if (!String.IsNullOrWhiteSpace(proximity)) @@ -189,7 +200,7 @@ private static AggregationBase GetPercentilesAggregation(string originalField, s }; } - private static AggregationBase GetHistogramAggregation(string originalField, string field, string proximity, string boost, IQueryVisitorContext context) + private static Aggregation GetHistogramAggregation(string originalField, string field, string proximity, string boost, IQueryVisitorContext context) { double interval = 50; if (Double.TryParse(proximity, out double prox)) @@ -198,25 +209,25 @@ private static AggregationBase GetHistogramAggregation(string originalField, str return new HistogramAggregation(originalField) { Field = field, - MinimumDocumentCount = 0, + MinDocCount = 0, Interval = interval }; } - private static AggregationBase GetDateHistogramAggregation(string originalField, string field, string proximity, string boost, IQueryVisitorContext context) + private static Aggregation GetDateHistogramAggregation(string originalField, string field, string proximity, string boost, IQueryVisitorContext context) { // NOTE: StartDate and EndDate are set in the Repositories QueryBuilderContext. var start = context.GetDate("StartDate"); var end = context.GetDate("EndDate"); bool isValidRange = start.HasValue && start.Value > DateTime.MinValue && end.HasValue && end.Value < DateTime.MaxValue && start.Value <= end.Value; - var bounds = isValidRange ? new ExtendedBounds { Minimum = start.Value, Maximum = end.Value } : null; + var bounds = isValidRange ? new ExtendedBoundsDate { Min = start.Value, Max = end.Value } : null; var interval = GetInterval(proximity, start, end); string timezone = TryConvertTimeUnitToUtcOffset(boost); var agg = new DateHistogramAggregation(originalField) { Field = field, - MinimumDocumentCount = 0, + MinDocCount = 0, Format = "date_optional_time", TimeZone = timezone, Meta = !String.IsNullOrEmpty(boost) ? new Dictionary { { "@timezone", boost } } : null, @@ -247,55 +258,55 @@ private static string TryConvertTimeUnitToUtcOffset(string boost) return "+" + timezoneOffset.Value.ToString("hh\\:mm"); } - private static Union GetInterval(string proximity, DateTime? start, DateTime? end) + private static Union GetInterval(string proximity, DateTime? start, DateTime? end) { if (String.IsNullOrEmpty(proximity)) return GetInterval(start, end); return proximity.Trim() switch { - "s" or "1s" or "second" => DateInterval.Second, - "m" or "1m" or "minute" => DateInterval.Minute, - "h" or "1h" or "hour" => DateInterval.Hour, - "d" or "1d" or "day" => DateInterval.Day, - "w" or "1w" or "week" => DateInterval.Week, - "M" or "1M" or "month" => DateInterval.Month, - "q" or "1q" or "quarter" => DateInterval.Quarter, - "y" or "1y" or "year" => DateInterval.Year, - _ => new Union(proximity), + "s" or "1s" or "second" => CalendarInterval.Second, + "m" or "1m" or "minute" => CalendarInterval.Minute, + "h" or "1h" or "hour" => CalendarInterval.Hour, + "d" or "1d" or "day" => CalendarInterval.Day, + "w" or "1w" or "week" => CalendarInterval.Week, + "M" or "1M" or "month" => CalendarInterval.Month, + "q" or "1q" or "quarter" => CalendarInterval.Quarter, + "y" or "1y" or "year" => CalendarInterval.Year, + _ => new Union(proximity), }; } - private static Union GetInterval(DateTime? utcStart, DateTime? utcEnd, int desiredDataPoints = 100) + private static Union GetInterval(DateTime? utcStart, DateTime? utcEnd, int desiredDataPoints = 100) { if (!utcStart.HasValue || !utcEnd.HasValue || utcStart.Value == DateTime.MinValue) - return DateInterval.Day; + return CalendarInterval.Day; var totalTime = utcEnd.Value - utcStart.Value; var timePerBlock = TimeSpan.FromMinutes(totalTime.TotalMinutes / desiredDataPoints); if (timePerBlock.TotalDays > 1) { timePerBlock = timePerBlock.Round(TimeSpan.FromDays(1)); - return (Time)timePerBlock; + return (Duration)timePerBlock; } if (timePerBlock.TotalHours > 1) { timePerBlock = timePerBlock.Round(TimeSpan.FromHours(1)); - return (Time)timePerBlock; + return (Duration)timePerBlock; } if (timePerBlock.TotalMinutes > 1) { timePerBlock = timePerBlock.Round(TimeSpan.FromMinutes(1)); - return (Time)timePerBlock; + return (Duration)timePerBlock; } timePerBlock = timePerBlock.Round(TimeSpan.FromSeconds(15)); if (timePerBlock.TotalSeconds < 1) timePerBlock = TimeSpan.FromSeconds(15); - return (Time)timePerBlock; + return (Duration)timePerBlock; } public static int? GetProximityAsInt32(this IFieldQueryWithProximityAndBoostNode node) diff --git a/src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultQueryNodeExtensions.cs b/src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultQueryNodeExtensions.cs index 4c2aba27..ab76b6f0 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultQueryNodeExtensions.cs +++ b/src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultQueryNodeExtensions.cs @@ -1,16 +1,16 @@ -using System; +using System; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch.QueryDsl; using Foundatio.Parsers.ElasticQueries.Visitors; using Foundatio.Parsers.LuceneQueries.Extensions; using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; -using Nest; namespace Foundatio.Parsers.ElasticQueries.Extensions; public static class DefaultQueryNodeExtensions { - public static async Task GetDefaultQueryAsync(this IQueryNode node, IQueryVisitorContext context) + public static async Task GetDefaultQueryAsync(this IQueryNode node, IQueryVisitorContext context) { if (node is TermNode termNode) return termNode.GetDefaultQuery(context); @@ -27,12 +27,12 @@ public static async Task GetDefaultQueryAsync(this IQueryNode node, I return null; } - public static QueryBase GetDefaultQuery(this TermNode node, IQueryVisitorContext context) + public static Query GetDefaultQuery(this TermNode node, IQueryVisitorContext context) { if (context is not IElasticQueryVisitorContext elasticContext) throw new ArgumentException("Context must be of type IElasticQueryVisitorContext", nameof(context)); - QueryBase query; + Query query; string field = node.UnescapedField; string[] defaultFields = node.GetDefaultFields(elasticContext.DefaultFields); if (field == null && defaultFields != null && defaultFields.Length == 1) @@ -58,17 +58,15 @@ public static QueryBase GetDefaultQuery(this TermNode node, IQueryVisitorContext { if (node.IsQuotedTerm) { - query = new MatchPhraseQuery + query = new MatchPhraseQuery(fields[0]) { - Field = fields[0], Query = node.UnescapedTerm }; } else { - query = new MatchQuery + query = new MatchQuery(fields[0]) { - Field = fields[0], Query = node.UnescapedTerm }; } @@ -78,10 +76,9 @@ public static QueryBase GetDefaultQuery(this TermNode node, IQueryVisitorContext query = new MultiMatchQuery { Fields = fields, - Query = node.UnescapedTerm + Query = node.UnescapedTerm, + Type = node.IsQuotedTerm ? TextQueryType.Phrase : null }; - if (node.IsQuotedTerm) - ((MultiMatchQuery)query).Type = TextQueryType.Phrase; } } } @@ -89,17 +86,15 @@ public static QueryBase GetDefaultQuery(this TermNode node, IQueryVisitorContext { if (!node.IsQuotedTerm && node.UnescapedTerm.EndsWith("*")) { - query = new PrefixQuery + query = new PrefixQuery(field) { - Field = field, Value = node.UnescapedTerm.TrimEnd('*') }; } else { - query = new TermQuery + query = new TermQuery(field) { - Field = field, Value = node.UnescapedTerm }; } @@ -108,7 +103,7 @@ public static QueryBase GetDefaultQuery(this TermNode node, IQueryVisitorContext return query; } - public static async Task GetDefaultQueryAsync(this TermRangeNode node, IQueryVisitorContext context) + public static async Task GetDefaultQueryAsync(this TermRangeNode node, IQueryVisitorContext context) { if (context is not IElasticQueryVisitorContext elasticContext) throw new ArgumentException("Context must be of type IElasticQueryVisitorContext", nameof(context)); @@ -116,54 +111,54 @@ public static async Task GetDefaultQueryAsync(this TermRangeNode node string field = node.UnescapedField; if (elasticContext.MappingResolver.IsDatePropertyType(field)) { - var range = new DateRangeQuery { Field = field, TimeZone = node.Boost ?? node.GetTimeZone(await elasticContext.GetTimeZoneAsync()) }; + var range = new DateRangeQuery(field) { TimeZone = node.Boost ?? node.GetTimeZone(await elasticContext.GetTimeZoneAsync()) }; if (!String.IsNullOrWhiteSpace(node.UnescapedMin) && node.UnescapedMin != "*") { if (node.MinInclusive.HasValue && !node.MinInclusive.Value) - range.GreaterThan = node.UnescapedMin; + range.Gt = node.UnescapedMin; else - range.GreaterThanOrEqualTo = node.UnescapedMin; + range.Gte = node.UnescapedMin; } if (!String.IsNullOrWhiteSpace(node.UnescapedMax) && node.UnescapedMax != "*") { if (node.MaxInclusive.HasValue && !node.MaxInclusive.Value) - range.LessThan = node.UnescapedMax; + range.Lt = node.UnescapedMax; else - range.LessThanOrEqualTo = node.UnescapedMax; + range.Lte = node.UnescapedMax; } return range; } else { - var range = new TermRangeQuery { Field = field }; + var range = new TermRangeQuery(field); if (!String.IsNullOrWhiteSpace(node.UnescapedMin) && node.UnescapedMin != "*") { if (node.MinInclusive.HasValue && !node.MinInclusive.Value) - range.GreaterThan = node.UnescapedMin; + range.Gt = node.UnescapedMin; else - range.GreaterThanOrEqualTo = node.UnescapedMin; + range.Gte = node.UnescapedMin; } if (!String.IsNullOrWhiteSpace(node.UnescapedMax) && node.UnescapedMax != "*") { if (node.MaxInclusive.HasValue && !node.MaxInclusive.Value) - range.LessThan = node.UnescapedMax; + range.Lt = node.UnescapedMax; else - range.LessThanOrEqualTo = node.UnescapedMax; + range.Lte = node.UnescapedMax; } return range; } } - public static QueryBase GetDefaultQuery(this ExistsNode node, IQueryVisitorContext context) + public static Query GetDefaultQuery(this ExistsNode node, IQueryVisitorContext context) { return new ExistsQuery { Field = node.UnescapedField }; } - public static QueryBase GetDefaultQuery(this MissingNode node, IQueryVisitorContext context) + public static Query GetDefaultQuery(this MissingNode node, IQueryVisitorContext context) { return new BoolQuery { diff --git a/src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultSortNodeExtensions.cs b/src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultSortNodeExtensions.cs index 3775c69e..cdcd4147 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultSortNodeExtensions.cs +++ b/src/Foundatio.Parsers.ElasticQueries/Extensions/DefaultSortNodeExtensions.cs @@ -1,15 +1,16 @@ using System; +using Elastic.Clients.Elasticsearch; +using Elastic.Clients.Elasticsearch.Mapping; using Foundatio.Parsers.ElasticQueries.Visitors; using Foundatio.Parsers.LuceneQueries.Extensions; using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; -using Nest; namespace Foundatio.Parsers.ElasticQueries.Extensions; public static class DefaultSortNodeExtensions { - public static IFieldSort GetDefaultSort(this TermNode node, IQueryVisitorContext context) + public static SortOptions GetDefaultSort(this TermNode node, IQueryVisitorContext context) { if (context is not IElasticQueryVisitorContext elasticContext) throw new ArgumentException("Context must be of type IElasticQueryVisitorContext", nameof(context)); @@ -17,13 +18,10 @@ public static IFieldSort GetDefaultSort(this TermNode node, IQueryVisitorContext string field = elasticContext.MappingResolver.GetSortFieldName(node.UnescapedField); var fieldType = elasticContext.MappingResolver.GetFieldType(field); - var sort = new FieldSort + return SortOptions.Field(field, new FieldSort { - Field = field, UnmappedType = fieldType == FieldType.None ? FieldType.Keyword : fieldType, - Order = node.IsNodeOrGroupNegated() ? SortOrder.Descending : SortOrder.Ascending - }; - - return sort; + Order = node.IsNodeOrGroupNegated() ? SortOrder.Desc : SortOrder.Asc + }); } } diff --git a/src/Foundatio.Parsers.ElasticQueries/Extensions/ElasticExtensions.cs b/src/Foundatio.Parsers.ElasticQueries/Extensions/ElasticExtensions.cs index e12e54cf..aa442120 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Extensions/ElasticExtensions.cs +++ b/src/Foundatio.Parsers.ElasticQueries/Extensions/ElasticExtensions.cs @@ -6,9 +6,10 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Elasticsearch.Net; +using Elastic.Clients.Elasticsearch; +using Elastic.Clients.Elasticsearch.Aggregations; +using Elastic.Transport.Products.Elasticsearch; using Microsoft.Extensions.Logging; -using Nest; namespace Foundatio.Parsers.ElasticQueries.Extensions; @@ -37,7 +38,7 @@ public static TermsExclude AddValue(this TermsExclude exclude, string value) } // TODO: Handle IFailureReason/BulkIndexByScrollFailure and other bulk response types. - public static string GetErrorMessage(this IElasticsearchResponse elasticResponse, string message = null, bool normalize = false, bool includeResponse = false, bool includeDebugInformation = false) + public static string GetErrorMessage(this ElasticsearchResponse elasticResponse, string message = null, bool normalize = false, bool includeResponse = false, bool includeDebugInformation = false) { if (elasticResponse == null) return String.Empty; @@ -47,31 +48,30 @@ public static string GetErrorMessage(this IElasticsearchResponse elasticResponse if (!String.IsNullOrEmpty(message)) sb.AppendLine(message); - var response = elasticResponse as IResponse; - if (includeDebugInformation && response?.DebugInformation != null) - sb.AppendLine(response.DebugInformation); + if (includeDebugInformation && elasticResponse?.DebugInformation != null) + sb.AppendLine(elasticResponse.DebugInformation); - if (response?.OriginalException != null) - sb.AppendLine($"Original: [{response.OriginalException.GetType().Name}] {response.OriginalException.Message}"); + if (elasticResponse.TryGetOriginalException(out var exception) && exception is not null) + sb.AppendLine($"Original: [{exception.GetType().Name}] {exception.Message}"); - if (response?.ServerError?.Error != null) - sb.AppendLine($"Server Error (Index={response.ServerError.Error?.Index}): {response.ServerError.Error.Reason}"); + if (elasticResponse.ElasticsearchServerError?.Error != null) + sb.AppendLine($"Server Error (Index={elasticResponse.ElasticsearchServerError.Error?.Index}): {elasticResponse.ElasticsearchServerError.Error.Reason}"); if (elasticResponse is BulkResponse bulkResponse) sb.AppendLine($"Bulk: {String.Join("\r\n", bulkResponse.ItemsWithErrors.Select(i => i.Error))}"); - if (elasticResponse.ApiCall != null) - sb.AppendLine($"[{elasticResponse.ApiCall.HttpStatusCode}] {elasticResponse.ApiCall.HttpMethod} {elasticResponse.ApiCall.Uri?.PathAndQuery}"); + var apiCall = elasticResponse.ApiCallDetails; + if (apiCall is not null) + sb.AppendLine($"[{apiCall.HttpStatusCode}] {apiCall.HttpMethod} {apiCall.Uri?.PathAndQuery}"); - if (elasticResponse.ApiCall?.RequestBodyInBytes != null) + if (apiCall?.RequestBodyInBytes is not null) { - string body = Encoding.UTF8.GetString(elasticResponse.ApiCall?.RequestBodyInBytes); + string body = Encoding.UTF8.GetString(apiCall.RequestBodyInBytes); if (normalize) body = JsonUtility.Normalize(body); sb.AppendLine(body); } - var apiCall = response.ApiCall; if (includeResponse && apiCall.ResponseBodyInBytes != null && apiCall.ResponseBodyInBytes.Length > 0 && apiCall.ResponseBodyInBytes.Length < 20000) { string body = Encoding.UTF8.GetString(apiCall?.ResponseBodyInBytes); @@ -88,52 +88,52 @@ public static string GetErrorMessage(this IElasticsearchResponse elasticResponse return sb.ToString(); } - public static string GetRequest(this IElasticsearchResponse elasticResponse, bool normalize = false, bool includeResponse = false, bool includeDebugInformation = false) + public static string GetRequest(this ElasticsearchResponse elasticResponse, bool normalize = false, bool includeResponse = false, bool includeDebugInformation = false) { return GetErrorMessage(elasticResponse, null, normalize, includeResponse, includeDebugInformation); } - public static async Task WaitForReadyAsync(this IElasticClient client, CancellationToken cancellationToken, ILogger logger = null) + public static async Task WaitForReadyAsync(this ElasticsearchClient client, CancellationToken cancellationToken, ILogger logger = null) { - var nodes = client.ConnectionSettings.ConnectionPool.Nodes.Select(n => n.Uri.ToString()); + var nodes = client.ElasticsearchClientSettings.NodePool.Nodes.Select(n => n.Uri.ToString()); var startTime = DateTime.UtcNow; while (!cancellationToken.IsCancellationRequested) { - var pingResponse = await client.PingAsync(ct: cancellationToken); - if (pingResponse.IsValid) + var pingResponse = await client.PingAsync(cancellationToken); + if (pingResponse.IsValidResponse) return true; - if (logger != null && logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Information)) + if (logger != null && logger.IsEnabled(LogLevel.Information)) logger?.LogInformation("Waiting for Elasticsearch to be ready {Server} after {Duration:g}...", nodes, DateTime.UtcNow.Subtract(startTime)); await Task.Delay(1000, cancellationToken); } - if (logger != null && logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Error)) + if (logger != null && logger.IsEnabled(LogLevel.Error)) logger?.LogError("Unable to connect to Elasticsearch {Server} after attempting for {Duration:g}", nodes, DateTime.UtcNow.Subtract(startTime)); return false; } - public static bool WaitForReady(this IElasticClient client, CancellationToken cancellationToken, ILogger logger = null) + public static bool WaitForReady(this ElasticsearchClient client, CancellationToken cancellationToken, ILogger logger = null) { - var nodes = client.ConnectionSettings.ConnectionPool.Nodes.Select(n => n.Uri.ToString()); + var nodes = client.ElasticsearchClientSettings.NodePool.Nodes.Select(n => n.Uri.ToString()); var startTime = DateTime.UtcNow; while (!cancellationToken.IsCancellationRequested) { var pingResponse = client.Ping(); - if (pingResponse.IsValid) + if (pingResponse.IsValidResponse) return true; - if (logger != null && logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Information)) + if (logger != null && logger.IsEnabled(LogLevel.Information)) logger?.LogInformation("Waiting for Elasticsearch to be ready {Server} after {Duration:g}...", nodes, DateTime.UtcNow.Subtract(startTime)); Thread.Sleep(1000); } - if (logger != null && logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Error)) + if (logger != null && logger.IsEnabled(LogLevel.Error)) logger?.LogError("Unable to connect to Elasticsearch {Server} after attempting for {Duration:g}", nodes, DateTime.UtcNow.Subtract(startTime)); return false; @@ -213,7 +213,6 @@ private static void Write(JsonElement element, Utf8JsonWriter writer) default: throw new NotImplementedException($"Kind: {element.ValueKind}"); - } } } diff --git a/src/Foundatio.Parsers.ElasticQueries/Extensions/ElasticMappingExtensions.cs b/src/Foundatio.Parsers.ElasticQueries/Extensions/ElasticMappingExtensions.cs index d40836c4..c01507fb 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Extensions/ElasticMappingExtensions.cs +++ b/src/Foundatio.Parsers.ElasticQueries/Extensions/ElasticMappingExtensions.cs @@ -1,4 +1,7 @@ -namespace Nest; +using Elastic.Clients.Elasticsearch.IndexManagement; +using Elastic.Clients.Elasticsearch.Mapping; + +namespace Foundatio.Parsers.ElasticQueries.Extensions; public static class ElasticMapping { @@ -15,7 +18,7 @@ public static TextPropertyDescriptor AddKeywordField(this TextPropertyDesc /// public static TextPropertyDescriptor AddKeywordField(this TextPropertyDescriptor descriptor, string normalizer) where T : class { - return descriptor.Fields(f => f.Keyword(s => s.Name(KeywordFieldName).Normalizer(normalizer).IgnoreAbove(256))); + return descriptor.Fields(f => f.Keyword(KeywordFieldName, s => s.Normalizer(normalizer).IgnoreAbove(256))); } /// @@ -31,14 +34,14 @@ public static TextPropertyDescriptor AddKeywordField(this TextPropertyDesc /// public static TextPropertyDescriptor AddSortField(this TextPropertyDescriptor descriptor, string normalizer = "sort") where T : class { - return descriptor.Fields(f => f.Keyword(s => s.Name(SortFieldName).Normalizer(normalizer).IgnoreAbove(256))); + return descriptor.Fields(f => f.Keyword(SortFieldName, s => s.Normalizer(normalizer).IgnoreAbove(256))); } public static TextPropertyDescriptor AddKeywordAndSortFields(this TextPropertyDescriptor descriptor, string sortNormalizer = "sort", string keywordNormalizer = null) where T : class { return descriptor.Fields(f => f - .Keyword(s => s.Name(KeywordFieldName).Normalizer(keywordNormalizer).IgnoreAbove(256)) - .Keyword(s => s.Name(SortFieldName).Normalizer(sortNormalizer).IgnoreAbove(256))); + .Keyword(KeywordFieldName, s => s.Normalizer(keywordNormalizer).IgnoreAbove(256)) + .Keyword(SortFieldName, s => s.Normalizer(sortNormalizer).IgnoreAbove(256))); } public static TextPropertyDescriptor AddKeywordAndSortFields(this TextPropertyDescriptor descriptor, bool keywordLowercase) where T : class @@ -46,9 +49,9 @@ public static TextPropertyDescriptor AddKeywordAndSortFields(this TextProp return descriptor.AddKeywordAndSortFields(keywordNormalizer: keywordLowercase ? "lowercase" : null); } - public static AnalysisDescriptor AddSortNormalizer(this AnalysisDescriptor descriptor) + public static IndexSettingsAnalysisDescriptor AddSortNormalizer(this IndexSettingsAnalysisDescriptor descriptor) { - return descriptor.Normalizers(d => d.Custom("sort", n => n.Filters("lowercase", "asciifolding"))); + return descriptor.Normalizers(d => d.Custom("sort", n => n.Filter(["lowercase", "asciifolding"]))); } public static string KeywordFieldName = "keyword"; diff --git a/src/Foundatio.Parsers.ElasticQueries/Extensions/QueryNodeExtensions.cs b/src/Foundatio.Parsers.ElasticQueries/Extensions/QueryNodeExtensions.cs index 274108ae..1fe70e5b 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Extensions/QueryNodeExtensions.cs +++ b/src/Foundatio.Parsers.ElasticQueries/Extensions/QueryNodeExtensions.cs @@ -1,27 +1,30 @@ -using System; +using System; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch; +using Elastic.Clients.Elasticsearch.Aggregations; +using Elastic.Clients.Elasticsearch.Core.Search; +using Elastic.Clients.Elasticsearch.QueryDsl; using Foundatio.Parsers.LuceneQueries.Nodes; -using Nest; namespace Foundatio.Parsers.ElasticQueries.Extensions; public static class QueryNodeExtensions { private const string QueryKey = "@Query"; - public static Task GetQueryAsync(this IQueryNode node, Func> getDefaultValue = null) + public static Task GetQueryAsync(this IQueryNode node, Func> getDefaultValue = null) { if (!node.Data.TryGetValue(QueryKey, out object value)) { if (getDefaultValue == null) - return Task.FromResult(null); + return Task.FromResult(null); return getDefaultValue?.Invoke(); } - return Task.FromResult(value as QueryBase); + return Task.FromResult(value as Query); } - public static void SetQuery(this IQueryNode node, QueryBase container) + public static void SetQuery(this IQueryNode node, Query container) { node.Data[QueryKey] = container; } @@ -42,20 +45,20 @@ public static SourceFilter GetSourceFilter(this IQueryNode node, Func GetAggregationAsync(this IQueryNode node, Func> getDefaultValue = null) + public static Task GetAggregationAsync(this IQueryNode node, Func> getDefaultValue = null) { if (!node.Data.TryGetValue(AggregationKey, out object value)) { if (getDefaultValue == null) - return Task.FromResult(null); + return Task.FromResult(null); return getDefaultValue?.Invoke(); } - return Task.FromResult(value as AggregationBase); + return Task.FromResult(value as Aggregation); } - public static void SetAggregation(this IQueryNode node, AggregationBase aggregation) + public static void SetAggregation(this IQueryNode node, Aggregation aggregation) { node.Data[AggregationKey] = aggregation; } @@ -66,15 +69,15 @@ public static void RemoveAggregation(this IQueryNode node) } private const string SortKey = "@Sort"; - public static IFieldSort GetSort(this IQueryNode node, Func getDefaultValue = null) + public static SortOptions GetSort(this IQueryNode node, Func getDefaultValue = null) { if (!node.Data.TryGetValue(SortKey, out object value)) return getDefaultValue?.Invoke(); - return value as IFieldSort; + return value as SortOptions; } - public static void SetSort(this IQueryNode node, IFieldSort sort) + public static void SetSort(this IQueryNode node, SortOptions sort) { node.Data[SortKey] = sort; } diff --git a/src/Foundatio.Parsers.ElasticQueries/Extensions/QueryVisitorContextExtensions.cs b/src/Foundatio.Parsers.ElasticQueries/Extensions/QueryVisitorContextExtensions.cs index d7c65606..64310b2b 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Extensions/QueryVisitorContextExtensions.cs +++ b/src/Foundatio.Parsers.ElasticQueries/Extensions/QueryVisitorContextExtensions.cs @@ -1,10 +1,10 @@ using System; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch.QueryDsl; using Foundatio.Parsers.ElasticQueries.Visitors; using Foundatio.Parsers.LuceneQueries.Extensions; using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; -using Nest; namespace Foundatio.Parsers.ElasticQueries.Extensions; diff --git a/src/Foundatio.Parsers.ElasticQueries/Extensions/SearchDescriptorExtensions.cs b/src/Foundatio.Parsers.ElasticQueries/Extensions/SearchDescriptorExtensions.cs deleted file mode 100644 index f462b798..00000000 --- a/src/Foundatio.Parsers.ElasticQueries/Extensions/SearchDescriptorExtensions.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using Nest; - -namespace Foundatio.Parsers.ElasticQueries.Extensions; - -public static class SearchDescriptorExtensions -{ - public static SearchDescriptor Aggregations(this SearchDescriptor descriptor, AggregationContainer aggregations) where T : class - { - descriptor.Aggregations(f => - { - ((IAggregationContainer)f).Aggregations = aggregations.Aggregations; - return f; - }); - - return descriptor; - } - - public static SearchDescriptor Sort(this SearchDescriptor descriptor, IEnumerable sorts) where T : class - { - var searchRequest = descriptor as ISearchRequest; - - foreach (var sort in sorts) - { - if (searchRequest.Sort == null) - searchRequest.Sort = new List(); - - searchRequest.Sort.Add(sort); - } - - return descriptor; - } -} diff --git a/src/Foundatio.Parsers.ElasticQueries/Foundatio.Parsers.ElasticQueries.csproj b/src/Foundatio.Parsers.ElasticQueries/Foundatio.Parsers.ElasticQueries.csproj index 61260e8d..f09c4c55 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Foundatio.Parsers.ElasticQueries.csproj +++ b/src/Foundatio.Parsers.ElasticQueries/Foundatio.Parsers.ElasticQueries.csproj @@ -1,8 +1,8 @@  + - diff --git a/src/Foundatio.Parsers.ElasticQueries/Visitors/CombineAggregationsVisitor.cs b/src/Foundatio.Parsers.ElasticQueries/Visitors/CombineAggregationsVisitor.cs index ba7985d4..1e5e5001 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Visitors/CombineAggregationsVisitor.cs +++ b/src/Foundatio.Parsers.ElasticQueries/Visitors/CombineAggregationsVisitor.cs @@ -2,11 +2,13 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch; +using Elastic.Clients.Elasticsearch.Aggregations; +using Elastic.Clients.Elasticsearch.Core.Search; using Foundatio.Parsers.ElasticQueries.Extensions; using Foundatio.Parsers.LuceneQueries.Extensions; using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; -using Nest; namespace Foundatio.Parsers.ElasticQueries.Visitors; @@ -20,7 +22,7 @@ public override async Task VisitAsync(GroupNode node, IQueryVisitorContext conte throw new ArgumentException("Context must be of type IElasticQueryVisitorContext", nameof(context)); var container = await GetParentContainerAsync(node, context); - var termsAggregation = container as ITermsAggregation; + var termsAggregation = container as TermsAggregation; foreach (var child in node.Children.OfType()) { @@ -49,11 +51,11 @@ public override async Task VisitAsync(GroupNode node, IQueryVisitorContext conte if (!String.IsNullOrEmpty(termNode.Term) && Int32.TryParse(termNode.UnescapedTerm, out int parsedMinCount)) minCount = parsedMinCount; - termsAggregation.MinimumDocumentCount = minCount; + termsAggregation.MinDocCount = minCount; } } - if (termNode != null && container is ITopHitsAggregation topHitsAggregation) + if (termNode != null && container is TopHitsAggregation topHitsAggregation) { var filter = node.GetSourceFilter(() => new SourceFilter()); if (termNode.Field == "@exclude") @@ -70,10 +72,10 @@ public override async Task VisitAsync(GroupNode node, IQueryVisitorContext conte else filter.Includes.And(termNode.UnescapedTerm); } - topHitsAggregation.Source = filter; + topHitsAggregation.Source = new SourceConfig(filter); } - if (termNode != null && container is IDateHistogramAggregation dateHistogramAggregation) + if (termNode != null && container is DateHistogramAggregation dateHistogramAggregation) { if (termNode.Field == "@missing") { @@ -97,7 +99,7 @@ public override async Task VisitAsync(GroupNode node, IQueryVisitorContext conte if (bucketContainer.Aggregations == null) bucketContainer.Aggregations = new AggregationDictionary(); - bucketContainer.Aggregations[((IAggregation)aggregation).Name] = (AggregationContainer)aggregation; + bucketContainer.Aggregations[((Aggregation)aggregation).Name] = (Aggregation)aggregation; } if (termsAggregation != null && (child.Prefix == "-" || child.Prefix == "+")) @@ -107,8 +109,8 @@ public override async Task VisitAsync(GroupNode node, IQueryVisitorContext conte termsAggregation.Order.Add(new TermsOrder { - Key = ((IAggregation)aggregation).Name, - Order = child.Prefix == "-" ? SortOrder.Descending : SortOrder.Ascending + Key = ((Aggregation)aggregation).Name, + Order = child.Prefix == "-" ? SortOrder.Desc : SortOrder.Asc }); } } @@ -117,9 +119,9 @@ public override async Task VisitAsync(GroupNode node, IQueryVisitorContext conte node.SetAggregation(container); } - private async Task GetParentContainerAsync(IQueryNode node, IQueryVisitorContext context) + private async Task GetParentContainerAsync(IQueryNode node, IQueryVisitorContext context) { - AggregationBase container = null; + Aggregation container = null; var currentNode = node; while (container == null && currentNode != null) { diff --git a/src/Foundatio.Parsers.ElasticQueries/Visitors/CombineQueriesVisitor.cs b/src/Foundatio.Parsers.ElasticQueries/Visitors/CombineQueriesVisitor.cs index 390b5609..7d0c953a 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Visitors/CombineQueriesVisitor.cs +++ b/src/Foundatio.Parsers.ElasticQueries/Visitors/CombineQueriesVisitor.cs @@ -1,11 +1,11 @@ using System; using System.Linq; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch.QueryDsl; using Foundatio.Parsers.ElasticQueries.Extensions; using Foundatio.Parsers.LuceneQueries.Extensions; using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; -using Nest; namespace Foundatio.Parsers.ElasticQueries.Visitors; @@ -24,8 +24,8 @@ public override async Task VisitAsync(GroupNode node, IQueryVisitorContext conte if (context is not IElasticQueryVisitorContext elasticContext) throw new ArgumentException("Context must be of type IElasticQueryVisitorContext", nameof(context)); - QueryBase query = await node.GetQueryAsync(() => node.GetDefaultQueryAsync(context)).ConfigureAwait(false); - QueryBase container = query; + Query query = await node.GetQueryAsync(() => node.GetDefaultQueryAsync(context)).ConfigureAwait(false); + Query container = query; var nested = query as NestedQuery; if (nested != null && node.Parent != null) container = null; diff --git a/src/Foundatio.Parsers.ElasticQueries/Visitors/GeoVisitor.cs b/src/Foundatio.Parsers.ElasticQueries/Visitors/GeoVisitor.cs index e754808b..576529af 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Visitors/GeoVisitor.cs +++ b/src/Foundatio.Parsers.ElasticQueries/Visitors/GeoVisitor.cs @@ -1,10 +1,11 @@ using System; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch; +using Elastic.Clients.Elasticsearch.QueryDsl; using Foundatio.Parsers.ElasticQueries.Extensions; using Foundatio.Parsers.LuceneQueries; using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; -using Nest; namespace Foundatio.Parsers.ElasticQueries.Visitors; @@ -23,7 +24,7 @@ public override async Task VisitAsync(TermNode node, IQueryVisitorContext contex return; string location = _resolveGeoLocation != null ? await _resolveGeoLocation(node.Term).ConfigureAwait(false) ?? node.Term : node.Term; - var query = new GeoDistanceQuery { Field = node.Field, Location = location, Distance = node.Proximity ?? Distance.Miles(10) }; + var query = new GeoDistanceQuery { Field = node.Field, Location = location, Distance = node.Proximity ?? "10mi" }; node.SetQuery(query); } @@ -32,7 +33,7 @@ public override void Visit(TermRangeNode node, IQueryVisitorContext context) if (context is not IElasticQueryVisitorContext elasticContext || !elasticContext.MappingResolver.IsGeoPropertyType(node.Field)) return; - var box = new BoundingBox { TopLeft = node.Min, BottomRight = node.Max }; + var box = GeoBounds.TopLeftBottomRight(new TopLeftBottomRightGeoBounds { TopLeft = node.Min, BottomRight = node.Max }); var query = new GeoBoundingBoxQuery { BoundingBox = box, Field = node.Field }; node.SetQuery(query); } diff --git a/src/Foundatio.Parsers.ElasticQueries/Visitors/GetSortFieldsVisitor.cs b/src/Foundatio.Parsers.ElasticQueries/Visitors/GetSortFieldsVisitor.cs index 6fb2f28b..71b7c47f 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Visitors/GetSortFieldsVisitor.cs +++ b/src/Foundatio.Parsers.ElasticQueries/Visitors/GetSortFieldsVisitor.cs @@ -1,16 +1,16 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch; using Foundatio.Parsers.ElasticQueries.Extensions; using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; -using Nest; namespace Foundatio.Parsers.ElasticQueries.Visitors; -public class GetSortFieldsVisitor : QueryNodeVisitorWithResultBase> +public class GetSortFieldsVisitor : QueryNodeVisitorWithResultBase> { - private readonly List _fields = new(); + private readonly List _fields = new(); public override void Visit(TermNode node, IQueryVisitorContext context) { @@ -18,24 +18,24 @@ public override void Visit(TermNode node, IQueryVisitorContext context) return; var sort = node.GetSort(() => node.GetDefaultSort(context)); - if (sort.SortKey == null) + if (sort.AdditionalPropertyName == null) return; _fields.Add(sort); } - public override async Task> AcceptAsync(IQueryNode node, IQueryVisitorContext context) + public override async Task> AcceptAsync(IQueryNode node, IQueryVisitorContext context) { await node.AcceptAsync(this, context).ConfigureAwait(false); return _fields; } - public static Task> RunAsync(IQueryNode node, IQueryVisitorContext context = null) + public static Task> RunAsync(IQueryNode node, IQueryVisitorContext context = null) { return new GetSortFieldsVisitor().AcceptAsync(node, context); } - public static IEnumerable Run(IQueryNode node, IQueryVisitorContext context = null) + public static IEnumerable Run(IQueryNode node, IQueryVisitorContext context = null) { return RunAsync(node, context).GetAwaiter().GetResult(); } diff --git a/src/Foundatio.Parsers.ElasticQueries/Visitors/NestedVisitor.cs b/src/Foundatio.Parsers.ElasticQueries/Visitors/NestedVisitor.cs index 95feaf04..037414ad 100644 --- a/src/Foundatio.Parsers.ElasticQueries/Visitors/NestedVisitor.cs +++ b/src/Foundatio.Parsers.ElasticQueries/Visitors/NestedVisitor.cs @@ -1,10 +1,10 @@ using System; using System.Linq; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch.QueryDsl; using Foundatio.Parsers.ElasticQueries.Extensions; using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; -using Nest; namespace Foundatio.Parsers.ElasticQueries.Visitors; diff --git a/tests/Foundatio.Parsers.ElasticQueries.Tests/AggregationParserTests.cs b/tests/Foundatio.Parsers.ElasticQueries.Tests/AggregationParserTests.cs index d8d9ac89..90997adf 100644 --- a/tests/Foundatio.Parsers.ElasticQueries.Tests/AggregationParserTests.cs +++ b/tests/Foundatio.Parsers.ElasticQueries.Tests/AggregationParserTests.cs @@ -2,13 +2,13 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch; using Foundatio.Parsers.ElasticQueries.Extensions; using Foundatio.Parsers.ElasticQueries.Visitors; using Foundatio.Parsers.LuceneQueries; using Foundatio.Parsers.LuceneQueries.Extensions; using Foundatio.Parsers.LuceneQueries.Visitors; using Microsoft.Extensions.Logging; -using Nest; using Xunit; using Xunit.Abstractions; @@ -138,7 +138,7 @@ await Client.IndexManyAsync([ _logger.LogInformation("Actual: {Request}", actualRequest); var expectedResponse = Client.Search(d => d.Index(index).Aggregations(a => a - .GeoHash("geogrid_field3", h => h.Field("field3").GeoHashPrecision(GeoHashPrecision.Precision1) + .GeoHash("geogrid_field3", h => h.Field("field3").GeoHashPrecision(1) .Aggregations(a1 => a1.Average("avg_lat", s => s.Script(ss => ss.Source("doc['field3'].lat"))).Average("avg_lon", s => s.Script(ss => ss.Source("doc['field3'].lon"))))) .Terms("terms_field1", t => t.Field("field1.keyword").Meta(m => m.Add("@field_type", "text"))) .Histogram("histogram_field4", h => h.Field("field4").Interval(50).MinimumDocumentCount(0)) @@ -245,7 +245,7 @@ await Client.IndexManyAsync([ _logger.LogInformation("Actual: {Request}", actualRequest); var expectedResponse = Client.Search(d => d.Index(index).Aggregations(a => a - .GeoHash("geogrid_alias3", h => h.Field("field3").GeoHashPrecision(GeoHashPrecision.Precision1) + .GeoHash("geogrid_alias3", h => h.Field("field3").GeoHashPrecision(1) .Aggregations(a1 => a1.Average("avg_lat", s => s.Script(ss => ss.Source("doc['field3'].lat"))).Average("avg_lon", s => s.Script(ss => ss.Source("doc['field3'].lon"))))) .Terms("terms_alias1", t => t.Field("field1.keyword").Meta(m => m.Add("@field_type", "text"))) .Histogram("histogram_alias4", h => h.Field("field4").Interval(50).MinimumDocumentCount(0)) diff --git a/tests/Foundatio.Parsers.ElasticQueries.Tests/CustomVisitorTests.cs b/tests/Foundatio.Parsers.ElasticQueries.Tests/CustomVisitorTests.cs index 4852ff02..171d5b7e 100644 --- a/tests/Foundatio.Parsers.ElasticQueries.Tests/CustomVisitorTests.cs +++ b/tests/Foundatio.Parsers.ElasticQueries.Tests/CustomVisitorTests.cs @@ -6,7 +6,6 @@ using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; using Microsoft.Extensions.Logging; -using Nest; using Xunit; using Xunit.Abstractions; diff --git a/tests/Foundatio.Parsers.ElasticQueries.Tests/ElasticMappingResolverTests.cs b/tests/Foundatio.Parsers.ElasticQueries.Tests/ElasticMappingResolverTests.cs index 99812a6b..59ea0f6c 100644 --- a/tests/Foundatio.Parsers.ElasticQueries.Tests/ElasticMappingResolverTests.cs +++ b/tests/Foundatio.Parsers.ElasticQueries.Tests/ElasticMappingResolverTests.cs @@ -1,6 +1,5 @@ using System; using System.Linq.Expressions; -using Nest; using Xunit; using Xunit.Abstractions; @@ -13,7 +12,7 @@ public ElasticMappingResolverTests(ITestOutputHelper output, ElasticsearchFixtur Log.DefaultMinimumLevel = Microsoft.Extensions.Logging.LogLevel.Trace; } - private ITypeMapping MapMyNestedType(TypeMappingDescriptor m) + private TypeMapping MapMyNestedType(TypeMappingDescriptor m) { return m .AutoMap() diff --git a/tests/Foundatio.Parsers.ElasticQueries.Tests/ElasticQueryParserTests.cs b/tests/Foundatio.Parsers.ElasticQueries.Tests/ElasticQueryParserTests.cs index d1967c5e..92b58a8b 100644 --- a/tests/Foundatio.Parsers.ElasticQueries.Tests/ElasticQueryParserTests.cs +++ b/tests/Foundatio.Parsers.ElasticQueries.Tests/ElasticQueryParserTests.cs @@ -2,6 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch; +using Elastic.Clients.Elasticsearch.Mapping; +using Elastic.Clients.Elasticsearch.QueryDsl; using Foundatio.Parsers.ElasticQueries.Extensions; using Foundatio.Parsers.ElasticQueries.Visitors; using Foundatio.Parsers.LuceneQueries; @@ -9,7 +12,6 @@ using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; using Microsoft.Extensions.Logging; -using Nest; using Xunit; using Xunit.Abstractions; @@ -1475,7 +1477,7 @@ public async Task GeoRangeQueryProcessor() [Fact] public async Task CanExpandElasticIncludesAsync() { - var client = new ElasticClient(new ConnectionSettings().DisableDirectStreaming().PrettyJson()); + var client = new ElasticsearchClient(new ElasticsearchClientSettings().DisableDirectStreaming().PrettyJson()); var aliases = new FieldMap { { "field", "aliased" }, { "included", "aliasedincluded" } }; var processor = new ElasticQueryParser(c => c.SetLoggerFactory(Log).UseIncludes(GetIncludeAsync).UseFieldMap(aliases)); diff --git a/tests/Foundatio.Parsers.ElasticQueries.Tests/InvertQueryTests.cs b/tests/Foundatio.Parsers.ElasticQueries.Tests/InvertQueryTests.cs index 6037ef46..3447fc49 100644 --- a/tests/Foundatio.Parsers.ElasticQueries.Tests/InvertQueryTests.cs +++ b/tests/Foundatio.Parsers.ElasticQueries.Tests/InvertQueryTests.cs @@ -6,7 +6,6 @@ using Foundatio.Parsers.LuceneQueries.Nodes; using Foundatio.Parsers.LuceneQueries.Visitors; using Microsoft.Extensions.Logging; -using Nest; using Xunit; using Xunit.Abstractions; diff --git a/tests/Foundatio.Parsers.ElasticQueries.Tests/Utility/ElasticsearchTestBase.cs b/tests/Foundatio.Parsers.ElasticQueries.Tests/Utility/ElasticsearchTestBase.cs index 9792421a..00589aa8 100644 --- a/tests/Foundatio.Parsers.ElasticQueries.Tests/Utility/ElasticsearchTestBase.cs +++ b/tests/Foundatio.Parsers.ElasticQueries.Tests/Utility/ElasticsearchTestBase.cs @@ -2,10 +2,12 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch; +using Elastic.Clients.Elasticsearch.IndexManagement; +using Elastic.Clients.Elasticsearch.Mapping; using Foundatio.Parsers.ElasticQueries.Extensions; using Foundatio.Xunit; using Microsoft.Extensions.Logging; -using Nest; using Xunit; using Xunit.Abstractions; @@ -26,14 +28,14 @@ public ElasticsearchTestBase(ITestOutputHelper output, T fixture) : base(output) _fixture.Log = Log; } - protected IElasticClient Client => _fixture.Client; + protected ElasticsearchClient Client => _fixture.Client; - protected void CreateNamedIndex(string index, Func, ITypeMapping> configureMappings = null, Func> configureIndex = null) where TModel : class + protected void CreateNamedIndex(string index, Func, TypeMapping> configureMappings = null, Func> configureIndex = null) where TModel : class { _fixture.CreateNamedIndex(index, configureMappings, configureIndex); } - protected string CreateRandomIndex(Func, ITypeMapping> configureMappings = null, Func> configureIndex = null) where TModel : class + protected string CreateRandomIndex(Func, TypeMapping> configureMappings = null, Func> configureIndex = null) where TModel : class { return _fixture.CreateRandomIndex(configureMappings, configureIndex); } @@ -65,23 +67,23 @@ public class ElasticsearchFixture : IAsyncLifetime private readonly List _createdIndexes = new(); private static bool _elaticsearchReady; protected readonly ILogger _logger; - private readonly Lazy _client; + private readonly Lazy _client; public ElasticsearchFixture() { - _client = new Lazy(() => GetClient(ConfigureConnectionSettings)); + _client = new Lazy(() => GetClient(ConfigureConnectionSettings)); } public TestLogger Log { get; set; } - public IElasticClient Client => _client.Value; + public ElasticsearchClient Client => _client.Value; - protected IElasticClient GetClient(Action configure = null) + protected ElasticsearchClient GetClient(Action configure = null) { string elasticsearchUrl = Environment.GetEnvironmentVariable("ELASTICSEARCH_URL") ?? "http://localhost:9200"; - var settings = new ConnectionSettings(new Uri(elasticsearchUrl)); + var settings = new ElasticsearchClientSettings(new Uri(elasticsearchUrl)); configure?.Invoke(settings); - var client = new ElasticClient(settings.DisableDirectStreaming().PrettyJson()); + var client = new ElasticsearchClient(settings.DisableDirectStreaming().PrettyJson()); if (!_elaticsearchReady) { @@ -94,9 +96,9 @@ protected IElasticClient GetClient(Action configure = null) return client; } - protected virtual void ConfigureConnectionSettings(ConnectionSettings settings) { } + protected virtual void ConfigureConnectionSettings(ElasticsearchClientSettings settings) { } - public void CreateNamedIndex(string index, Func, ITypeMapping> configureMappings = null, Func> configureIndex = null) where T : class + public void CreateNamedIndex(string index, Func, TypeMapping> configureMappings = null, Func> configureIndex = null) where T : class { if (configureMappings == null) configureMappings = m => m.AutoMap().Dynamic(); @@ -104,10 +106,10 @@ public void CreateNamedIndex(string index, Func, ITy configureIndex = i => i.NumberOfReplicas(0).Analysis(a => a.AddSortNormalizer()); CreateIndex(index, i => i.Settings(configureIndex).Map(configureMappings)); - Client.ConnectionSettings.DefaultIndices[typeof(T)] = index; + Client.ElasticsearchClientSettings.DefaultIndices[typeof(T)] = index; } - public string CreateRandomIndex(Func, ITypeMapping> configureMappings = null, Func> configureIndex = null) where T : class + public string CreateRandomIndex(Func, TypeMapping> configureMappings = null, Func> configureIndex = null) where T : class { string index = "test_" + Guid.NewGuid().ToString("N"); if (configureMappings == null) @@ -116,7 +118,7 @@ public string CreateRandomIndex(Func, ITypeMapping> configureIndex = i => i.NumberOfReplicas(0).Analysis(a => a.AddSortNormalizer()); CreateIndex(index, i => i.Settings(configureIndex).Map(configureMappings)); - Client.ConnectionSettings.DefaultIndices[typeof(T)] = index; + Client.ElasticsearchClientSettings.DefaultIndices[typeof(T)] = index; return index; } @@ -135,7 +137,7 @@ public CreateIndexResponse CreateIndex(IndexName index, Func 0) client.Indices.Delete(Indices.Index(_createdIndexes)); diff --git a/tests/Foundatio.Parsers.LuceneQueries.Tests/Utility/LoggingTracer.cs b/tests/Foundatio.Parsers.LuceneQueries.Tests/Utility/LoggingTracer.cs index 259e28b9..579d15a6 100644 --- a/tests/Foundatio.Parsers.LuceneQueries.Tests/Utility/LoggingTracer.cs +++ b/tests/Foundatio.Parsers.LuceneQueries.Tests/Utility/LoggingTracer.cs @@ -63,7 +63,7 @@ public void TraceRuleEnter(string ruleName, Cursor cursor) ruleStats.Locations.TryGetValue(key, out int count); ruleStats.Locations[key] = count + 1; - _logger.LogInformation($"{GetIndent()}Start '{ruleName}' at ({cursor.Line},{cursor.Column}) with state key {cursor.StateKey}"); + _logger.LogInformation("{Indent}Start \'{RuleName}\' at ({CursorLine},{CursorColumn}) with state key {CursorStateKey}", GetIndent(), ruleName, cursor.Line, cursor.Column, cursor.StateKey); _indentLevel++; }