Skip to content

Commit

Permalink
WIP - Upgrade to the new Elasticsearch client
Browse files Browse the repository at this point in the history
  • Loading branch information
niemyjski committed Sep 3, 2024
1 parent dcb1b70 commit 0cccbbf
Show file tree
Hide file tree
Showing 24 changed files with 234 additions and 218 deletions.
79 changes: 45 additions & 34 deletions src/Foundatio.Parsers.ElasticQueries/ElasticMappingResolver.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
using System;
using System.Collections.Concurrent;
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<string, FieldMapping> _mappingCache = new();
private readonly ILogger _logger;

public static ElasticMappingResolver NullInstance = new(() => null);

public ElasticMappingResolver(Func<ITypeMapping> getMapping, Inferrer inferrer = null, ILogger logger = null)
public ElasticMappingResolver(Func<TypeMapping> getMapping, Inferrer inferrer = null, ILogger logger = null)
{
GetServerMappingFunc = getMapping;
_inferrer = inferrer;
_logger = logger ?? NullLogger.Instance;
}

public ElasticMappingResolver(ITypeMapping codeMapping, Inferrer inferrer, Func<ITypeMapping> getMapping, ILogger logger = null)
public ElasticMappingResolver(TypeMapping codeMapping, Inferrer inferrer, Func<TypeMapping> getMapping, ILogger logger = null)
: this(getMapping, inferrer, logger)
{
_codeMapping = codeMapping;
Expand All @@ -53,7 +55,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);
Expand Down Expand Up @@ -136,19 +138,19 @@ public FieldMapping GetMapping(string field, bool followAlias = false)
_mappingCache.AddOrUpdate(field, resolvedMapping, (f, m) => 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;
Expand Down Expand Up @@ -235,7 +237,7 @@ public string GetNonAnalyzedFieldName(string field, string preferredSubField = n

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))
Expand Down Expand Up @@ -265,7 +267,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;
Expand All @@ -276,39 +278,48 @@ 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)
{
if (String.IsNullOrEmpty(field))
return false;

return GetMappingProperty(field, true) is IGeoPointProperty;
return GetMappingProperty(field, true) is GeoPointProperty;
}

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)
{
if (String.IsNullOrEmpty(field))
return false;

return GetMappingProperty(field, true) is IBooleanProperty;
return GetMappingProperty(field, true) is BooleanProperty;
}

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)
Expand All @@ -334,7 +345,7 @@ public FieldType GetFieldType(string field)
"completion" => FieldType.Completion,
"nested" => FieldType.Nested,
"object" => FieldType.Object,
"murmur3" => FieldType.Murmur3Hash,
"murmur3" => FieldType.Murmur3,
"token_count" => FieldType.TokenCount,
"percolator" => FieldType.Percolator,
"integer" => FieldType.Integer,
Expand All @@ -355,12 +366,12 @@ public FieldType GetFieldType(string field)
};
}

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)
{
Expand All @@ -369,7 +380,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;
Expand All @@ -380,12 +391,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
};
Expand All @@ -397,7 +408,7 @@ 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;
Expand All @@ -406,12 +417,12 @@ private IProperties MergeProperties(IProperties codeProperties, IProperties serv

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;
}
Expand All @@ -430,7 +441,7 @@ private IProperties MergeProperties(IProperties codeProperties, IProperties serv
return properties;
}

private Func<ITypeMapping> GetServerMappingFunc { get; set; }
private Func<TypeMapping> GetServerMappingFunc { get; set; }
private DateTime? _lastMappingUpdate = null;
private bool GetServerMapping()
{
Expand All @@ -455,7 +466,7 @@ private bool GetServerMapping()
}
}

public static ElasticMappingResolver Create<T>(Func<TypeMappingDescriptor<T>, ITypeMapping> mappingBuilder, IElasticClient client, ILogger logger = null) where T : class
public static ElasticMappingResolver Create<T>(Func<TypeMappingDescriptor<T>, TypeMapping> mappingBuilder, ElasticsearchClient client, ILogger logger = null) where T : class
{
logger ??= NullLogger.Instance;

Expand All @@ -471,7 +482,7 @@ public static ElasticMappingResolver Create<T>(Func<TypeMappingDescriptor<T>, IT
}, logger);
}

public static ElasticMappingResolver Create<T>(Func<TypeMappingDescriptor<T>, ITypeMapping> mappingBuilder, IElasticClient client, string index, ILogger logger = null) where T : class
public static ElasticMappingResolver Create<T>(Func<TypeMappingDescriptor<T>, TypeMapping> mappingBuilder, ElasticsearchClient client, string index, ILogger logger = null) where T : class
{
logger ??= NullLogger.Instance;

Expand All @@ -487,14 +498,14 @@ public static ElasticMappingResolver Create<T>(Func<TypeMappingDescriptor<T>, IT
}, logger);
}

