diff --git a/new_docs/contents/nest/search/suggest.markdown b/new_docs/contents/nest/search/suggest.markdown new file mode 100644 index 00000000000..9f7b36280c8 --- /dev/null +++ b/new_docs/contents/nest/search/suggest.markdown @@ -0,0 +1,33 @@ +--- +template: layout.jade +title: Suggest +menusection: search +menuitem: suggest +--- + +# Suggest +The suggest feature suggests similar looking terms based on a provided text by using a suggester. + +## Completion Suggester + + client.Suggest(s => s + .Completion("my-suggestion", c => c + .Text("test"))); + +You can also use fuzzy parameters, either by specifying edit distance and such: + + client.Suggest(s => s + .Completion("my-suggestion", c => c + .Text("test") + .Fuzzy(f => f + .EditDistance(2) + .Transpositions(false) + .MinLength(5) + .PrefixLength(4)))); + +Or by using the Fuzziness variant: + + client.Suggest(s => s + .Completion("my-suggestion", c => c + .Text("test") + .Fuzziness(); \ No newline at end of file diff --git a/src/Nest/DSL/Suggest/CompletionSuggestDescriptor.cs b/src/Nest/DSL/Suggest/CompletionSuggestDescriptor.cs index e886f12bfca..3b77f20f818 100644 --- a/src/Nest/DSL/Suggest/CompletionSuggestDescriptor.cs +++ b/src/Nest/DSL/Suggest/CompletionSuggestDescriptor.cs @@ -1,4 +1,5 @@ -using Nest.Resolvers; +using Nest.DSL.Suggest; +using Nest.Resolvers; using Newtonsoft.Json; using System; using System.Collections.Generic; @@ -12,13 +13,13 @@ namespace Nest public class CompletionSuggestDescriptor : BaseSuggestDescriptor where T : class { [JsonProperty(PropertyName = "fuzzy")] - internal FuzzySuggestDescriptor _Fuzzy { get; set; } + internal IFuzzySuggestDescriptor _Fuzzy { get; set; } public CompletionSuggestDescriptor Size(int size) { this._Size = size; return this; - } + } public CompletionSuggestDescriptor Text(string text) { @@ -49,5 +50,17 @@ public CompletionSuggestDescriptor Fuzzy() this._Fuzzy = new FuzzySuggestDescriptor(); return this; } + + public CompletionSuggestDescriptor Fuzziness(Func, FuzzinessSuggestDescriptor> fuzzinessDescriptor) + { + this._Fuzzy = fuzzinessDescriptor(new FuzzinessSuggestDescriptor()); + return this; + } + + public CompletionSuggestDescriptor Fuzziness() + { + this._Fuzzy = new FuzzinessSuggestDescriptor(); + return this; + } } } diff --git a/src/Nest/DSL/Suggest/FuzzinessSuggestDescriptor.cs b/src/Nest/DSL/Suggest/FuzzinessSuggestDescriptor.cs new file mode 100644 index 00000000000..09f6c600f84 --- /dev/null +++ b/src/Nest/DSL/Suggest/FuzzinessSuggestDescriptor.cs @@ -0,0 +1,34 @@ +using Newtonsoft.Json; + +namespace Nest.DSL.Suggest +{ + [JsonObject(MemberSerialization = MemberSerialization.OptIn)] + public class FuzzinessSuggestDescriptor : IFuzzySuggestDescriptor where T : class + { + [JsonProperty(PropertyName = "fuzziness")] + internal object _Fuzziness { get; private set; } + + public FuzzinessSuggestDescriptor() + { + this._Fuzziness = new object(); + } + + public FuzzinessSuggestDescriptor Fuzziness(string fuzziness) + { + this._Fuzziness = fuzziness; + return this; + } + + public FuzzinessSuggestDescriptor Fuzziness(int fuzziness) + { + this._Fuzziness = fuzziness; + return this; + } + + public FuzzinessSuggestDescriptor Fuzziness(double fuzziness) + { + this._Fuzziness = fuzziness; + return this; + } + } +} diff --git a/src/Nest/DSL/Suggest/FuzzySuggestDescriptor.cs b/src/Nest/DSL/Suggest/FuzzySuggestDescriptor.cs index 03fdd33d7e8..35c1c8348fe 100644 --- a/src/Nest/DSL/Suggest/FuzzySuggestDescriptor.cs +++ b/src/Nest/DSL/Suggest/FuzzySuggestDescriptor.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +using Nest.DSL.Suggest; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; @@ -7,7 +8,7 @@ namespace Nest { [JsonObject(MemberSerialization = MemberSerialization.OptIn)] - public class FuzzySuggestDescriptor where T : class + public class FuzzySuggestDescriptor : IFuzzySuggestDescriptor where T : class { [JsonProperty(PropertyName="edit_distance")] internal int _EditDistance { get; set; } diff --git a/src/Nest/DSL/Suggest/IFuzzySuggestDescriptor.cs b/src/Nest/DSL/Suggest/IFuzzySuggestDescriptor.cs new file mode 100644 index 00000000000..44a07a96db7 --- /dev/null +++ b/src/Nest/DSL/Suggest/IFuzzySuggestDescriptor.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Nest.DSL.Suggest +{ + internal interface IFuzzySuggestDescriptor + { + } +} diff --git a/src/Nest/IElasticClient.cs b/src/Nest/IElasticClient.cs index 1b3e302720f..35a5dab4c66 100644 --- a/src/Nest/IElasticClient.cs +++ b/src/Nest/IElasticClient.cs @@ -41,6 +41,7 @@ ISearchResponse Scroll(Func, ScrollDescriptor> scro /// indicating for how long the nodes that participate in the search will maintain relevant resources in /// order to continue and support it. /// This is very similar in its idea to opening a cursor against a database. + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-scroll.html /// /// The type that represents the result hits /// A descriptor that describes the scroll operation @@ -248,7 +249,7 @@ Task ValidateAsync(Func, Valida /// Allows to put a warmup search request on a specific index (or indices), with the body composing of a regular /// search request. Types can be provided as part of the URI if the search request is designed to be run only /// against the specific types. - /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html#warmer-adding /// /// The name for the warmer that you want to register /// A descriptor that further describes what the warmer should look like @@ -258,7 +259,7 @@ Task ValidateAsync(Func, Valida /// Allows to put a warmup search request on a specific index (or indices), with the body composing of a regular /// search request. Types can be provided as part of the URI if the search request is designed to be run only /// against the specific types. - /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html#warmer-adding /// /// The name for the warmer that you want to register /// A descriptor that further describes what the warmer should look like @@ -266,7 +267,7 @@ Task ValidateAsync(Func, Valida /// /// Getting a warmer for specific index (or alias, or several indices) based on its name. - /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html#warmer-retrieving /// /// The name of the warmer to get /// An optional selector specifying additional parameters for the get warmer operation @@ -274,7 +275,7 @@ Task ValidateAsync(Func, Valida /// /// Getting a warmer for specific index (or alias, or several indices) based on its name. - /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html#warmer-retrieving /// /// The name of the warmer to get /// An optional selector specifying additional parameters for the get warmer operation @@ -282,7 +283,7 @@ Task ValidateAsync(Func, Valida /// /// Deletes a warmer - /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html#removing /// /// The name of the warmer to delete /// An optional selector specifying additional parameters for the delete warmer operation @@ -290,7 +291,7 @@ Task ValidateAsync(Func, Valida /// /// Deletes a warmer - /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-warmers.html#removing /// /// The name of the warmer to delete /// An optional selector specifying additional parameters for the delete warmer operation @@ -298,7 +299,7 @@ Task ValidateAsync(Func, Valida /// /// Gets an index template - /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html#getting /// /// The name of the template to get /// An optional selector specifying additional parameters for the get template operation @@ -306,7 +307,7 @@ Task ValidateAsync(Func, Valida /// /// Gets an index template - /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html#getting /// /// The name of the template to get /// An optional selector specifying additional parameters for the get template operation @@ -334,7 +335,7 @@ Task ValidateAsync(Func, Valida /// /// Deletes an index template - /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html#delete /// /// The name of the template to delete /// An optional selector specifying additional parameters for the delete template operation @@ -342,7 +343,7 @@ Task ValidateAsync(Func, Valida /// /// Deletes an index template - /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html#delete /// /// The name of the template to delete /// An optional selector specifying additional parameters for the delete template operation @@ -471,6 +472,7 @@ IPercolateCountResponse PercolateCount(K @object, Func PercolateCountAsync(K @object, Func, PercolateCountDescriptor> percolateSelector = null) where T : class where K : class; + /// /// The put mapping API allows to register specific mapping definition for a specific type. /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-put-mapping.html @@ -1036,7 +1038,7 @@ Task IndexManyAsync(IEnumerable objects, string index = nul /// /// The suggest feature suggests similar looking terms based on a provided text by using a suggester. - /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-status.html + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html /// /// The type used to strongly type parts of the suggest operation /// The suggesters to use this operation (can be multiple) @@ -1045,7 +1047,7 @@ ISuggestResponse Suggest(Func, SuggestDescriptor> sel /// /// The suggest feature suggests similar looking terms based on a provided text by using a suggester. - /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-status.html + /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html /// /// The type used to strongly type parts of the suggest operation /// The suggesters to use this operation (can be multiple) @@ -1117,7 +1119,8 @@ Task DocumentExistsAsync(Func, D Task DeleteRepositoryAsync(string repository, Func selector = null); /// - /// A repository can contain multiple snapshots of the same cluster. Snapshot are identified by unique names within the cluster. + /// A repository can contain multiple snapshots of the same cluster. Snapshot are identified by unique names within the cluster. + /// /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshots.html#_snapshot /// /// The name of the repository we want to create a snapshot in /// The name of the snapshot @@ -1125,7 +1128,7 @@ Task DocumentExistsAsync(Func, D ISnapshotResponse Snapshot(string repository, string snapshotName, Func selector = null); /// - /// A repository can contain multiple snapshots of the same cluster. Snapshot are identified by unique names within the cluster. + /// A repository can contain multiple snapshots of the same cluster. Snapshot are identified by unique names within the cluster. /// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshots.html#_snapshot /// /// The name of the repository we want to create a snapshot in diff --git a/src/Nest/Nest.csproj b/src/Nest/Nest.csproj index d28c0dbaa67..18acd344395 100644 --- a/src/Nest/Nest.csproj +++ b/src/Nest/Nest.csproj @@ -226,6 +226,8 @@ + + diff --git a/src/Tests/Nest.Tests.Unit/Search/suggest/CompletionSuggestTests.cs b/src/Tests/Nest.Tests.Unit/Search/suggest/CompletionSuggestTests.cs index 67cf96eca1f..dcb01199f60 100644 --- a/src/Tests/Nest.Tests.Unit/Search/suggest/CompletionSuggestTests.cs +++ b/src/Tests/Nest.Tests.Unit/Search/suggest/CompletionSuggestTests.cs @@ -8,72 +8,132 @@ namespace Nest.Tests.Unit.Search.Suggest { - [TestFixture] - public class CompletionSuggestTests : BaseJsonTests - { - [Test] - public void CompletionSuggestDescriptorTest() - { - var completionSuggestDescriptor = new CompletionSuggestDescriptor() - .OnField("suggest") - .Text("n"); - - var json = TestElasticClient.Serialize(completionSuggestDescriptor); - - var expected = @"{ ""field"": ""suggest"" }"; - - Assert.IsTrue(json.JsonEquals(expected), json); - } - - [Test] - public void CompletionSuggestDescriptorDefaultFuzzyTest() - { - var completionSuggestDescriptor = new CompletionSuggestDescriptor() - .OnField("suggest") - .Text("n") - .Fuzzy(); - - var json = TestElasticClient.Serialize(completionSuggestDescriptor); - - var expected = @"{ - ""fuzzy"": { - ""edit_distance"": 1, - ""transpositions"": true, - ""min_length"": 3, - ""prefix_length"": 1 + [TestFixture] + public class CompletionSuggestTests : BaseJsonTests + { + [Test] + public void CompletionSuggestDescriptorTest() + { + var completionSuggestDescriptor = new CompletionSuggestDescriptor() + .OnField("suggest") + .Text("n"); + + var json = TestElasticClient.Serialize(completionSuggestDescriptor); + + var expected = @"{ field: ""suggest"" }"; + + Assert.IsTrue(json.JsonEquals(expected), json); + } + + [Test] + public void CompletionSuggestDescriptorDefaultFuzzyTest() + { + var completionSuggestDescriptor = new CompletionSuggestDescriptor() + .OnField("suggest") + .Text("n") + .Fuzzy(); + + var json = TestElasticClient.Serialize(completionSuggestDescriptor); + + var expected = @"{ + fuzzy: { + edit_distance: 1, + transpositions: true, + min_length: 3, + prefix_length: 1 + }, + field: ""suggest"" + }"; + + Assert.IsTrue(json.JsonEquals(expected), json); + } + + [Test] + public void CompletionSuggestDescriptorDefaultFuzzinessTest() + { + var completionSuggestDescriptor = new CompletionSuggestDescriptor() + .OnField("suggest") + .Text("n") + .Fuzziness(); + + var json = TestElasticClient.Serialize(completionSuggestDescriptor); + + var expected = @"{ + fuzzy: { + fuzziness: {} + }, + field: ""suggest"" + }"; + + Assert.IsTrue(json.JsonEquals(expected), json); + } + + [Test] + public void CompletionSuggestDescriptorFuzzyTest() + { + var completionSuggestDescriptor = new CompletionSuggestDescriptor() + .OnField("suggest") + .Text("n") + .Fuzzy(f => f + .EditDistance(2) + .Transpositions(false) + .MinLength(5) + .PrefixLength(4)); + + var json = TestElasticClient.Serialize(completionSuggestDescriptor); + + var expected = @"{ + fuzzy"": { + edit_distance: 2, + transpositions: false, + min_length: 5, + prefix_length: 4 + }, + field: ""suggest"" + }"; + + Assert.IsTrue(json.JsonEquals(expected), json); + } + + [Test] + public void CompletionSuggestDescriptorFuzzinessTest() + { + var completionSuggestDescriptor = new CompletionSuggestDescriptor() + .OnField("suggest") + .Text("n") + .Fuzziness(f => f.Fuzziness(1)); + + var json = TestElasticClient.Serialize(completionSuggestDescriptor); + + var expected = @"{ + fuzzy: { + fuzziness: 1 }, - ""field"": ""suggest"" + field: ""suggest"" }"; - Assert.IsTrue(json.JsonEquals(expected), json); - } - - [Test] - public void CompletionSuggestDescriptorFuzzyTest() - { - var completionSuggestDescriptor = new CompletionSuggestDescriptor() - .OnField("suggest") - .Text("n") - .Fuzzy(f => f - .EditDistance(2) - .Transpositions(false) - .MinLength(5) - .PrefixLength(4)); - - var json = TestElasticClient.Serialize(completionSuggestDescriptor); - - var expected = @"{ - ""fuzzy"": { - ""edit_distance"": 2, - ""transpositions"": false, - ""min_length"": 5, - ""prefix_length"": 4 + Assert.IsTrue(json.JsonEquals(expected), json); + } + + [Test] + public void CompletionSuggestDescriptorFuzzinessDoubleTest() + { + var completionSuggestDescriptor = new CompletionSuggestDescriptor() + .OnField("suggest") + .Text("n") + .Fuzziness(f => f.Fuzziness(0.4)); + + var json = TestElasticClient.Serialize(completionSuggestDescriptor); + + var expected = @"{ + fuzzy: { + fuzziness: 0.4 }, - ""field"": ""suggest"" + field: ""suggest"" }"; - Assert.IsTrue(json.JsonEquals(expected), json); - } + Assert.IsTrue(json.JsonEquals(expected), json); + } [Test] public void CompletionSuggestOnSearchTest() @@ -81,7 +141,7 @@ public void CompletionSuggestOnSearchTest() var search = this._client.Search(s => s .SuggestCompletion("mycompletionsuggest", ts => ts .Text("n") - .OnField(p=>p.Name) + .OnField(p => p.Name) .Fuzzy() ) ); @@ -105,5 +165,33 @@ public void CompletionSuggestOnSearchTest() var json = search.ConnectionStatus.Request.Utf8String(); Assert.True(json.JsonEquals(expected), json); } - } + + [Test] + public void CompletionSuggestWithFuzzinessOnSearchTest() + { + var search = this._client.Search(s => s + .SuggestCompletion("mycompletionsuggest", ts => ts + .Text("n") + .OnField(p => p.Name) + .Fuzziness() + ) + ); + + var expected = @"{ + suggest: { + mycompletionsuggest: { + text: ""n"", + completion: { + fuzzy: { + fuzziness: {} + }, + field: ""name"" + } + } + } + }"; + var json = search.ConnectionStatus.Request.Utf8String(); + Assert.True(json.JsonEquals(expected), json); + } + } }