diff --git a/Hackney.Core.Tests/Hackney.Core.Tests.ElasticSearch/QueryBuilderTests.cs b/Hackney.Core.Tests/Hackney.Core.Tests.ElasticSearch/QueryBuilderTests.cs index 8f84a92..1ea315c 100644 --- a/Hackney.Core.Tests/Hackney.Core.Tests.ElasticSearch/QueryBuilderTests.cs +++ b/Hackney.Core.Tests/Hackney.Core.Tests.ElasticSearch/QueryBuilderTests.cs @@ -1,29 +1,29 @@ -using Elasticsearch.Net; -using Hackney.Core.ElasticSearch; -using Hackney.Core.ElasticSearch.Interfaces; -using Moq; -using Nest; +using Elasticsearch.Net; +using Hackney.Core.ElasticSearch; +using Hackney.Core.ElasticSearch.Interfaces; +using Moq; +using Nest; using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using Xunit; namespace Hackney.Core.Tests.ElasticSearch { public class QueryBuilderTests - { - private readonly QueryBuilder _sut; - private readonly Mock _wildcardAppenderAndPrependerMock; - private readonly QueryContainerDescriptor _queryContainerDesc; - public QueryBuilderTests() - { - _wildcardAppenderAndPrependerMock = new Mock(); - _queryContainerDesc = new QueryContainerDescriptor(); - - _sut = new QueryBuilder(_wildcardAppenderAndPrependerMock.Object); - } - + { + private readonly QueryBuilder _sut; + private readonly Mock _wildcardAppenderAndPrependerMock; + private readonly QueryContainerDescriptor _queryContainerDesc; + public QueryBuilderTests() + { + _wildcardAppenderAndPrependerMock = new Mock(); + _queryContainerDesc = new QueryContainerDescriptor(); + + _sut = new QueryBuilder(_wildcardAppenderAndPrependerMock.Object); + } + [Theory] [InlineData(TextQueryType.BestFields)] [InlineData(TextQueryType.MostFields)] @@ -36,15 +36,15 @@ public void WhenCreatingQuery_WithSpecifiedType_ResultantQueryShouldBeThatType(T .Returns(new List { "*4*", "*Annerdale*", "*House*" }); // Act - QueryContainer query = _sut.WithWildstarQuery(searchText, fields, queryType) - .Build(_queryContainerDesc); - - // Assert + QueryContainer query = _sut.WithWildstarQuery(searchText, fields, queryType) + .Build(_queryContainerDesc); + + // Assert var container = (query as IQueryContainer).Bool.Should.First() as IQueryContainer; Assert.Equal(queryType, container.QueryString.Type); - } - + } + [Fact] public void WhenCreatingQuery_WithWildstar_ResultantQueryShouldHaveOneSubquery() { @@ -55,16 +55,36 @@ public void WhenCreatingQuery_WithWildstar_ResultantQueryShouldHaveOneSubquery() .Returns(new List { "*12*", "*Pitcairn*", "*Street*" }); // Act - QueryContainer query = _sut.WithWildstarQuery(searchText, fields) - .Build(_queryContainerDesc); + QueryContainer query = _sut.WithWildstarQuery(searchText, fields) + .Build(_queryContainerDesc); // Assert var container = (query as IQueryContainer).Bool.Should; Assert.Equal(2, container.Count()); Assert.Equal(1, container.Count(q => q != null)); - } - + } + + [Fact] + public void WhenCreatingQuery_WithWildstarBool_ResultantQueryShouldHaveOneSubquery() + { + // Arrange + string searchText = "8 Westminster Lane"; + var fields = new List { "field1", "field2" }; + _wildcardAppenderAndPrependerMock.Setup(x => x.Process(It.IsAny())) + .Returns(new List { "*8*", "*Westminster*", "*Lane*" }); + + // Act + QueryContainer query = _sut.WithWildstarBoolQuery(searchText, fields) + .Build(_queryContainerDesc); + + // Assert + var container = (query as IQueryContainer).Bool.Should; + + Assert.Equal(2, container.Count()); + Assert.Equal(1, container.Count(q => q != null)); + } + [Fact] public void WhenCreatingSimpleQuery_WithWildstar_ResultantQueryBeOfSimpleType() { @@ -73,14 +93,14 @@ public void WhenCreatingSimpleQuery_WithWildstar_ResultantQueryBeOfSimpleType() var fields = new List { "field11", "field12" }; // Act - QueryContainer query = _sut.BuildSimpleQuery(_queryContainerDesc, searchText, fields); + QueryContainer query = _sut.BuildSimpleQuery(_queryContainerDesc, searchText, fields); // Assert var container = (query as IQueryContainer).SimpleQueryString; Assert.NotNull(container); - Assert.Equal(2, container.Fields.Count()); - Assert.Equal(searchText, container.Query); - } + Assert.Equal(2, container.Fields.Count()); + Assert.Equal(searchText, container.Query); + } } } diff --git a/Hackney.Core/Hackney.Core.ElasticSearch/QueryBuilder.cs b/Hackney.Core/Hackney.Core.ElasticSearch/QueryBuilder.cs index 2dec1e0..f7f44d2 100644 --- a/Hackney.Core/Hackney.Core.ElasticSearch/QueryBuilder.cs +++ b/Hackney.Core/Hackney.Core.ElasticSearch/QueryBuilder.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Hackney.Core.ElasticSearch.Interfaces; using Nest; @@ -29,6 +30,16 @@ public IQueryBuilder WithWildstarQuery(string searchText, List fields return this; } + public IQueryBuilder WithWildstarBoolQuery(string searchText, List fields, int? minimumShouldMatch = 1, TextQueryType textQueryType = TextQueryType.MostFields) + { + var listOfWildCardedWords = _wildCardAppenderAndPrepender.Process(searchText); + + _wildstarQuery = CreateWildcardBoolQuery(listOfWildCardedWords, fields); + + return this; + } + + public IQueryBuilder WithFilterQuery(string commaSeparatedFilters, List fields, TextQueryType textQueryType = TextQueryType.MostFields) { if (commaSeparatedFilters != null) @@ -107,5 +118,27 @@ public QueryContainer BuildSimpleQuery(QueryContainerDescriptor containerDesc } ).Query(searchTerm)); } + + private static Func, QueryContainer> CreateWildcardBoolQuery( + List words, List fields) + { + Func, QueryContainer> query = + (containerDescriptor) => containerDescriptor.Bool(b => b + .Should(fields.Select(field => + (QueryContainer)new BoolQuery + { + Should = words.Select(word => + (QueryContainer)new WildcardQuery + { + Value = word, + Field = field + }).ToList(), + MinimumShouldMatch = words.Count + }).ToArray() + ) + ); + + return query; + } } } \ No newline at end of file