public async Task CanExpandElasticIncludesAsync() { var client = new ElasticClient(new ConnectionSettings().DisableDirectStreaming().PrettyJson()); var aliases = new FieldMap { { "field", "aliased" }, { "included", "aliasedincluded" } }; var processor = new ElasticQueryParser(c => c.SetLoggerFactory(Log).UseIncludes(GetIncludeAsync).UseFieldMap(aliases)); var result = await processor.BuildQueryAsync("@include:other"); var actualResponse = client.Search <MyType>(d => d.Index("stuff").Query(q => result)); string actualRequest = actualResponse.GetRequest(); _logger.LogInformation("Actual: {Request}", actualRequest); var expectedResponse = client.Search <MyType>(d => d.Index("stuff").Query(f => f.Bool(b => b.Filter(f1 => f1.Term("aliasedincluded", "value"))))); string expectedRequest = expectedResponse.GetRequest(); _logger.LogInformation("Expected: {Request}", expectedRequest); Assert.Equal(expectedRequest, actualRequest); Assert.Equal(expectedResponse.Total, actualResponse.Total); result = await processor.BuildQueryAsync("@include:other"); actualResponse = client.Search <MyType>(d => d.Index("stuff").Query(q => result)); actualRequest = actualResponse.GetRequest(); _logger.LogInformation("Actual: {Request}", actualRequest); _logger.LogInformation("Expected: {Request}", expectedRequest); Assert.Equal(expectedRequest, actualRequest); Assert.Equal(expectedResponse.Total, actualResponse.Total); }
public void CanResolveIncludeToCustomFilterContainingIgnoredInclude() { var client = GetClient(); var index = CreateRandomIndex <MyType>(client); client.Index(new MyType { Id = "1" }, i => i.Index(index)); var processor = new ElasticQueryParser(c => c .SetLoggerFactory(Log) .UseIncludes(include => ResolveIncludeAsync("test", include, "@custom:(one @include:3)"), ShouldSkipInclude, 0) .AddVisitor(new CustomFilterVisitor(), 1)); var result = processor.BuildQueryAsync("@include:test").Result; var actualResponse = client.Search <MyType>(d => d.Index(index).Query(q => result)); string actualRequest = actualResponse.GetRequest(); _logger.LogInformation("Actual: {Request}", actualRequest); var expectedResponse = client.Search <MyType>(d => d .Index(index).Query(f => f.Bool(b => b.Filter(filter => filter.Terms(m => m.Field("id").Terms("1", "3")))))); string expectedRequest = expectedResponse.GetRequest(); _logger.LogInformation("Expected: {Request}", expectedRequest); Assert.Equal(expectedRequest, actualRequest); Assert.Equal(expectedResponse.Total, actualResponse.Total); }
public async Task CanQueryByAliasAsyncAsync() { string index = nameof(Employee).ToLower(); var client = GetClient(); await client.DeleteIndexAsync(index); await client.RefreshAsync(index); var mapping = new TypeMappingDescriptor <Employee>() .Properties(p => p .Keyword(f => f.Name(e => e.Id).Alias("employee_id")) .Object <object>(o => o.Name("data").Properties(p1 => p1 .Keyword(f => f.Name("Profile_URL").RootAlias("url")) .Keyword(f => f.Name("Security_Access_Code").Alias("code"))))); await client.CreateIndexAsync(index, d => d.Mappings(m => m.Map <Employee>(index, md => mapping))); var response = client.IndexMany(new List <Employee> { new Employee { Id = "ex-001", Data = new Dictionary <string, object> { { "Profile_URL", "/u/ex-001/profile.png" }, { "Security_Access_Code", "1234567890" } } }, }, index); await client.RefreshAsync(index); var visitor = new AliasMappingVisitor(client.Infer); var walker = new MappingWalker(visitor); walker.Accept(mapping); var processor = new ElasticQueryParser(c => c.UseAliases(visitor.RootAliasMap).UseMappings <Employee>(m => mapping, () => client.GetMapping(new GetMappingRequest(index, index)).Mapping)); var result = await processor.BuildQueryAsync("employee_id:ex-001 url:\"/u/ex-001/profile.png\" data.code:1234567890"); var actualResponse = client.Search <Employee>(d => d.Index(index).Query(q => result)); string actualRequest = actualResponse.GetRequest(); _logger.LogInformation("Actual: {Request}", actualResponse); var expectedResponse = client.Search <Employee>(d => d.Index(index).Type(index).Query(q => q .Bool(b => b.Filter( Query <Employee> .Term(f1 => f1.Id, "ex-001") && Query <Employee> .Term(f1 => f1.Data["Profile_URL"], "/u/ex-001/profile.png") && Query <Employee> .Term(f1 => f1.Data["Security_Access_Code"], "1234567890"))) )); string expectedRequest = expectedResponse.GetRequest(); _logger.LogInformation("Actual: {Request}", expectedRequest); Assert.Equal(expectedRequest, actualRequest); Assert.True(actualResponse.IsValid); Assert.True(expectedResponse.IsValid); Assert.Equal(expectedResponse.Total, actualResponse.Total); }
public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new() { string filter = ctx.Source.GetFilterExpression(); string search = ctx.Source.GetSearchExpression(); string sort = ctx.Source.GetSortExpression(); // NOTE: Calling UseScoring here to keep the query from being wrapped in a filter which happens ElasticQueryBuilderExtensions.BuildQuery if (!String.IsNullOrEmpty(filter)) { ctx.Filter &= await _parser.BuildQueryAsync(filter, ctx.SetDefaultOperator(Operator.And).UseScoring()).AnyContext(); } if (!String.IsNullOrEmpty(search)) { ctx.Query &= await _parser.BuildQueryAsync(search, ctx.SetDefaultOperator(Operator.Or).UseScoring()).AnyContext(); } if (!String.IsNullOrEmpty(sort)) { ctx.Search.Sort(await _parser.BuildSortAsync(sort, ctx).AnyContext()); } }
public async Task CanUseAliasMapForTopLevelAlias2Async() { string filter = "program:postgrad"; var aliasMap = new FieldMap { { "program", "programName" } }; var p = new ElasticQueryParser(c => c.UseFieldMap(aliasMap)); IQueryContainer query = await p.BuildQueryAsync(filter); var term = query.Bool.Filter.Single() as IQueryContainer; Assert.NotNull(term.Term); Assert.Equal("programName", term.Term.Field.Name); Assert.Equal("postgrad", term.Term.Value); }
public void CanResolveMultipleCustomFilters() { var client = GetClient(); var index = CreateRandomIndex <MyType>(client); client.Index(new MyType { Id = "1" }, i => i.Index(index)); var processor = new ElasticQueryParser(c => c .SetLoggerFactory(Log) .AddVisitor(new IncludeVisitor()) .AddVisitor(new CustomFilterVisitor())); var result = processor.BuildQueryAsync("@custom:(one) OR (field1:Test @custom:(two))").Result; var actualResponse = client.Search <MyType>(d => d.Index(index).Query(q => result)); string actualRequest = actualResponse.GetRequest(); _logger.LogInformation("Actual: {Request}", actualRequest); var expectedResponse = client.Search <MyType>(d => d.Index(index) .Query(f => f .Bool(b => b .Filter(filter => filter .Bool(b1 => b1 .Should( s1 => s1.Terms(m => m.Field("id").Terms("1")), s2 => s2.Bool(b2 => b2 .Must( m2 => m2.Terms(t1 => t1.Field("id").Terms("2")), m2 => m2.Term(t1 => t1.Field("field1").Value("Test")) ) ) ) ) ) ) ) ); string expectedRequest = expectedResponse.GetRequest(); _logger.LogInformation("Expected: {Request}", expectedRequest); Assert.Equal(expectedRequest, actualRequest); Assert.Equal(expectedResponse.Total, actualResponse.Total); }
public async Task BuildAsync <T>(QueryBuilderContext <T> ctx) where T : class, new() { var searchQuery = ctx.GetSourceAs <ISearchQuery>(); if (searchQuery == null) { return; } if (!String.IsNullOrEmpty(searchQuery.Criteria)) { ctx.Query &= await _parser.BuildQueryAsync(searchQuery.Criteria, ctx).AnyContext(); } if (!String.IsNullOrEmpty(searchQuery.Filter)) { ctx.Filter &= await _parser.BuildFilterAsync(searchQuery.Filter, ctx).AnyContext(); } if (!String.IsNullOrEmpty(searchQuery.Sort)) { ctx.Search.Sort(await _parser.BuildSortAsync(searchQuery.Sort, ctx).AnyContext()); } }