diff --git a/src/Nest/Search/Search/Highlighting/HighlighterType.cs b/src/Nest/Search/Search/Highlighting/HighlighterType.cs index a835163ae85..e744c4bf4e6 100644 --- a/src/Nest/Search/Search/Highlighting/HighlighterType.cs +++ b/src/Nest/Search/Search/Highlighting/HighlighterType.cs @@ -12,8 +12,8 @@ public enum HighlighterType { /// /// Plain Highlighter. - /// The default choice of highlighter is of type plain and uses the Lucene highlighter. - /// It tries hard to reflect the query matching logic in terms of understanding word + /// The default choice of highlighter is of type plain and uses the Lucene highlighter. + /// It tries hard to reflect the query matching logic in terms of understanding word /// importance and any word positioning criteria in phrase queries. /// [EnumMember(Value = "plain")] @@ -21,7 +21,7 @@ public enum HighlighterType /// /// Postings Highlighter. - /// If index_options is set to offsets in the mapping the postings highlighter + /// If index_options is set to offsets in the mapping the postings highlighter /// will be used instead of the plain highlighter /// [EnumMember(Value = "postings")] @@ -29,10 +29,22 @@ public enum HighlighterType /// /// Fast Vector Highlighter. - /// If term_vector information is provided by setting term_vector to with_positions_offsets + /// If term_vector information is provided by setting term_vector to with_positions_offsets /// in the mapping then the fast vector highlighter will be used instead of the plain highlighter /// [EnumMember(Value = "fvh")] - Fvh + Fvh, + + + /// + /// Unified Highlighter. + /// The unified highlighter can extract offsets from either postings, term vectors, or via re-analyzing text. + /// Under the hood it uses Lucene UnifiedHighlighter which picks its strategy depending on the field and the query to highlight. + /// Independently of the strategy this highlighter breaks the text into sentences and scores individual sentences as if + /// they were documents in this corpus, using the BM25 algorithm. It supports accurate phrase and multi-term + /// (fuzzy, prefix, regex) highlighting + /// + [EnumMember(Value = "unified")] + Unified } } diff --git a/src/Tests/Search/Request/HighlightingUsageTests.cs b/src/Tests/Search/Request/HighlightingUsageTests.cs index 91ff69dc40b..ab6956bdafc 100644 --- a/src/Tests/Search/Request/HighlightingUsageTests.cs +++ b/src/Tests/Search/Request/HighlightingUsageTests.cs @@ -23,6 +23,8 @@ public class HighlightingUsageTests : SearchUsageTestBase { public HighlightingUsageTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + public string LastNameSearch { get; } = Project.Projects.First().LeadDeveloper.LastName; + protected override object ExpectJson => new { query = new @@ -72,6 +74,26 @@ public HighlightingUsageTests(ReadOnlyCluster cluster, EndpointUsage usage) : ba } } }, + { "leadDeveloper.lastName", new JObject + { + { "type", "unified" }, + { "pre_tags", new JArray { "" } }, + { "post_tags", new JArray { "" } }, + { "highlight_query", new JObject + { + { "match", new JObject + { + { "leadDeveloper.lastName", new JObject + { + { "query", LastNameSearch } + } + } + } + } + } + } + } + }, { "state.offsets", new JObject { { "type", "postings" }, @@ -122,6 +144,17 @@ public HighlightingUsageTests(ReadOnlyCluster cluster, EndpointUsage usage) : ba .Query("Kurt Edgardo Naomi Dariana Justice Felton") ) ), + fs => fs + .Field(p => p.LeadDeveloper.LastName) + .Type(HighlighterType.Unified) + .PreTags("") + .PostTags("") + .HighlightQuery(q => q + .Match(m => m + .Field(p => p.LeadDeveloper.LastName) + .Query(LastNameSearch) + ) + ), fs => fs .Field(p => p.State.Suffix("offsets")) .Type(HighlighterType.Postings) @@ -175,6 +208,18 @@ public HighlightingUsageTests(ReadOnlyCluster cluster, EndpointUsage usage) : ba } } }, + { "leadDeveloper.lastName", new HighlightField + { + Type = HighlighterType.Unified, + PreTags = new[] { ""}, + PostTags = new[] { ""}, + HighlightQuery = new MatchQuery + { + Field = "leadDeveloper.lastName", + Query = LastNameSearch + } + } + }, { "state.offsets", new HighlightField { Type = HighlighterType.Postings, @@ -215,6 +260,14 @@ protected override void ExpectResponse(ISearchResponse response) highlight.Should().Contain(""); } } + else if (highlightField.Key == "leadDeveloper.lastName ") + { + foreach (var highlight in highlightField.Value.Highlights) + { + highlight.Should().Contain(""); + highlight.Should().Contain(""); + } + } else if (highlightField.Key == "state.offsets") { foreach (var highlight in highlightField.Value.Highlights)