From 6ce6924c4b7e67d8605dd59cd9409c452eb90685 Mon Sep 17 00:00:00 2001 From: TebbeM Date: Tue, 15 Oct 2024 14:52:21 +0200 Subject: [PATCH 1/5] add federated multisearch to MeilisearchClient.cs --- .env | 2 +- src/Meilisearch/Constants.cs | 3 + .../AlwaysIncludeEmptyObjectConverter.cs | 63 ++++++++ src/Meilisearch/FederatedMultiSearchQuery.cs | 36 +++++ src/Meilisearch/FederatedSearchQuery.cs | 16 ++ src/Meilisearch/Meilisearch.csproj | 1 - src/Meilisearch/MeilisearchClient.cs | 124 ++++++++++----- .../MultiSearchFederationOptions.cs | 18 +++ src/Meilisearch/SearchQuery.cs | 105 +----------- src/Meilisearch/SearchQueryBase.cs | 113 +++++++++++++ .../MultiIndexSearchTests.cs | 150 +++++++++++++++++- 11 files changed, 484 insertions(+), 147 deletions(-) create mode 100644 src/Meilisearch/Converters/AlwaysIncludeEmptyObjectConverter.cs create mode 100644 src/Meilisearch/FederatedMultiSearchQuery.cs create mode 100644 src/Meilisearch/FederatedSearchQuery.cs create mode 100644 src/Meilisearch/MultiSearchFederationOptions.cs create mode 100644 src/Meilisearch/SearchQueryBase.cs diff --git a/.env b/.env index 767307bf..e1107443 100644 --- a/.env +++ b/.env @@ -1,3 +1,3 @@ -MEILISEARCH_VERSION=v1.9.0 +MEILISEARCH_VERSION=v1.10.0 PROXIED_MEILISEARCH=http://nginx/api/ MEILISEARCH_URL=http://meilisearch:7700 diff --git a/src/Meilisearch/Constants.cs b/src/Meilisearch/Constants.cs index 5aa0a1b3..32216d29 100644 --- a/src/Meilisearch/Constants.cs +++ b/src/Meilisearch/Constants.cs @@ -1,6 +1,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +using Meilisearch.Converters; + namespace Meilisearch { /// @@ -15,6 +17,7 @@ internal static class Constants { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + Converters = { new MultiSearchFederationOptionsConverter() } }; /// diff --git a/src/Meilisearch/Converters/AlwaysIncludeEmptyObjectConverter.cs b/src/Meilisearch/Converters/AlwaysIncludeEmptyObjectConverter.cs new file mode 100644 index 00000000..d85cfba1 --- /dev/null +++ b/src/Meilisearch/Converters/AlwaysIncludeEmptyObjectConverter.cs @@ -0,0 +1,63 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Meilisearch.Converters +{ + /// + /// Always include Property in json objects will be serialized as "{}" + /// + /// + public class MultiSearchFederationOptionsConverter : JsonConverter + { + public override MultiSearchFederationOptions Read(ref Utf8JsonReader reader, Type typeToConvert, + JsonSerializerOptions options) + { + return JsonSerializer.Deserialize(ref reader, options); + } + + public override void Write(Utf8JsonWriter writer, MultiSearchFederationOptions value, + JsonSerializerOptions options) + { + if (value == null || !HasAnyValueSet(value)) + { + // Write an empty object if the value is null + writer.WriteStartObject(); + writer.WriteEndObject(); + } + else + { + var newOptions = new JsonSerializerOptions(options); + newOptions.Converters.Remove(newOptions.Converters.First(c => + c.GetType() == typeof(MultiSearchFederationOptionsConverter))); + + // Serialize the value as usual + JsonSerializer.Serialize(writer, value, newOptions); + } + } + + private bool HasAnyValueSet(MultiSearchFederationOptions value) + { + foreach (var property in + value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) + { + var propertyValue = property.GetValue(value); + var defaultValue = GetDefaultValue(property.PropertyType); + + if (!Equals(propertyValue, defaultValue)) + { + return true; + } + } + + return false; + } + + private object GetDefaultValue(Type type) + { + return type.IsValueType ? Activator.CreateInstance(type) : null; + } + } +} diff --git a/src/Meilisearch/FederatedMultiSearchQuery.cs b/src/Meilisearch/FederatedMultiSearchQuery.cs new file mode 100644 index 00000000..1b5f5dc7 --- /dev/null +++ b/src/Meilisearch/FederatedMultiSearchQuery.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +using Meilisearch.Converters; + +namespace Meilisearch +{ + /// + /// Search query used in federated multi-index search + /// + public class FederatedMultiSearchQuery + { + + /// + /// Default Constructor that ensures FederationOptions are always set + /// + public FederatedMultiSearchQuery() + { + FederationOptions = new MultiSearchFederationOptions(); + } + + /// + /// The queries + /// + [JsonPropertyName("queries")] + public List Queries { get; set; } + + /// + /// If present and not null, returns a single list merging all search results across all specified queries + /// + [JsonInclude] + [JsonPropertyName("federation")] + [JsonConverter(typeof(MultiSearchFederationOptionsConverter))] + public MultiSearchFederationOptions FederationOptions { get; set; } + } +} diff --git a/src/Meilisearch/FederatedSearchQuery.cs b/src/Meilisearch/FederatedSearchQuery.cs new file mode 100644 index 00000000..beaec24d --- /dev/null +++ b/src/Meilisearch/FederatedSearchQuery.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; + +namespace Meilisearch +{ + /// + /// Search Query for federated Multisearch + /// + public class FederatedSearchQuery : SearchQueryBase + { + /// + /// Federation Options + /// + [JsonPropertyName("federationOptions")] + public MultiSearchFederationOptions FederationOptions { get; set; } + } +} diff --git a/src/Meilisearch/Meilisearch.csproj b/src/Meilisearch/Meilisearch.csproj index b1fc09c2..0c6923f7 100644 --- a/src/Meilisearch/Meilisearch.csproj +++ b/src/Meilisearch/Meilisearch.csproj @@ -13,7 +13,6 @@ logo.png README.md MIT - True diff --git a/src/Meilisearch/MeilisearchClient.cs b/src/Meilisearch/MeilisearchClient.cs index 19fd7b03..74a66ed9 100644 --- a/src/Meilisearch/MeilisearchClient.cs +++ b/src/Meilisearch/MeilisearchClient.cs @@ -13,7 +13,6 @@ namespace Meilisearch { - /// /// Typed client for Meilisearch. /// @@ -29,7 +28,9 @@ public class MeilisearchClient /// /// URL corresponding to Meilisearch server. /// API Key to connect to the Meilisearch server. - public MeilisearchClient(string url, string apiKey = default) : this(new HttpClient(new MeilisearchMessageHandler(new HttpClientHandler())) { BaseAddress = url.ToSafeUri() }, apiKey) + public MeilisearchClient(string url, string apiKey = default) : this( + new HttpClient(new MeilisearchMessageHandler(new HttpClientHandler())) { BaseAddress = url.ToSafeUri() }, + apiKey) { } @@ -58,7 +59,8 @@ public async Task GetVersionAsync(CancellationToken cancella { var response = await _http.GetAsync("version", cancellationToken).ConfigureAwait(false); - return await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken).ConfigureAwait(false); + return await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -74,6 +76,28 @@ public Index Index(string uid) return index; } + /// + /// Searches multiple indexes at once but get a aggregated result + /// + /// The queries to be executed (must have IndexUid set) + /// + /// Aggregated results + /// + public async Task> FederatedMultiSearchAsync(FederatedMultiSearchQuery query, + CancellationToken cancellationToken = default) + { + if (!query.Queries.TrueForAll(x => x.IndexUid != null)) + { + throw new ArgumentNullException("IndexUid", "IndexUid should be provided for all search queries"); + } + + var responseMessage = await _http.PostAsJsonAsync("multi-search", query, + Constants.JsonSerializerOptionsRemoveNulls, cancellationToken: cancellationToken); + return await responseMessage.Content + .ReadFromJsonAsync>(cancellationToken: cancellationToken) + .ConfigureAwait(false); + } + /// /// Searches multiple indexes at once /// @@ -81,17 +105,19 @@ public Index Index(string uid) /// /// /// - public async Task MultiSearchAsync(MultiSearchQuery query, CancellationToken cancellationToken = default) + public async Task MultiSearchAsync(MultiSearchQuery query, + CancellationToken cancellationToken = default) { if (!query.Queries.TrueForAll(x => x.IndexUid != null)) { throw new ArgumentNullException("IndexUid", "IndexUid should be provided for all search queries"); } - var responseMessage = await _http.PostAsJsonAsync("multi-search", query, Constants.JsonSerializerOptionsRemoveNulls, cancellationToken: cancellationToken); + var responseMessage = await _http.PostAsJsonAsync("multi-search", query, + Constants.JsonSerializerOptionsRemoveNulls, cancellationToken: cancellationToken); return await responseMessage.Content - .ReadFromJsonAsync(cancellationToken: cancellationToken) - .ConfigureAwait(false); + .ReadFromJsonAsync(cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -101,13 +127,16 @@ public async Task MultiSearchAsync(MultiSearchQuery query, Ca /// Primary key for documents. /// The cancellation token for this call. /// Returns the associated task. - public async Task CreateIndexAsync(string uid, string primaryKey = default, CancellationToken cancellationToken = default) + public async Task CreateIndexAsync(string uid, string primaryKey = default, + CancellationToken cancellationToken = default) { var index = new Index(uid, primaryKey); - var responseMessage = await _http.PostJsonCustomAsync("indexes", index, Constants.JsonSerializerOptionsRemoveNulls, cancellationToken: cancellationToken) + var responseMessage = await _http.PostJsonCustomAsync("indexes", index, + Constants.JsonSerializerOptionsRemoveNulls, cancellationToken: cancellationToken) .ConfigureAwait(false); - return await responseMessage.Content.ReadFromJsonAsync(cancellationToken: cancellationToken).ConfigureAwait(false); + return await responseMessage.Content.ReadFromJsonAsync(cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -117,7 +146,8 @@ public async Task CreateIndexAsync(string uid, string primaryKey = def /// Primary key set. /// The cancellation token for this call. /// Returns the associated task. - public async Task UpdateIndexAsync(string uid, string primarykeytoChange, CancellationToken cancellationToken = default) + public async Task UpdateIndexAsync(string uid, string primarykeytoChange, + CancellationToken cancellationToken = default) { return await Index(uid).UpdateAsync(primarykeytoChange, cancellationToken).ConfigureAwait(false); } @@ -140,7 +170,8 @@ public async Task DeleteIndexAsync(string uid, CancellationToken cance /// Query parameters. Supports limit and offset. /// The cancellation token for this call. /// An IEnumerable of indexes in JsonElement format. - public async Task GetAllRawIndexesAsync(IndexesQuery query = default, CancellationToken cancellationToken = default) + public async Task GetAllRawIndexesAsync(IndexesQuery query = default, + CancellationToken cancellationToken = default) { var uri = query.ToQueryString(uri: "indexes"); var response = await _http.GetAsync(uri, cancellationToken).ConfigureAwait(false); @@ -155,12 +186,15 @@ public async Task GetAllRawIndexesAsync(IndexesQuery query = defau /// Query parameters. Supports limit and offset. /// The cancellation token for this call. /// Return Enumerable of Index. - public async Task>> GetAllIndexesAsync(IndexesQuery query = default, CancellationToken cancellationToken = default) + public async Task>> GetAllIndexesAsync(IndexesQuery query = default, + CancellationToken cancellationToken = default) { var uri = query.ToQueryString(uri: "indexes"); var response = await _http.GetAsync(uri, cancellationToken).ConfigureAwait(false); - var content = await response.Content.ReadFromJsonAsync>>(cancellationToken: cancellationToken).ConfigureAwait(false); + var content = await response.Content + .ReadFromJsonAsync>>(cancellationToken: cancellationToken) + .ConfigureAwait(false); content.Results .Select(p => p.WithHttpClient(_http)) .ToList(); @@ -188,7 +222,7 @@ public async Task GetIndexAsync(string uid, CancellationToken cancellatio public async Task GetRawIndexAsync(string uid, CancellationToken cancellationToken = default) { var json = await ( - await Meilisearch.Index.GetRawAsync(_http, uid, cancellationToken).ConfigureAwait(false)) + await Meilisearch.Index.GetRawAsync(_http, uid, cancellationToken).ConfigureAwait(false)) .Content.ReadAsStringAsync().ConfigureAwait(false); return JsonDocument.Parse(json).RootElement; } @@ -199,7 +233,8 @@ await Meilisearch.Index.GetRawAsync(_http, uid, cancellationToken).ConfigureAwai /// Query parameters supports by the method. /// The cancellation token for this call. /// Returns a list of tasks. - public async Task>> GetTasksAsync(TasksQuery query = default, CancellationToken cancellationToken = default) + public async Task>> GetTasksAsync(TasksQuery query = default, + CancellationToken cancellationToken = default) { return await TaskEndpoint().GetTasksAsync(query, cancellationToken).ConfigureAwait(false); } @@ -229,7 +264,8 @@ public async Task WaitForTaskAsync( int intervalMs = 50, CancellationToken cancellationToken = default) { - return await TaskEndpoint().WaitForTaskAsync(taskUid, timeoutMs, intervalMs, cancellationToken).ConfigureAwait(false); + return await TaskEndpoint().WaitForTaskAsync(taskUid, timeoutMs, intervalMs, cancellationToken) + .ConfigureAwait(false); } /// @@ -239,7 +275,8 @@ public async Task WaitForTaskAsync( /// Returns stats of all indexes. public async Task GetStatsAsync(CancellationToken cancellationToken = default) { - return await _http.GetFromJsonAsync("stats", cancellationToken: cancellationToken).ConfigureAwait(false); + return await _http.GetFromJsonAsync("stats", cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -281,7 +318,8 @@ public async Task CreateDumpAsync(CancellationToken cancellationToken { var response = await _http.PostAsync("dumps", default, cancellationToken).ConfigureAwait(false); - return await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken).ConfigureAwait(false); + return await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -290,10 +328,12 @@ public async Task CreateDumpAsync(CancellationToken cancellationToken /// Query parameters supports by the method. /// The cancellation token for this call. /// Returns a list of the API keys. - public async Task>> GetKeysAsync(KeysQuery query = default, CancellationToken cancellationToken = default) + public async Task>> GetKeysAsync(KeysQuery query = default, + CancellationToken cancellationToken = default) { var uri = query.ToQueryString(uri: "keys"); - return await _http.GetFromJsonAsync>>(uri, cancellationToken: cancellationToken) + return await _http + .GetFromJsonAsync>>(uri, cancellationToken: cancellationToken) .ConfigureAwait(false); } @@ -318,10 +358,12 @@ public async Task GetKeyAsync(string keyOrUid, CancellationToken cancellati public async Task CreateKeyAsync(Key keyOptions, CancellationToken cancellationToken = default) { var responseMessage = - await _http.PostAsJsonAsync("keys", keyOptions, Constants.JsonSerializerOptionsWriteNulls, cancellationToken: cancellationToken) + await _http.PostAsJsonAsync("keys", keyOptions, Constants.JsonSerializerOptionsWriteNulls, + cancellationToken: cancellationToken) .ConfigureAwait(false); - return await responseMessage.Content.ReadFromJsonAsync(cancellationToken: cancellationToken).ConfigureAwait(false); + return await responseMessage.Content.ReadFromJsonAsync(cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -330,7 +372,8 @@ await _http.PostAsJsonAsync("keys", keyOptions, Constants.JsonSerializerOptionsW /// Query parameters supports by the method. /// The cancellation token for this call. /// Returns the task info of finished task. - public async Task CancelTasksAsync(CancelTasksQuery query, CancellationToken cancellationToken = default) + public async Task CancelTasksAsync(CancelTasksQuery query, + CancellationToken cancellationToken = default) { return await TaskEndpoint().CancelTasksAsync(query, cancellationToken).ConfigureAwait(false); } @@ -341,7 +384,8 @@ public async Task CancelTasksAsync(CancelTasksQuery query, Cancellatio /// Query parameters supports by the method. /// The cancellation token for this call. /// Returns the task info of finished task. - public async Task DeleteTasksAsync(DeleteTasksQuery query, CancellationToken cancellationToken = default) + public async Task DeleteTasksAsync(DeleteTasksQuery query, + CancellationToken cancellationToken = default) { return await TaskEndpoint().DeleteTasksAsync(query, cancellationToken).ConfigureAwait(false); } @@ -354,19 +398,18 @@ public async Task DeleteTasksAsync(DeleteTasksQuery query, Cancellatio /// A name to label the key internally. /// The cancellation token for this call. /// Returns the updated API key. - public async Task UpdateKeyAsync(string keyOrUid, string description = null, string name = null, CancellationToken cancellationToken = default) + public async Task UpdateKeyAsync(string keyOrUid, string description = null, string name = null, + CancellationToken cancellationToken = default) { - var key = new Key - { - Name = name, - Description = description - }; + var key = new Key { Name = name, Description = description }; var responseMessage = - await _http.PatchAsJsonAsync($"keys/{keyOrUid}", key, Constants.JsonSerializerOptionsRemoveNulls, cancellationToken: cancellationToken) + await _http.PatchAsJsonAsync($"keys/{keyOrUid}", key, Constants.JsonSerializerOptionsRemoveNulls, + cancellationToken: cancellationToken) .ConfigureAwait(false); - return await responseMessage.Content.ReadFromJsonAsync(cancellationToken: cancellationToken).ConfigureAwait(false); + return await responseMessage.Content.ReadFromJsonAsync(cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -388,12 +431,15 @@ public async Task DeleteKeyAsync(string keyOrUid, CancellationToken cancel /// List of IndexSwap objects. /// The cancellation token for this call. /// Returns the task info of finished task. - public async Task SwapIndexesAsync(List indexes, CancellationToken cancellationToken = default) + public async Task SwapIndexesAsync(List indexes, + CancellationToken cancellationToken = default) { - var response = await _http.PostAsJsonAsync("swap-indexes", indexes, Constants.JsonSerializerOptionsRemoveNulls, cancellationToken: cancellationToken) - .ConfigureAwait(false); + var response = await _http.PostAsJsonAsync("swap-indexes", indexes, + Constants.JsonSerializerOptionsRemoveNulls, cancellationToken: cancellationToken) + .ConfigureAwait(false); - return await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken).ConfigureAwait(false); + return await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken) + .ConfigureAwait(false); } /// @@ -406,7 +452,8 @@ public async Task SwapIndexesAsync(List indexes, Cancellati /// When there is no defined in the client or as argument. /// When the sent param is in the past /// Returns a generated tenant token. - public string GenerateTenantToken(string apiKeyUid, TenantTokenRules searchRules, string apiKey = null, DateTime? expiresAt = null) + public string GenerateTenantToken(string apiKeyUid, TenantTokenRules searchRules, string apiKey = null, + DateTime? expiresAt = null) { return TenantToken.GenerateToken(apiKeyUid, searchRules, apiKey ?? ApiKey, expiresAt); } @@ -425,6 +472,5 @@ private TaskEndpoint TaskEndpoint() return _taskEndpoint; } - } } diff --git a/src/Meilisearch/MultiSearchFederationOptions.cs b/src/Meilisearch/MultiSearchFederationOptions.cs new file mode 100644 index 00000000..8115edbd --- /dev/null +++ b/src/Meilisearch/MultiSearchFederationOptions.cs @@ -0,0 +1,18 @@ +namespace Meilisearch +{ + /// + /// Federation options in federated multi-index search + /// + public class MultiSearchFederationOptions + { + /// + /// Number of documents to skip + /// + public int Offset { get; set; } + + /// + /// Maximum number of documents returned + /// + public int Limit { get; set; } + } +} diff --git a/src/Meilisearch/SearchQuery.cs b/src/Meilisearch/SearchQuery.cs index 27186a4a..895afa94 100644 --- a/src/Meilisearch/SearchQuery.cs +++ b/src/Meilisearch/SearchQuery.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Text.Json.Serialization; namespace Meilisearch @@ -6,110 +5,8 @@ namespace Meilisearch /// /// Search Query for Meilisearch class. /// - public class SearchQuery + public class SearchQuery : SearchQueryBase { - /// - /// The id of the index - /// - [JsonPropertyName("indexUid")] - public string IndexUid { get; set; } - - /// - /// Gets or sets query string. - /// - [JsonPropertyName("q")] - public string Q { get; set; } - - /// - /// Gets or sets the filter to apply to the query. - /// - [JsonPropertyName("filter")] - public dynamic Filter { get; set; } - - /// - /// Gets or sets attributes to retrieve. - /// - [JsonPropertyName("attributesToRetrieve")] - public IEnumerable AttributesToRetrieve { get; set; } - - /// - /// Gets or sets attributes to crop. - /// - [JsonPropertyName("attributesToCrop")] - public IEnumerable AttributesToCrop { get; set; } - - /// - /// Gets or sets attributes to search on. - /// - [JsonPropertyName("attributesToSearchOn")] - public IEnumerable AttributesToSearchOn { get; set; } - - /// - /// Gets or sets length used to crop field values. - /// - [JsonPropertyName("cropLength")] - public int? CropLength { get; set; } - - /// - /// Gets or sets attributes to highlight. - /// - [JsonPropertyName("attributesToHighlight")] - public IEnumerable AttributesToHighlight { get; set; } - - /// - /// Gets or sets the crop marker to apply before and/or after cropped part selected within an attribute defined in `attributesToCrop` parameter. - /// - [JsonPropertyName("cropMarker")] - public string CropMarker { get; set; } - - /// - /// Gets or sets the tag to put before the highlighted query terms. - /// - [JsonPropertyName("highlightPreTag")] - public string HighlightPreTag { get; set; } - - /// - /// Gets or sets the tag to put after the highlighted query terms. - /// - [JsonPropertyName("highlightPostTag")] - public string HighlightPostTag { get; set; } - - /// - /// Gets or sets the facets for the query. - /// - [JsonPropertyName("facets")] - public IEnumerable Facets { get; set; } - - /// - /// Gets or sets showMatchesPosition. It defines whether an object that contains information about the matches should be returned or not. - /// - [JsonPropertyName("showMatchesPosition")] - public bool? ShowMatchesPosition { get; set; } - - /// - /// Gets or sets the sorted attributes. - /// - [JsonPropertyName("sort")] - public IEnumerable Sort { get; set; } - - /// - /// Gets or sets the words matching strategy. - /// - [JsonPropertyName("matchingStrategy")] - public string MatchingStrategy { get; set; } - - /// - /// Gets or sets showRankingScore parameter. It defines wheter the global ranking score of a document (between 0 and 1) is returned or not. - /// - [JsonPropertyName("showRankingScore")] - public bool? ShowRankingScore { get; set; } - - /// - /// Gets or sets showRankingScoreDetails parameter. It defines whether details on how the ranking score was computed are returned or not. - /// - [JsonPropertyName("showRankingScoreDetails")] - public bool? ShowRankingScoreDetails { get; set; } - // pagination: /// diff --git a/src/Meilisearch/SearchQueryBase.cs b/src/Meilisearch/SearchQueryBase.cs new file mode 100644 index 00000000..7b9e8163 --- /dev/null +++ b/src/Meilisearch/SearchQueryBase.cs @@ -0,0 +1,113 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Meilisearch +{ + /// + /// Base properties of Search Query + /// + public class SearchQueryBase + { + /// + /// The id of the index + /// + [JsonPropertyName("indexUid")] + public string IndexUid { get; set; } + + /// + /// Gets or sets query string. + /// + [JsonPropertyName("q")] + public string Q { get; set; } + + /// + /// Gets or sets the filter to apply to the query. + /// + [JsonPropertyName("filter")] + public dynamic Filter { get; set; } + + /// + /// Gets or sets attributes to retrieve. + /// + [JsonPropertyName("attributesToRetrieve")] + public IEnumerable AttributesToRetrieve { get; set; } + + /// + /// Gets or sets attributes to crop. + /// + [JsonPropertyName("attributesToCrop")] + public IEnumerable AttributesToCrop { get; set; } + + /// + /// Gets or sets attributes to search on. + /// + [JsonPropertyName("attributesToSearchOn")] + public IEnumerable AttributesToSearchOn { get; set; } + + /// + /// Gets or sets length used to crop field values. + /// + [JsonPropertyName("cropLength")] + public int? CropLength { get; set; } + + /// + /// Gets or sets attributes to highlight. + /// + [JsonPropertyName("attributesToHighlight")] + public IEnumerable AttributesToHighlight { get; set; } + + /// + /// Gets or sets the crop marker to apply before and/or after cropped part selected within an attribute defined in `attributesToCrop` parameter. + /// + [JsonPropertyName("cropMarker")] + public string CropMarker { get; set; } + + /// + /// Gets or sets the tag to put before the highlighted query terms. + /// + [JsonPropertyName("highlightPreTag")] + public string HighlightPreTag { get; set; } + + /// + /// Gets or sets the tag to put after the highlighted query terms. + /// + [JsonPropertyName("highlightPostTag")] + public string HighlightPostTag { get; set; } + + /// + /// Gets or sets the facets for the query. + /// + [JsonPropertyName("facets")] + public IEnumerable Facets { get; set; } + + /// + /// Gets or sets showMatchesPosition. It defines whether an object that contains information about the matches should be returned or not. + /// + [JsonPropertyName("showMatchesPosition")] + public bool? ShowMatchesPosition { get; set; } + + /// + /// Gets or sets the sorted attributes. + /// + [JsonPropertyName("sort")] + public IEnumerable Sort { get; set; } + + /// + /// Gets or sets the words matching strategy. + /// + [JsonPropertyName("matchingStrategy")] + public string MatchingStrategy { get; set; } + + /// + /// Gets or sets showRankingScore parameter. It defines wheter the global ranking score of a document (between 0 and 1) is returned or not. + /// + [JsonPropertyName("showRankingScore")] + public bool? ShowRankingScore { get; set; } + + /// + /// Gets or sets showRankingScoreDetails parameter. It defines whether details on how the ranking score was computed are returned or not. + /// + [JsonPropertyName("showRankingScoreDetails")] + public bool? ShowRankingScoreDetails { get; set; } + } +} diff --git a/tests/Meilisearch.Tests/MultiIndexSearchTests.cs b/tests/Meilisearch.Tests/MultiIndexSearchTests.cs index 02f68ab5..38c7dfad 100644 --- a/tests/Meilisearch.Tests/MultiIndexSearchTests.cs +++ b/tests/Meilisearch.Tests/MultiIndexSearchTests.cs @@ -32,7 +32,8 @@ public async Task InitializeAsync() _index2 = await _fixture.SetUpBasicIndex("BasicIndex-MultiSearch-Index2"); var t1 = _index1.UpdateFilterableAttributesAsync(new[] { "genre" }); var t2 = _index2.UpdateFilterableAttributesAsync(new[] { "genre" }); - await Task.WhenAll((await Task.WhenAll(t1, t2)).Select(x => _fixture.DefaultClient.WaitForTaskAsync(x.TaskUid))); + await Task.WhenAll( + (await Task.WhenAll(t1, t2)).Select(x => _fixture.DefaultClient.WaitForTaskAsync(x.TaskUid))); } [Fact] @@ -41,7 +42,7 @@ public async Task BasicSearch() var result = await _fixture.DefaultClient.MultiSearchAsync(new MultiSearchQuery() { Queries = new System.Collections.Generic.List() - { + { new SearchQuery() { IndexUid = _index1.Uid, Q = "", Filter = "genre = 'SF'" }, new SearchQuery() { IndexUid = _index2.Uid, Q = "", Filter = "genre = 'Action'" } } @@ -78,5 +79,150 @@ Movie GetMovie(IEnumerable movies, string id) return og.Name == x.Name && og.Genre == x.Genre; }).Should().BeTrue(); } + + + [Fact] + public async Task FederatedSearchWithNoFederationOptions() + { + var result = await _fixture.DefaultClient.FederatedMultiSearchAsync( + new FederatedMultiSearchQuery() + { + Queries = new List() + { + new FederatedSearchQuery() { IndexUid = _index1.Uid, Q = "", Filter = "genre = 'SF'" }, + new FederatedSearchQuery() { IndexUid = _index2.Uid, Q = "", Filter = "genre = 'Action'" } + }, + }); + + + Movie GetMovie(IEnumerable movies, string id) + { + return movies.FirstOrDefault(x => x.Id == id); + } + + var original1 = await _index1.GetDocumentsAsync(); + var originalHits1 = original1.Results; + result.Hits.Should().HaveCount(4); + var res1 = result.Hits.ToList()[0]; + // res1.IndexUid.Should().Be(_index1.Uid); + // var res1Hits = res1.Hits.Select(x => x.Deserialize(Constants.JsonSerializerOptionsWriteNulls)); + // res1Hits.Should().HaveCount(2); + // res1Hits.All(x => + // { + // var og = GetMovie(originalHits1, x.Id); + // return og.Name == x.Name && og.Genre == x.Genre; + // }).Should().BeTrue(); + // + // var original2 = await _index2.GetDocumentsAsync(); + // var originalHits2 = original2.Results.ToList(); + // var res2 = result.Results[1]; + // var res2Hits = res2.Hits.Select(x => x.Deserialize(Constants.JsonSerializerOptionsWriteNulls)); + // res2Hits.Should().HaveCount(2); + // res2.IndexUid.Should().Be(_index2.Uid); + // res1Hits.All(x => + // { + // var og = GetMovie(originalHits2, x.Id); + // return og.Name == x.Name && og.Genre == x.Genre; + // }).Should().BeTrue(); + } + + [Fact] + public async Task FederatedSearchWithEmptyOptions() + { + var result = await _fixture.DefaultClient.FederatedMultiSearchAsync( + new FederatedMultiSearchQuery() + { + Queries = new List() + { + new FederatedSearchQuery() { IndexUid = _index1.Uid, Q = "", Filter = "genre = 'SF'" }, + new FederatedSearchQuery() { IndexUid = _index2.Uid, Q = "", Filter = "genre = 'Action'" } + }, + FederationOptions = new MultiSearchFederationOptions() + { + + } + }); + + + Movie GetMovie(IEnumerable movies, string id) + { + return movies.FirstOrDefault(x => x.Id == id); + } + + var original1 = await _index1.GetDocumentsAsync(); + var originalHits1 = original1.Results; + result.Hits.Should().HaveCount(4); + var res1 = result.Hits.ToList()[0]; + // res1.IndexUid.Should().Be(_index1.Uid); + // var res1Hits = res1.Hits.Select(x => x.Deserialize(Constants.JsonSerializerOptionsWriteNulls)); + // res1Hits.Should().HaveCount(2); + // res1Hits.All(x => + // { + // var og = GetMovie(originalHits1, x.Id); + // return og.Name == x.Name && og.Genre == x.Genre; + // }).Should().BeTrue(); + // + // var original2 = await _index2.GetDocumentsAsync(); + // var originalHits2 = original2.Results.ToList(); + // var res2 = result.Results[1]; + // var res2Hits = res2.Hits.Select(x => x.Deserialize(Constants.JsonSerializerOptionsWriteNulls)); + // res2Hits.Should().HaveCount(2); + // res2.IndexUid.Should().Be(_index2.Uid); + // res1Hits.All(x => + // { + // var og = GetMovie(originalHits2, x.Id); + // return og.Name == x.Name && og.Genre == x.Genre; + // }).Should().BeTrue(); + } + + [Fact] + public async Task FederatedSearchWithLimitAndOffset() + { + var result = await _fixture.DefaultClient.FederatedMultiSearchAsync( + new FederatedMultiSearchQuery() + { + Queries = new List() + { + new FederatedSearchQuery() { IndexUid = _index1.Uid, Q = "", Filter = "genre = 'SF'" }, + new FederatedSearchQuery() { IndexUid = _index2.Uid, Q = "", Filter = "genre = 'Action'" } + }, + FederationOptions = new MultiSearchFederationOptions() + { + Limit = 2, + Offset = 0 + } + }); + + + Movie GetMovie(IEnumerable movies, string id) + { + return movies.FirstOrDefault(x => x.Id == id); + } + + var original1 = await _index1.GetDocumentsAsync(); + var originalHits1 = original1.Results; + result.Hits.Should().HaveCount(2); + var res1 = result.Hits.ToList()[0]; + // res1.IndexUid.Should().Be(_index1.Uid); + // var res1Hits = res1.Hits.Select(x => x.Deserialize(Constants.JsonSerializerOptionsWriteNulls)); + // res1Hits.Should().HaveCount(2); + // res1Hits.All(x => + // { + // var og = GetMovie(originalHits1, x.Id); + // return og.Name == x.Name && og.Genre == x.Genre; + // }).Should().BeTrue(); + // + // var original2 = await _index2.GetDocumentsAsync(); + // var originalHits2 = original2.Results.ToList(); + // var res2 = result.Results[1]; + // var res2Hits = res2.Hits.Select(x => x.Deserialize(Constants.JsonSerializerOptionsWriteNulls)); + // res2Hits.Should().HaveCount(2); + // res2.IndexUid.Should().Be(_index2.Uid); + // res1Hits.All(x => + // { + // var og = GetMovie(originalHits2, x.Id); + // return og.Name == x.Name && og.Genre == x.Genre; + // }).Should().BeTrue(); + } } } From b50817bc231fa28301aa8dc6124375ea969d791b Mon Sep 17 00:00:00 2001 From: TebbeM Date: Wed, 16 Oct 2024 09:43:34 +0200 Subject: [PATCH 2/5] remove commented code in tests --- src/Meilisearch/Constants.cs | 11 ++- src/Meilisearch/MeilisearchClient.cs | 2 +- .../MultiIndexSearchTests.cs | 87 ------------------- 3 files changed, 11 insertions(+), 89 deletions(-) diff --git a/src/Meilisearch/Constants.cs b/src/Meilisearch/Constants.cs index 32216d29..bb9cd504 100644 --- a/src/Meilisearch/Constants.cs +++ b/src/Meilisearch/Constants.cs @@ -13,13 +13,22 @@ internal static class Constants /// /// JsonSerializer options used when serializing objects that needs to remove null values. /// - internal static readonly JsonSerializerOptions JsonSerializerOptionsRemoveNulls = new JsonSerializerOptions + internal static readonly JsonSerializerOptions FederatedSearchJsonSerializerOptionsRemoveNulls = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, Converters = { new MultiSearchFederationOptionsConverter() } }; + /// + /// JsonSerializer options used when serializing objects that needs to remove null values. + /// + internal static readonly JsonSerializerOptions JsonSerializerOptionsRemoveNulls = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + /// /// JsonSerializer options used when serializing objects that keeps null values. /// diff --git a/src/Meilisearch/MeilisearchClient.cs b/src/Meilisearch/MeilisearchClient.cs index 74a66ed9..23521d74 100644 --- a/src/Meilisearch/MeilisearchClient.cs +++ b/src/Meilisearch/MeilisearchClient.cs @@ -92,7 +92,7 @@ public async Task> FederatedMultiSearchAsync(FederatedMultiSea } var responseMessage = await _http.PostAsJsonAsync("multi-search", query, - Constants.JsonSerializerOptionsRemoveNulls, cancellationToken: cancellationToken); + Constants.FederatedSearchJsonSerializerOptionsRemoveNulls, cancellationToken: cancellationToken); return await responseMessage.Content .ReadFromJsonAsync>(cancellationToken: cancellationToken) .ConfigureAwait(false); diff --git a/tests/Meilisearch.Tests/MultiIndexSearchTests.cs b/tests/Meilisearch.Tests/MultiIndexSearchTests.cs index 38c7dfad..81a7adef 100644 --- a/tests/Meilisearch.Tests/MultiIndexSearchTests.cs +++ b/tests/Meilisearch.Tests/MultiIndexSearchTests.cs @@ -94,36 +94,7 @@ public async Task FederatedSearchWithNoFederationOptions() }, }); - - Movie GetMovie(IEnumerable movies, string id) - { - return movies.FirstOrDefault(x => x.Id == id); - } - - var original1 = await _index1.GetDocumentsAsync(); - var originalHits1 = original1.Results; result.Hits.Should().HaveCount(4); - var res1 = result.Hits.ToList()[0]; - // res1.IndexUid.Should().Be(_index1.Uid); - // var res1Hits = res1.Hits.Select(x => x.Deserialize(Constants.JsonSerializerOptionsWriteNulls)); - // res1Hits.Should().HaveCount(2); - // res1Hits.All(x => - // { - // var og = GetMovie(originalHits1, x.Id); - // return og.Name == x.Name && og.Genre == x.Genre; - // }).Should().BeTrue(); - // - // var original2 = await _index2.GetDocumentsAsync(); - // var originalHits2 = original2.Results.ToList(); - // var res2 = result.Results[1]; - // var res2Hits = res2.Hits.Select(x => x.Deserialize(Constants.JsonSerializerOptionsWriteNulls)); - // res2Hits.Should().HaveCount(2); - // res2.IndexUid.Should().Be(_index2.Uid); - // res1Hits.All(x => - // { - // var og = GetMovie(originalHits2, x.Id); - // return og.Name == x.Name && og.Genre == x.Genre; - // }).Should().BeTrue(); } [Fact] @@ -139,40 +110,10 @@ public async Task FederatedSearchWithEmptyOptions() }, FederationOptions = new MultiSearchFederationOptions() { - } }); - - Movie GetMovie(IEnumerable movies, string id) - { - return movies.FirstOrDefault(x => x.Id == id); - } - - var original1 = await _index1.GetDocumentsAsync(); - var originalHits1 = original1.Results; result.Hits.Should().HaveCount(4); - var res1 = result.Hits.ToList()[0]; - // res1.IndexUid.Should().Be(_index1.Uid); - // var res1Hits = res1.Hits.Select(x => x.Deserialize(Constants.JsonSerializerOptionsWriteNulls)); - // res1Hits.Should().HaveCount(2); - // res1Hits.All(x => - // { - // var og = GetMovie(originalHits1, x.Id); - // return og.Name == x.Name && og.Genre == x.Genre; - // }).Should().BeTrue(); - // - // var original2 = await _index2.GetDocumentsAsync(); - // var originalHits2 = original2.Results.ToList(); - // var res2 = result.Results[1]; - // var res2Hits = res2.Hits.Select(x => x.Deserialize(Constants.JsonSerializerOptionsWriteNulls)); - // res2Hits.Should().HaveCount(2); - // res2.IndexUid.Should().Be(_index2.Uid); - // res1Hits.All(x => - // { - // var og = GetMovie(originalHits2, x.Id); - // return og.Name == x.Name && og.Genre == x.Genre; - // }).Should().BeTrue(); } [Fact] @@ -193,36 +134,8 @@ public async Task FederatedSearchWithLimitAndOffset() } }); - - Movie GetMovie(IEnumerable movies, string id) - { - return movies.FirstOrDefault(x => x.Id == id); - } - - var original1 = await _index1.GetDocumentsAsync(); - var originalHits1 = original1.Results; result.Hits.Should().HaveCount(2); var res1 = result.Hits.ToList()[0]; - // res1.IndexUid.Should().Be(_index1.Uid); - // var res1Hits = res1.Hits.Select(x => x.Deserialize(Constants.JsonSerializerOptionsWriteNulls)); - // res1Hits.Should().HaveCount(2); - // res1Hits.All(x => - // { - // var og = GetMovie(originalHits1, x.Id); - // return og.Name == x.Name && og.Genre == x.Genre; - // }).Should().BeTrue(); - // - // var original2 = await _index2.GetDocumentsAsync(); - // var originalHits2 = original2.Results.ToList(); - // var res2 = result.Results[1]; - // var res2Hits = res2.Hits.Select(x => x.Deserialize(Constants.JsonSerializerOptionsWriteNulls)); - // res2Hits.Should().HaveCount(2); - // res2.IndexUid.Should().Be(_index2.Uid); - // res1Hits.All(x => - // { - // var og = GetMovie(originalHits2, x.Id); - // return og.Name == x.Name && og.Genre == x.Genre; - // }).Should().BeTrue(); } } } From 1597f9c057ec230992973689997b162485047d1f Mon Sep 17 00:00:00 2001 From: TebbeM Date: Wed, 16 Oct 2024 09:44:27 +0200 Subject: [PATCH 3/5] remove unused code --- tests/Meilisearch.Tests/MultiIndexSearchTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Meilisearch.Tests/MultiIndexSearchTests.cs b/tests/Meilisearch.Tests/MultiIndexSearchTests.cs index 81a7adef..324c9d6c 100644 --- a/tests/Meilisearch.Tests/MultiIndexSearchTests.cs +++ b/tests/Meilisearch.Tests/MultiIndexSearchTests.cs @@ -135,7 +135,6 @@ public async Task FederatedSearchWithLimitAndOffset() }); result.Hits.Should().HaveCount(2); - var res1 = result.Hits.ToList()[0]; } } } From b9566c501600dde2d908815f21ebc311bdacfbb7 Mon Sep 17 00:00:00 2001 From: TebbeM Date: Thu, 17 Oct 2024 07:37:28 +0200 Subject: [PATCH 4/5] change function and class descriptions, removed some comments and made the code more readable --- src/Meilisearch/Constants.cs | 16 +++++----- .../AlwaysIncludeEmptyObjectConverter.cs | 30 ++++++++++++------- src/Meilisearch/FederatedMultiSearchQuery.cs | 5 ++-- src/Meilisearch/FederatedSearchQuery.cs | 4 +-- src/Meilisearch/MeilisearchClient.cs | 8 ++--- src/Meilisearch/SearchQueryBase.cs | 4 +-- 6 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/Meilisearch/Constants.cs b/src/Meilisearch/Constants.cs index bb9cd504..c558fe0a 100644 --- a/src/Meilisearch/Constants.cs +++ b/src/Meilisearch/Constants.cs @@ -13,12 +13,13 @@ internal static class Constants /// /// JsonSerializer options used when serializing objects that needs to remove null values. /// - internal static readonly JsonSerializerOptions FederatedSearchJsonSerializerOptionsRemoveNulls = new JsonSerializerOptions - { - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - Converters = { new MultiSearchFederationOptionsConverter() } - }; + internal static readonly JsonSerializerOptions FederatedSearchJsonSerializerOptionsRemoveNulls = + new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + Converters = { new MultiSearchFederationOptionsConverter() } + }; /// /// JsonSerializer options used when serializing objects that needs to remove null values. @@ -34,8 +35,7 @@ internal static class Constants /// internal static readonly JsonSerializerOptions JsonSerializerOptionsWriteNulls = new JsonSerializerOptions { - DefaultIgnoreCondition = JsonIgnoreCondition.Never, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DefaultIgnoreCondition = JsonIgnoreCondition.Never, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, }; internal static string VersionErrorHintMessage(string message, string method) diff --git a/src/Meilisearch/Converters/AlwaysIncludeEmptyObjectConverter.cs b/src/Meilisearch/Converters/AlwaysIncludeEmptyObjectConverter.cs index d85cfba1..40ef2073 100644 --- a/src/Meilisearch/Converters/AlwaysIncludeEmptyObjectConverter.cs +++ b/src/Meilisearch/Converters/AlwaysIncludeEmptyObjectConverter.cs @@ -7,7 +7,8 @@ namespace Meilisearch.Converters { /// - /// Always include Property in json objects will be serialized as "{}" + /// Always include property in json. MultiSearchFederationOptions will be serialized as "{}" + /// /// /// public class MultiSearchFederationOptionsConverter : JsonConverter @@ -23,21 +24,30 @@ public override void Write(Utf8JsonWriter writer, MultiSearchFederationOptions v { if (value == null || !HasAnyValueSet(value)) { - // Write an empty object if the value is null - writer.WriteStartObject(); - writer.WriteEndObject(); + WriteEmptyObject(writer); } else { - var newOptions = new JsonSerializerOptions(options); - newOptions.Converters.Remove(newOptions.Converters.First(c => - c.GetType() == typeof(MultiSearchFederationOptionsConverter))); - - // Serialize the value as usual - JsonSerializer.Serialize(writer, value, newOptions); + var sanitizedOptions = + RemoveSelfFromSerializerOptions(options); //Prevents getting stuck in a loop during serialization + JsonSerializer.Serialize(writer, value, sanitizedOptions); } } + private static JsonSerializerOptions RemoveSelfFromSerializerOptions(JsonSerializerOptions options) + { + var sanitizedOptions = new JsonSerializerOptions(options); + sanitizedOptions.Converters.Remove(sanitizedOptions.Converters.First(c => + c.GetType() == typeof(MultiSearchFederationOptionsConverter))); + return sanitizedOptions; + } + + private static void WriteEmptyObject(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + writer.WriteEndObject(); + } + private bool HasAnyValueSet(MultiSearchFederationOptions value) { foreach (var property in diff --git a/src/Meilisearch/FederatedMultiSearchQuery.cs b/src/Meilisearch/FederatedMultiSearchQuery.cs index 1b5f5dc7..35e57af3 100644 --- a/src/Meilisearch/FederatedMultiSearchQuery.cs +++ b/src/Meilisearch/FederatedMultiSearchQuery.cs @@ -10,9 +10,8 @@ namespace Meilisearch /// public class FederatedMultiSearchQuery { - /// - /// Default Constructor that ensures FederationOptions are always set + /// Default constructor that ensures FederationOptions are always set /// public FederatedMultiSearchQuery() { @@ -26,7 +25,7 @@ public FederatedMultiSearchQuery() public List Queries { get; set; } /// - /// If present and not null, returns a single list merging all search results across all specified queries + /// The federated search query options /// [JsonInclude] [JsonPropertyName("federation")] diff --git a/src/Meilisearch/FederatedSearchQuery.cs b/src/Meilisearch/FederatedSearchQuery.cs index beaec24d..45a24fbd 100644 --- a/src/Meilisearch/FederatedSearchQuery.cs +++ b/src/Meilisearch/FederatedSearchQuery.cs @@ -3,12 +3,12 @@ namespace Meilisearch { /// - /// Search Query for federated Multisearch + /// Search query for federated multi-index search /// public class FederatedSearchQuery : SearchQueryBase { /// - /// Federation Options + /// Federated search options /// [JsonPropertyName("federationOptions")] public MultiSearchFederationOptions FederationOptions { get; set; } diff --git a/src/Meilisearch/MeilisearchClient.cs b/src/Meilisearch/MeilisearchClient.cs index 23521d74..6196641e 100644 --- a/src/Meilisearch/MeilisearchClient.cs +++ b/src/Meilisearch/MeilisearchClient.cs @@ -77,11 +77,11 @@ public Index Index(string uid) } /// - /// Searches multiple indexes at once but get a aggregated result + /// Searches multiple indexes at once but gets an aggregated list of results. /// - /// The queries to be executed (must have IndexUid set) + /// The query to be executed (must have at least one query inside) /// - /// Aggregated results + /// Aggregated results. /// public async Task> FederatedMultiSearchAsync(FederatedMultiSearchQuery query, CancellationToken cancellationToken = default) @@ -99,7 +99,7 @@ public async Task> FederatedMultiSearchAsync(FederatedMultiSea } /// - /// Searches multiple indexes at once + /// Searches multiple indexes at once. /// /// The queries to be executed (must have IndexUid set) /// diff --git a/src/Meilisearch/SearchQueryBase.cs b/src/Meilisearch/SearchQueryBase.cs index 7b9e8163..ca2ce0c1 100644 --- a/src/Meilisearch/SearchQueryBase.cs +++ b/src/Meilisearch/SearchQueryBase.cs @@ -4,7 +4,7 @@ namespace Meilisearch { /// - /// Base properties of Search Query + /// Base properties of search query /// public class SearchQueryBase { @@ -99,7 +99,7 @@ public class SearchQueryBase public string MatchingStrategy { get; set; } /// - /// Gets or sets showRankingScore parameter. It defines wheter the global ranking score of a document (between 0 and 1) is returned or not. + /// Gets or sets showRankingScore parameter. It defines whether the global ranking score of a document (between 0 and 1) is returned or not. /// [JsonPropertyName("showRankingScore")] public bool? ShowRankingScore { get; set; } From 1ff060e71695e5be8c6ccab1964f589636632dfe Mon Sep 17 00:00:00 2001 From: TebbeM Date: Thu, 17 Oct 2024 10:22:53 +0200 Subject: [PATCH 5/5] run dotnet format --- src/Meilisearch/Constants.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Meilisearch/Constants.cs b/src/Meilisearch/Constants.cs index c558fe0a..19d5ba0a 100644 --- a/src/Meilisearch/Constants.cs +++ b/src/Meilisearch/Constants.cs @@ -35,7 +35,8 @@ internal static class Constants /// internal static readonly JsonSerializerOptions JsonSerializerOptionsWriteNulls = new JsonSerializerOptions { - DefaultIgnoreCondition = JsonIgnoreCondition.Never, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DefaultIgnoreCondition = JsonIgnoreCondition.Never, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, }; internal static string VersionErrorHintMessage(string message, string method)