public static ElasticMappingResolver Create<T>(Func<TypeMappingDescriptor<T>, ITypeMapping> mappingBuilder, Inferrer inferrer, Func<ITypeMapping> getMapping, ILogger logger = null) where T : class
public static ElasticMappingResolver Create<T>(Func<TypeMappingDescriptor<T>, TypeMapping> mappingBuilder, Inferrer inferrer, Func<TypeMapping> getMapping, ILogger logger = null) where T : class
{
var codeMapping = new TypeMappingDescriptor<T>();
codeMapping = mappingBuilder(codeMapping) as TypeMappingDescriptor<T>;
return new ElasticMappingResolver(codeMapping, inferrer, getMapping, logger: logger);
}

public static ElasticMappingResolver Create<T>(IElasticClient client, ILogger logger = null)
public static ElasticMappingResolver Create<T>(ElasticsearchClient client, ILogger logger = null)
{
logger ??= NullLogger.Instance;

Expand All @@ -510,7 +521,7 @@ public static ElasticMappingResolver Create<T>(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;

Expand All @@ -526,7 +537,7 @@ public static ElasticMappingResolver Create(IElasticClient client, string index,
}, client.Infer, logger);
}

public static ElasticMappingResolver Create(Func<ITypeMapping> getMapping, Inferrer inferrer, ILogger logger = null)
public static ElasticMappingResolver Create(Func<TypeMapping> getMapping, Inferrer inferrer, ILogger logger = null)
{
return new ElasticMappingResolver(getMapping, inferrer, logger: logger);
}
Expand Down
18 changes: 10 additions & 8 deletions src/Foundatio.Parsers.ElasticQueries/ElasticQueryParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
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;
Expand Down Expand Up @@ -162,7 +164,7 @@ public async Task<QueryValidationResult> ValidateQueryAsync(string query, QueryV
return context.GetValidationResult();
}

public async Task<QueryContainer> BuildQueryAsync(string query, IElasticQueryVisitorContext context = null)
public async Task<Query> BuildQueryAsync(string query, IElasticQueryVisitorContext context = null)
{
if (context == null)
context = new ElasticQueryVisitorContext();
Expand All @@ -175,7 +177,7 @@ public async Task<QueryContainer> BuildQueryAsync(string query, IElasticQueryVis
return await BuildQueryAsync(result, context).ConfigureAwait(false);
}

public async Task<QueryContainer> BuildQueryAsync(IQueryNode query, IElasticQueryVisitorContext context = null)
public async Task<Query> BuildQueryAsync(IQueryNode query, IElasticQueryVisitorContext context = null)
{
if (context == null)
context = new ElasticQueryVisitorContext();
Expand All @@ -185,7 +187,7 @@ public async Task<QueryContainer> BuildQueryAsync(IQueryNode query, IElasticQuer
{
q = new BoolQuery
{
Filter = new QueryContainer[] { q }
Filter = new Query[] { q }
};
}

Expand All @@ -205,7 +207,7 @@ public async Task<QueryValidationResult> ValidateAggregationsAsync(string query,
return context.GetValidationResult();
}

public async Task<AggregationContainer> BuildAggregationsAsync(string aggregations, IElasticQueryVisitorContext context = null)
public async Task<Aggregation> BuildAggregationsAsync(string aggregations, IElasticQueryVisitorContext context = null)
{
if (context == null)
context = new ElasticQueryVisitorContext();
Expand All @@ -219,7 +221,7 @@ public async Task<AggregationContainer> BuildAggregationsAsync(string aggregatio
}

#pragma warning disable IDE0060 // Remove unused parameter
public async Task<AggregationContainer> BuildAggregationsAsync(IQueryNode aggregations, IElasticQueryVisitorContext context = null)
public async Task<Aggregation> BuildAggregationsAsync(IQueryNode aggregations, IElasticQueryVisitorContext context = null)
{
if (aggregations == null)
return null;
Expand All @@ -241,7 +243,7 @@ public async Task<QueryValidationResult> ValidateSortAsync(string query, QueryVa
return context.GetValidationResult();
}

public async Task<IEnumerable<IFieldSort>> BuildSortAsync(string sort, IElasticQueryVisitorContext context = null)
public async Task<IEnumerable<FieldSort>> BuildSortAsync(string sort, IElasticQueryVisitorContext context = null)
{
if (context == null)
context = new ElasticQueryVisitorContext();
Expand All @@ -254,7 +256,7 @@ public async Task<IEnumerable<IFieldSort>> BuildSortAsync(string sort, IElasticQ
return await BuildSortAsync(result, context).ConfigureAwait(false);
}

public Task<IEnumerable<IFieldSort>> BuildSortAsync(IQueryNode sort, IElasticQueryVisitorContext context = null)
public Task<IEnumerable<FieldSort>> BuildSortAsync(IQueryNode sort, IElasticQueryVisitorContext context = null)
{
if (context == null)
context = new ElasticQueryVisitorContext();
Expand Down
Loading

0 comments on commit 0cccbbf

Please sign in to comment.