diff --git a/src/Typesense/SearchParameters.cs b/src/Typesense/SearchParameters.cs index 8b3326c..e363f49 100644 --- a/src/Typesense/SearchParameters.cs +++ b/src/Typesense/SearchParameters.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Text.Json.Serialization; using Typesense.Converter; @@ -81,8 +82,41 @@ public record SearchParameters /// be treated as a prefix, and not as a whole word. This is used for building /// autocomplete and instant search interfaces. Defaults to true. /// + /// Backwards compatible implementation for existing clients. + [JsonPropertyName("_prefix")] + public bool? Prefix + { + get => PrefixList == null ? null : PrefixList.Count > 0 ? PrefixList[0] : null; + set + { + if (value != null) + { + if (PrefixList == null) + { + PrefixList = new List(); + } + if(PrefixList.Count == 0) + { + PrefixList.Add(value.Value); + } + else + { + PrefixList[0] = value.Value!; + } + } + } + } + + /// + /// List of boolean fields to indicate that the last word in the query should + /// be treated as a prefix, and not as a whole word. This is used for building + /// autocomplete and instant search interfaces. + /// For example, if you are querying 3 fields and want to enable prefix searching only on the first field + /// you can set the prefix property to [true, false, false]. + /// Defaults to true. + /// [JsonPropertyName("prefix")] - public bool? Prefix { get; set; } + public List PrefixList { get; set; } /// /// If infix index is enabled for this field, infix searching can be done on a per-field basis by sending a comma separated string parameter called infix to the search query. diff --git a/src/Typesense/TypesenseClient.cs b/src/Typesense/TypesenseClient.cs index 37be0d8..80acca7 100644 --- a/src/Typesense/TypesenseClient.cs +++ b/src/Typesense/TypesenseClient.cs @@ -781,6 +781,12 @@ private static string CreateUrlParameters(T queryParameters) null => null, true => "true", false => "false", + List list => string.Join(",", + list.Select(v => v switch + { + true => "true", + false => "false" + })), Enum e => e.ToString().ToLowerInvariant(), _ => value.ToString(), }; diff --git a/test/Typesense.Tests/TypesenseClientTests.cs b/test/Typesense.Tests/TypesenseClientTests.cs index 341b37e..836dd31 100644 --- a/test/Typesense.Tests/TypesenseClientTests.cs +++ b/test/Typesense.Tests/TypesenseClientTests.cs @@ -1500,6 +1500,62 @@ public async Task Search_query_by_two_fields() } } + [Fact, TestPriority(11)] + public async Task Search_query_with_prefix_true_should_work() + { + var expected = new Company + { + Id = "124", + CompanyName = "Stark Industries", + NumEmployees = 6000, + Location = new Location + { + City = "Phoenix", + Country = "USA" + }, + }; + + var query = new SearchParameters("Stark", "company_name") + { + Prefix = true + }; + var response = await _client.Search("companies", query); + + using (var scope = new AssertionScope()) + { + response.Found.Should().Be(1); + response.Hits.First().Document.Should().BeEquivalentTo(expected); + } + } + + [Fact, TestPriority(11)] + public async Task Search_query_with_prefix_list_should_work() + { + var expected = new Company + { + Id = "124", + CompanyName = "Stark Industries", + NumEmployees = 6000, + Location = new Location + { + City = "Phoenix", + Country = "USA" + }, + }; + + var query = new SearchParameters("Stark", "company_name,location.country") + { + PrefixList = new List { true, false } + }; + var response = await _client.Search("companies", query); + + using (var scope = new AssertionScope()) + { + response.Found.Should().Be(1); + response.Hits.First().Document.Should().BeEquivalentTo(expected); + } + } + [Fact, TestPriority(11)] public async Task Search_facet_by_country() {