From a12fc5fd95f00941e5078b43422aa8908abd2225 Mon Sep 17 00:00:00 2001 From: Thomas Farr Date: Wed, 14 Aug 2024 02:47:58 +1200 Subject: [PATCH] Add support for indices.stats (#753) * Add support for indices.stats Signed-off-by: Thomas Farr * Add changelog entry Signed-off-by: Thomas Farr * Fix tests Signed-off-by: Thomas Farr * Fix another test Signed-off-by: Thomas Farr * Fix more tests Signed-off-by: Thomas Farr --------- Signed-off-by: Thomas Farr (cherry picked from commit 43ba0de9099c3bce9eeb95344c46db666af9c434) --- CHANGELOG.md | 1 + .../Configuration/CodeConfiguration.cs | 3 +- .../Endpoints/IndicesStatsOverrides.cs | 41 - src/OpenSearch.Client/ApiUrlsLookup.cs | 1 - .../Indices/Stats/IndicesStatsRequest.cs | 22 + .../Indices/Stats/IndicesStatsResponse.cs | 244 ++++++ .../_Generated/ApiUrlsLookup.cs | 3 + .../_Generated/Descriptors.Indices.cs | 104 +++ .../_Generated/OpenSearchClient.Indices.cs | 51 ++ .../_Generated/Requests.Indices.cs | 113 +++ src/OpenSearch.Net/Api/Enums.cs | 21 - .../RequestParameters.Indices.cs | 69 -- .../OpenSearchLowLevelClient.Indices.cs | 44 -- src/OpenSearch.Net/_Generated/Api/Enums.cs | 26 + .../RequestParameters.Indices.cs | 74 ++ .../OpenSearchLowLevelClient.Indices.cs | 121 +++ .../NodeSeeders/DefaultSeeder.cs | 18 +- .../ClusterReroute/ClusterRerouteApiTests.cs | 2 +- .../TaskManagement/GetTask/GetTaskApiTests.cs | 4 +- .../TasksList/TasksListApiTests.cs | 2 +- .../DeleteByQuery/DeleteByQueryApiTests.cs | 3 +- .../PutMapping/PutMappingApiTest.cs | 698 +++++++++--------- .../Indices/Stats/IndicesStatsApiTests.cs | 66 ++ .../Indices/Stats/IndicesStatsUrlsTests.cs | 49 ++ .../Specialized/Knn/KnnVectorPropertyTests.cs | 137 ++-- .../Percolate/PercolateQueryUsageTests.cs | 6 +- 26 files changed, 1325 insertions(+), 598 deletions(-) delete mode 100644 src/ApiGenerator/Configuration/Overrides/Endpoints/IndicesStatsOverrides.cs create mode 100644 src/OpenSearch.Client/Indices/Stats/IndicesStatsRequest.cs create mode 100644 src/OpenSearch.Client/Indices/Stats/IndicesStatsResponse.cs create mode 100644 tests/Tests/Indices/Stats/IndicesStatsApiTests.cs create mode 100644 tests/Tests/Indices/Stats/IndicesStatsUrlsTests.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 07c8a51a9b..d95df663ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Added support for `MinScore` on `ScriptScoreQuery` ([#624](https://github.com/opensearch-project/opensearch-net/pull/624)) - Added support for serializing the `DateOnly` and `TimeOnly` types ([#734](https://github.com/opensearch-project/opensearch-net/pull/734)) - Added support for the `Ext` parameter on `SearchRequest` ([#738](https://github.com/opensearch-project/opensearch-net/pull/738)) +- Added support for the `Indices.Stats` API ([#753](https://github.com/opensearch-project/opensearch-net/pull/753)) ### Dependencies - Bumps `AWSSDK.Core` from 3.7.204.12 to 3.7.400.4 diff --git a/src/ApiGenerator/Configuration/CodeConfiguration.cs b/src/ApiGenerator/Configuration/CodeConfiguration.cs index 067caec522..1c3a954582 100644 --- a/src/ApiGenerator/Configuration/CodeConfiguration.cs +++ b/src/ApiGenerator/Configuration/CodeConfiguration.cs @@ -44,7 +44,8 @@ public static class CodeConfiguration new("cat.{all_pit,pit}_segments"), new("cat.segment_replication"), new("cluster.{delete,exists,get,put}_component_template"), - new("indices.{delete,exists,get,put}_index_template") + new("indices.{delete,exists,get,put}_index_template"), + new("indices.stats") }; public static bool IncludeOperation(string name) => OperationsToInclude.Any(g => g.IsMatch(name)); diff --git a/src/ApiGenerator/Configuration/Overrides/Endpoints/IndicesStatsOverrides.cs b/src/ApiGenerator/Configuration/Overrides/Endpoints/IndicesStatsOverrides.cs deleted file mode 100644 index bb14a30b68..0000000000 --- a/src/ApiGenerator/Configuration/Overrides/Endpoints/IndicesStatsOverrides.cs +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 -* -* The OpenSearch Contributors require contributions made to -* this file be licensed under the Apache-2.0 license or a -* compatible open source license. -*/ -/* -* Modifications Copyright OpenSearch Contributors. See -* GitHub history for details. -* -* Licensed to Elasticsearch B.V. under one or more contributor -* license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright -* ownership. Elasticsearch B.V. licenses this file to you under -* the Apache License, Version 2.0 (the "License"); you may -* not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, -* software distributed under the License is distributed on an -* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -* KIND, either express or implied. See the License for the -* specific language governing permissions and limitations -* under the License. -*/ - -using System.Collections.Generic; - -namespace ApiGenerator.Configuration.Overrides.Endpoints -{ - // ReSharper disable once UnusedMember.Global - public class IndicesStatsOverrides : EndpointOverridesBase - { - public override IEnumerable SkipQueryStringParams => new[] - { - "types" - }; - } -} diff --git a/src/OpenSearch.Client/ApiUrlsLookup.cs b/src/OpenSearch.Client/ApiUrlsLookup.cs index 6336f9b211..a7441c9e65 100644 --- a/src/OpenSearch.Client/ApiUrlsLookup.cs +++ b/src/OpenSearch.Client/ApiUrlsLookup.cs @@ -118,7 +118,6 @@ internal static partial class ApiUrlsLookups internal static ApiUrls IndicesShardStores = new ApiUrls(new[]{"_shard_stores", "{index}/_shard_stores"}); internal static ApiUrls IndicesShrink = new ApiUrls(new[]{"{index}/_shrink/{target}"}); internal static ApiUrls IndicesSplit = new ApiUrls(new[]{"{index}/_split/{target}"}); - internal static ApiUrls IndicesStats = new ApiUrls(new[]{"_stats", "_stats/{metric}", "{index}/_stats", "{index}/_stats/{metric}"}); internal static ApiUrls IndicesBulkAlias = new ApiUrls(new[]{"_aliases"}); internal static ApiUrls IndicesValidateQuery = new ApiUrls(new[]{"_validate/query", "{index}/_validate/query"}); internal static ApiUrls NoNamespaceRootNodeInfo = new ApiUrls(new[]{""}); diff --git a/src/OpenSearch.Client/Indices/Stats/IndicesStatsRequest.cs b/src/OpenSearch.Client/Indices/Stats/IndicesStatsRequest.cs new file mode 100644 index 0000000000..906beed0f3 --- /dev/null +++ b/src/OpenSearch.Client/Indices/Stats/IndicesStatsRequest.cs @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: Apache-2.0 +* +* The OpenSearch Contributors require contributions made to +* this file be licensed under the Apache-2.0 license or a +* compatible open source license. +*/ + +namespace OpenSearch.Client; + +[MapsApi("indices.stats")] +[ReadAs(typeof(IndicesStatsRequest))] +public partial interface IIndicesStatsRequest +{ +} + +public partial class IndicesStatsRequest +{ +} + +public partial class IndicesStatsDescriptor +{ +} diff --git a/src/OpenSearch.Client/Indices/Stats/IndicesStatsResponse.cs b/src/OpenSearch.Client/Indices/Stats/IndicesStatsResponse.cs new file mode 100644 index 0000000000..545df60e18 --- /dev/null +++ b/src/OpenSearch.Client/Indices/Stats/IndicesStatsResponse.cs @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: Apache-2.0 +* +* The OpenSearch Contributors require contributions made to +* this file be licensed under the Apache-2.0 license or a +* compatible open source license. +*/ + +using System.Collections.Generic; +using System.Runtime.Serialization; +using OpenSearch.Net; +using OpenSearch.Net.Utf8Json; + +namespace OpenSearch.Client; + +[DataContract] +public class IndicesStatsResponse : ResponseBase +{ + [DataMember(Name = "_all")] + public AllIndicesStats All { get; internal set; } + + [DataMember(Name = "_shards")] + public ShardStatistics Shards { get; internal set; } + + [DataMember(Name = "indices")] + public IndicesStatsDictionary Indices { get; internal set; } +} + +[JsonFormatter(typeof(Converter))] +public class IndicesStatsDictionary : ResolvableDictionaryProxy +{ + private IndicesStatsDictionary(IConnectionConfigurationValues s, IReadOnlyDictionary d) + : base(s, d) { } + + private class Converter : ResolvableDictionaryFormatterBase + { + protected override IndicesStatsDictionary Create(IConnectionSettingsValues s, Dictionary d) => new(s, d); + } +} + +[DataContract] +public class AllIndicesStats +{ + [DataMember(Name = "primaries")] + public IndexStats Primaries { get; internal set; } + + [DataMember(Name = "total")] + public IndexStats Total { get; internal set; } +} + +[DataContract] +public class IndicesStats +{ + [DataMember(Name = "uuid")] + public string Uuid { get; internal set; } + + [DataMember(Name = "primaries")] + public IndexStats Primaries { get; internal set; } + + [DataMember(Name = "total")] + public IndexStats Total { get; internal set; } + + [DataMember(Name = "shards")] + public IReadOnlyDictionary> Shards { get; internal set; } +} + +[DataContract] +public abstract class IndexStatsBase +{ + [DataMember(Name = "docs")] + public DocStats Documents { get; internal set; } + + [DataMember(Name = "store")] + public StoreStats Store { get; internal set; } + + [DataMember(Name = "indexing")] + public IndexingStats Indexing { get; internal set; } + + [DataMember(Name = "get")] + public GetStats Get { get; internal set; } + + [DataMember(Name = "search")] + public SearchStats Search { get; internal set; } + + [DataMember(Name = "merges")] + public MergesStats Merges { get; internal set; } + + [DataMember(Name = "refresh")] + public RefreshStats Refresh { get; internal set; } + + [DataMember(Name = "flush")] + public FlushStats Flush { get; internal set; } + + [DataMember(Name = "warmer")] + public WarmerStats Warmer { get; internal set; } + + [DataMember(Name = "query_cache")] + public QueryCacheStats QueryCache { get; internal set; } + + [DataMember(Name = "fielddata")] + public FielddataStats Fielddata { get; internal set; } + + [DataMember(Name = "completion")] + public CompletionStats Completion { get; internal set; } + + [DataMember(Name = "segments")] + public SegmentsStats Segments { get; internal set; } + + [DataMember(Name = "translog")] + public TranslogStats Translog { get; internal set; } + + [DataMember(Name = "request_cache")] + public RequestCacheStats RequestCache { get; internal set; } + + [DataMember(Name = "recovery")] + public RecoveryStats Recovery { get; internal set; } +} + +[DataContract] +public class IndexStats : IndexStatsBase +{ + +} + +[DataContract] +public class IndexShardStats : IndexStatsBase +{ + [DataMember(Name = "routing")] + public ShardRouting Routing { get; internal set; } + + [DataMember(Name = "commit")] + public ShardCommitStats Commit { get; internal set; } + + [DataMember(Name = "seq_no")] + public ShardSequenceNumberStats SequenceNumber { get; internal set; } + + [DataMember(Name = "retention_leases")] + public ShardRetentionLeasesStats RetentionLeases { get; internal set; } + + [DataMember(Name = "shard_path")] + public ShardPath ShardPath { get; internal set; } +} + +[DataContract] +public class ShardRouting +{ + [DataMember(Name = "state")] + public ShardRoutingState State { get; internal set; } + + [DataMember(Name = "primary")] + public bool Primary { get; internal set; } + + [DataMember(Name = "node")] + public string Node { get; internal set; } + + [DataMember(Name = "relocating_node")] + public string RelocatingNode { get; internal set; } +} + +[StringEnum] +public enum ShardRoutingState +{ + [EnumMember(Value = "INITIALIZING")] + Initializing, + + [EnumMember(Value = "RELOCATING")] + Relocating, + + [EnumMember(Value = "STARTED")] + Started, + + [EnumMember(Value = "UNASSIGNED")] + Unassigned +} + +[DataContract] +public class ShardCommitStats +{ + [DataMember(Name = "id")] + public string Id { get; internal set; } + + [DataMember(Name = "generation")] + public long Generation { get; internal set; } + + [DataMember(Name = "num_docs")] + public int NumDocs { get; internal set; } + + [DataMember(Name = "user_data")] + public IReadOnlyDictionary UserData { get; internal set; } +} + +[DataContract] +public class ShardSequenceNumberStats +{ + [DataMember(Name = "max_seq_no")] + public long MaxSequenceNumber { get; internal set; } + + [DataMember(Name = "local_checkpoint")] + public long LocalCheckpoint { get; internal set; } + + [DataMember(Name = "global_checkpoint")] + public long GlobalCheckpoint { get; internal set; } +} + +[DataContract] +public class ShardRetentionLeasesStats +{ + [DataMember(Name = "primary_term")] + public long PrimaryTerm { get; internal set; } + + [DataMember(Name = "version")] + public long Version { get; internal set; } + + [DataMember(Name = "leases")] + public IReadOnlyCollection Leases { get; internal set; } +} + +[DataContract] +public class ShardRetentionLease +{ + [DataMember(Name = "id")] + public string Id { get; internal set; } + + [DataMember(Name = "retaining_seq_no")] + public long RetainingSequenceNumber { get; internal set; } + + [DataMember(Name = "timestamp")] + public long Timestamp { get; internal set; } + + [DataMember(Name = "source")] + public string Source { get; internal set; } +} + +[DataContract] +public class ShardPath +{ + [DataMember(Name = "state_path")] + public string StatePath { get; internal set; } + + [DataMember(Name = "data_path")] + public string DataPath { get; internal set; } + + [DataMember(Name = "is_custom_data_path")] + public bool IsCustomDataPath { get; internal set; } +} diff --git a/src/OpenSearch.Client/_Generated/ApiUrlsLookup.cs b/src/OpenSearch.Client/_Generated/ApiUrlsLookup.cs index 5b80ccb84a..9d021a30da 100644 --- a/src/OpenSearch.Client/_Generated/ApiUrlsLookup.cs +++ b/src/OpenSearch.Client/_Generated/ApiUrlsLookup.cs @@ -88,5 +88,8 @@ internal static partial class ApiUrlsLookups internal static readonly ApiUrls IndicesPutComposableTemplate = new(new[] { "_index_template/{name}" }); + + internal static readonly ApiUrls IndicesStats = + new(new[] { "_stats", "{index}/_stats", "{index}/_stats/{metric}", "_stats/{metric}" }); } } diff --git a/src/OpenSearch.Client/_Generated/Descriptors.Indices.cs b/src/OpenSearch.Client/_Generated/Descriptors.Indices.cs index 7caf232bfa..a22c8cfd75 100644 --- a/src/OpenSearch.Client/_Generated/Descriptors.Indices.cs +++ b/src/OpenSearch.Client/_Generated/Descriptors.Indices.cs @@ -241,4 +241,108 @@ public PutComposableIndexTemplateDescriptor Create(bool? create = true) => public PutComposableIndexTemplateDescriptor MasterTimeout(Time mastertimeout) => Qs("master_timeout", mastertimeout); } + + /// Descriptor for Stats https://opensearch.org/docs/latest + public partial class IndicesStatsDescriptor + : RequestDescriptorBase< + IndicesStatsDescriptor, + IndicesStatsRequestParameters, + IIndicesStatsRequest + >, + IIndicesStatsRequest + { + internal override ApiUrls ApiUrls => ApiUrlsLookups.IndicesStats; + + /// /_stats + public IndicesStatsDescriptor() + : base() { } + + /// /{index}/_stats + /// Optional, accepts null + public IndicesStatsDescriptor(Indices index) + : base(r => r.Optional("index", index)) { } + + /// /{index}/_stats/{metric} + /// Optional, accepts null + /// Optional, accepts null + public IndicesStatsDescriptor(Indices index, Metrics metric) + : base(r => r.Optional("index", index).Optional("metric", metric)) { } + + /// /_stats/{metric} + /// Optional, accepts null + public IndicesStatsDescriptor(Metrics metric) + : base(r => r.Optional("metric", metric)) { } + + // values part of the url path + Indices IIndicesStatsRequest.Index => Self.RouteValues.Get("index"); + Metrics IIndicesStatsRequest.Metric => Self.RouteValues.Get("metric"); + + /// A comma-separated list of index names; use the special string `_all` or Indices.All to perform the operation on all indices. + public IndicesStatsDescriptor Index(Indices index) => + Assign(index, (a, v) => a.RouteValues.Optional("index", v)); + + /// a shortcut into calling Index(typeof(TOther)) + public IndicesStatsDescriptor Index() + where TOther : class => + Assign(typeof(TOther), (a, v) => a.RouteValues.Optional("index", (Indices)v)); + + /// A shortcut into calling Index(Indices.All) + public IndicesStatsDescriptor AllIndices() => Index(Indices.All); + + /// Limit the information returned the specific metrics. + public IndicesStatsDescriptor Metric(Metrics metric) => + Assign(metric, (a, v) => a.RouteValues.Optional("metric", v)); + + // Request parameters + /// Comma-separated list or wildcard expressions of fields to include in fielddata and suggest statistics. + public IndicesStatsDescriptor CompletionFields(Fields completionfields) => + Qs("completion_fields", completionfields); + + /// Comma-separated list or wildcard expressions of fields to include in fielddata and suggest statistics. + public IndicesStatsDescriptor CompletionFields( + params Expression>[] fields + ) + where T : class => Qs("completion_fields", fields?.Select(e => (Field)e)); + + /// Type of index that wildcard patterns can match. If the request can target data streams, this argument determines whether wildcard expressions match hidden data streams. Supports comma-separated values, such as `open,hidden`. + public IndicesStatsDescriptor ExpandWildcards(ExpandWildcards? expandwildcards) => + Qs("expand_wildcards", expandwildcards); + + /// Comma-separated list or wildcard expressions of fields to include in fielddata statistics. + public IndicesStatsDescriptor FielddataFields(Fields fielddatafields) => + Qs("fielddata_fields", fielddatafields); + + /// Comma-separated list or wildcard expressions of fields to include in fielddata statistics. + public IndicesStatsDescriptor FielddataFields( + params Expression>[] fields + ) + where T : class => Qs("fielddata_fields", fields?.Select(e => (Field)e)); + + /// Comma-separated list or wildcard expressions of fields to include in the statistics. + public IndicesStatsDescriptor Fields(Fields fields) => Qs("fields", fields); + + /// Comma-separated list or wildcard expressions of fields to include in the statistics. + public IndicesStatsDescriptor Fields(params Expression>[] fields) + where T : class => Qs("fields", fields?.Select(e => (Field)e)); + + /// If true, statistics are not collected from closed indices. + public IndicesStatsDescriptor ForbidClosedIndices(bool? forbidclosedindices = true) => + Qs("forbid_closed_indices", forbidclosedindices); + + /// Comma-separated list of search groups to include in the search statistics. + public IndicesStatsDescriptor Groups(params string[] groups) => Qs("groups", groups); + + /// If true, the call reports the aggregated disk usage of each one of the Lucene index files (only applies if segment stats are requested). + public IndicesStatsDescriptor IncludeSegmentFileSizes( + bool? includesegmentfilesizes = true + ) => Qs("include_segment_file_sizes", includesegmentfilesizes); + + /// If true, the response includes information from segments that are not loaded into memory. + public IndicesStatsDescriptor IncludeUnloadedSegments( + bool? includeunloadedsegments = true + ) => Qs("include_unloaded_segments", includeunloadedsegments); + + /// Indicates whether statistics are aggregated at the cluster, index, or shard level. + public IndicesStatsDescriptor Level(Level? level) => Qs("level", level); + } } diff --git a/src/OpenSearch.Client/_Generated/OpenSearchClient.Indices.cs b/src/OpenSearch.Client/_Generated/OpenSearchClient.Indices.cs index 283cdf697a..8071764e71 100644 --- a/src/OpenSearch.Client/_Generated/OpenSearchClient.Indices.cs +++ b/src/OpenSearch.Client/_Generated/OpenSearchClient.Indices.cs @@ -306,5 +306,56 @@ public Task PutComposableTemplateAsync( request.RequestParameters, ct ); + + /// + /// GET request to the indices.stats API, read more about this API online: + /// + /// https://opensearch.org/docs/latest + /// + public IndicesStatsResponse Stats( + Indices index = null, + Func selector = null + ) => Stats(selector.InvokeOrDefault(new IndicesStatsDescriptor().Index(index: index))); + + /// + /// GET request to the indices.stats API, read more about this API online: + /// + /// https://opensearch.org/docs/latest + /// + public Task StatsAsync( + Indices index = null, + Func selector = null, + CancellationToken ct = default + ) => + StatsAsync( + selector.InvokeOrDefault(new IndicesStatsDescriptor().Index(index: index)), + ct + ); + + /// + /// GET request to the indices.stats API, read more about this API online: + /// + /// https://opensearch.org/docs/latest + /// + public IndicesStatsResponse Stats(IIndicesStatsRequest request) => + DoRequest( + request, + request.RequestParameters + ); + + /// + /// GET request to the indices.stats API, read more about this API online: + /// + /// https://opensearch.org/docs/latest + /// + public Task StatsAsync( + IIndicesStatsRequest request, + CancellationToken ct = default + ) => + DoRequestAsync( + request, + request.RequestParameters, + ct + ); } } diff --git a/src/OpenSearch.Client/_Generated/Requests.Indices.cs b/src/OpenSearch.Client/_Generated/Requests.Indices.cs index a4fd840358..ff12e59c76 100644 --- a/src/OpenSearch.Client/_Generated/Requests.Indices.cs +++ b/src/OpenSearch.Client/_Generated/Requests.Indices.cs @@ -317,4 +317,117 @@ public Time MasterTimeout set => Q("master_timeout", value); } } + + [InterfaceDataContract] + public partial interface IIndicesStatsRequest : IRequest + { + [IgnoreDataMember] + Indices Index { get; } + + [IgnoreDataMember] + Metrics Metric { get; } + } + + /// Request for Stats https://opensearch.org/docs/latest + public partial class IndicesStatsRequest + : PlainRequestBase, + IIndicesStatsRequest + { + protected IIndicesStatsRequest Self => this; + internal override ApiUrls ApiUrls => ApiUrlsLookups.IndicesStats; + + /// /_stats + public IndicesStatsRequest() + : base() { } + + /// /{index}/_stats + /// Optional, accepts null + public IndicesStatsRequest(Indices index) + : base(r => r.Optional("index", index)) { } + + /// /{index}/_stats/{metric} + /// Optional, accepts null + /// Optional, accepts null + public IndicesStatsRequest(Indices index, Metrics metric) + : base(r => r.Optional("index", index).Optional("metric", metric)) { } + + /// /_stats/{metric} + /// Optional, accepts null + public IndicesStatsRequest(Metrics metric) + : base(r => r.Optional("metric", metric)) { } + + // values part of the url path + [IgnoreDataMember] + Indices IIndicesStatsRequest.Index => Self.RouteValues.Get("index"); + + [IgnoreDataMember] + Metrics IIndicesStatsRequest.Metric => Self.RouteValues.Get("metric"); + + // Request parameters + /// Comma-separated list or wildcard expressions of fields to include in fielddata and suggest statistics. + public Fields CompletionFields + { + get => Q("completion_fields"); + set => Q("completion_fields", value); + } + + /// + /// Type of index that wildcard patterns can match. If the request can target data streams, this argument determines whether wildcard + /// expressions match hidden data streams. Supports comma-separated values, such as `open,hidden`. + /// + public ExpandWildcards? ExpandWildcards + { + get => Q("expand_wildcards"); + set => Q("expand_wildcards", value); + } + + /// Comma-separated list or wildcard expressions of fields to include in fielddata statistics. + public Fields FielddataFields + { + get => Q("fielddata_fields"); + set => Q("fielddata_fields", value); + } + + /// Comma-separated list or wildcard expressions of fields to include in the statistics. + public Fields Fields + { + get => Q("fields"); + set => Q("fields", value); + } + + /// If true, statistics are not collected from closed indices. + public bool? ForbidClosedIndices + { + get => Q("forbid_closed_indices"); + set => Q("forbid_closed_indices", value); + } + + /// Comma-separated list of search groups to include in the search statistics. + public string[] Groups + { + get => Q("groups"); + set => Q("groups", value); + } + + /// If true, the call reports the aggregated disk usage of each one of the Lucene index files (only applies if segment stats are requested). + public bool? IncludeSegmentFileSizes + { + get => Q("include_segment_file_sizes"); + set => Q("include_segment_file_sizes", value); + } + + /// If true, the response includes information from segments that are not loaded into memory. + public bool? IncludeUnloadedSegments + { + get => Q("include_unloaded_segments"); + set => Q("include_unloaded_segments", value); + } + + /// Indicates whether statistics are aggregated at the cluster, index, or shard level. + public Level? Level + { + get => Q("level"); + set => Q("level", value); + } + } } diff --git a/src/OpenSearch.Net/Api/Enums.cs b/src/OpenSearch.Net/Api/Enums.cs index 8b28badad8..708e33253c 100644 --- a/src/OpenSearch.Net/Api/Enums.cs +++ b/src/OpenSearch.Net/Api/Enums.cs @@ -269,17 +269,6 @@ public enum Size P } - [StringEnum] - public enum Level - { - [EnumMember(Value = "cluster")] - Cluster, - [EnumMember(Value = "indices")] - Indices, - [EnumMember(Value = "shards")] - Shards - } - [StringEnum] public enum WaitForEvents { @@ -408,7 +397,6 @@ static KnownEnums() AddEnumStringResolver(GetStringValue); AddEnumStringResolver(GetStringValue); AddEnumStringResolver(GetStringValue); - AddEnumStringResolver(GetStringValue); AddEnumStringResolver(GetStringValue); AddEnumStringResolver(GetStringValue); AddEnumStringResolver(GetStringValue); @@ -649,15 +637,6 @@ public static string GetStringValue(this Size enumValue) => _ => throw new ArgumentException($"'{enumValue.ToString()}' is not a valid value for enum 'Size'") }; - public static string GetStringValue(this Level enumValue) => - enumValue switch - { - Level.Cluster => "cluster", - Level.Indices => "indices", - Level.Shards => "shards", - _ => throw new ArgumentException($"'{enumValue.ToString()}' is not a valid value for enum 'Level'") - }; - public static string GetStringValue(this WaitForEvents enumValue) => enumValue switch { diff --git a/src/OpenSearch.Net/Api/RequestParameters/RequestParameters.Indices.cs b/src/OpenSearch.Net/Api/RequestParameters/RequestParameters.Indices.cs index 50907638f9..481a349126 100644 --- a/src/OpenSearch.Net/Api/RequestParameters/RequestParameters.Indices.cs +++ b/src/OpenSearch.Net/Api/RequestParameters/RequestParameters.Indices.cs @@ -1772,75 +1772,6 @@ public string WaitForActiveShards } } - ///Request options for Stats https://opensearch.org/docs/latest/opensearch/stats-api/ - public class IndicesStatsRequestParameters : RequestParameters - { - public override HttpMethod DefaultHttpMethod => HttpMethod.GET; - public override bool SupportsBody => false; - ///A comma-separated list of fields for `fielddata` and `suggest` index metric (supports wildcards) - public string[] CompletionFields - { - get => Q("completion_fields"); - set => Q("completion_fields", value); - } - - ///Whether to expand wildcard expression to concrete indices that are open, closed or both. - public ExpandWildcards? ExpandWildcards - { - get => Q("expand_wildcards"); - set => Q("expand_wildcards", value); - } - - ///A comma-separated list of fields for `fielddata` index metric (supports wildcards) - public string[] FielddataFields - { - get => Q("fielddata_fields"); - set => Q("fielddata_fields", value); - } - - ///A comma-separated list of fields for `fielddata` and `completion` index metric (supports wildcards) - public string[] Fields - { - get => Q("fields"); - set => Q("fields", value); - } - - ///If set to false stats will also collected from closed indices if explicitly specified or if expand_wildcards expands to closed indices - public bool? ForbidClosedIndices - { - get => Q("forbid_closed_indices"); - set => Q("forbid_closed_indices", value); - } - - ///A comma-separated list of search groups for `search` index metric - public string[] Groups - { - get => Q("groups"); - set => Q("groups", value); - } - - ///Whether to report the aggregated disk usage of each one of the Lucene index files (only applies if segment stats are requested) - public bool? IncludeSegmentFileSizes - { - get => Q("include_segment_file_sizes"); - set => Q("include_segment_file_sizes", value); - } - - ///If set to true segment stats will include stats for segments that are not currently loaded into memory - public bool? IncludeUnloadedSegments - { - get => Q("include_unloaded_segments"); - set => Q("include_unloaded_segments", value); - } - - ///Return stats aggregated at cluster, index or shard level - public Level? Level - { - get => Q("level"); - set => Q("level", value); - } - } - ///Request options for BulkAlias https://opensearch.org/docs/latest/opensearch/rest-api/alias/ public class BulkAliasRequestParameters : RequestParameters { diff --git a/src/OpenSearch.Net/OpenSearchLowLevelClient.Indices.cs b/src/OpenSearch.Net/OpenSearchLowLevelClient.Indices.cs index f788ad1693..6d1a653bf2 100644 --- a/src/OpenSearch.Net/OpenSearchLowLevelClient.Indices.cs +++ b/src/OpenSearch.Net/OpenSearchLowLevelClient.Indices.cs @@ -785,50 +785,6 @@ public TResponse Split(string index, string target, PostData body, Sp [MapsApi("indices.split", "index, target, body")] public Task SplitAsync(string index, string target, PostData body, SplitIndexRequestParameters requestParameters = null, CancellationToken ctx = default) where TResponse : class, IOpenSearchResponse, new() => DoRequestAsync(PUT, Url($"{index:index}/_split/{target:target}"), ctx, body, RequestParams(requestParameters)); - ///GET on /_stats https://opensearch.org/docs/latest/opensearch/stats-api/ - ///Request specific configuration such as querystring parameters & request specific connection settings. - public TResponse StatsForAll(IndicesStatsRequestParameters requestParameters = null) - where TResponse : class, IOpenSearchResponse, new() => DoRequest(GET, "_stats", null, RequestParams(requestParameters)); - ///GET on /_stats https://opensearch.org/docs/latest/opensearch/stats-api/ - ///Request specific configuration such as querystring parameters & request specific connection settings. - [MapsApi("indices.stats", "")] - public Task StatsForAllAsync(IndicesStatsRequestParameters requestParameters = null, CancellationToken ctx = default) - where TResponse : class, IOpenSearchResponse, new() => DoRequestAsync(GET, "_stats", ctx, null, RequestParams(requestParameters)); - ///GET on /_stats/{metric} https://opensearch.org/docs/latest/opensearch/stats-api/ - ///Limit the information returned the specific metrics. - ///Request specific configuration such as querystring parameters & request specific connection settings. - public TResponse StatsForAll(string metric, IndicesStatsRequestParameters requestParameters = null) - where TResponse : class, IOpenSearchResponse, new() => DoRequest(GET, Url($"_stats/{metric:metric}"), null, RequestParams(requestParameters)); - ///GET on /_stats/{metric} https://opensearch.org/docs/latest/opensearch/stats-api/ - ///Limit the information returned the specific metrics. - ///Request specific configuration such as querystring parameters & request specific connection settings. - [MapsApi("indices.stats", "metric")] - public Task StatsForAllAsync(string metric, IndicesStatsRequestParameters requestParameters = null, CancellationToken ctx = default) - where TResponse : class, IOpenSearchResponse, new() => DoRequestAsync(GET, Url($"_stats/{metric:metric}"), ctx, null, RequestParams(requestParameters)); - ///GET on /{index}/_stats https://opensearch.org/docs/latest/opensearch/stats-api/ - ///A comma-separated list of index names; use the special string `_all` or Indices.All to perform the operation on all indices - ///Request specific configuration such as querystring parameters & request specific connection settings. - public TResponse Stats(string index, IndicesStatsRequestParameters requestParameters = null) - where TResponse : class, IOpenSearchResponse, new() => DoRequest(GET, Url($"{index:index}/_stats"), null, RequestParams(requestParameters)); - ///GET on /{index}/_stats https://opensearch.org/docs/latest/opensearch/stats-api/ - ///A comma-separated list of index names; use the special string `_all` or Indices.All to perform the operation on all indices - ///Request specific configuration such as querystring parameters & request specific connection settings. - [MapsApi("indices.stats", "index")] - public Task StatsAsync(string index, IndicesStatsRequestParameters requestParameters = null, CancellationToken ctx = default) - where TResponse : class, IOpenSearchResponse, new() => DoRequestAsync(GET, Url($"{index:index}/_stats"), ctx, null, RequestParams(requestParameters)); - ///GET on /{index}/_stats/{metric} https://opensearch.org/docs/latest/opensearch/stats-api/ - ///A comma-separated list of index names; use the special string `_all` or Indices.All to perform the operation on all indices - ///Limit the information returned the specific metrics. - ///Request specific configuration such as querystring parameters & request specific connection settings. - public TResponse Stats(string index, string metric, IndicesStatsRequestParameters requestParameters = null) - where TResponse : class, IOpenSearchResponse, new() => DoRequest(GET, Url($"{index:index}/_stats/{metric:metric}"), null, RequestParams(requestParameters)); - ///GET on /{index}/_stats/{metric} https://opensearch.org/docs/latest/opensearch/stats-api/ - ///A comma-separated list of index names; use the special string `_all` or Indices.All to perform the operation on all indices - ///Limit the information returned the specific metrics. - ///Request specific configuration such as querystring parameters & request specific connection settings. - [MapsApi("indices.stats", "index, metric")] - public Task StatsAsync(string index, string metric, IndicesStatsRequestParameters requestParameters = null, CancellationToken ctx = default) - where TResponse : class, IOpenSearchResponse, new() => DoRequestAsync(GET, Url($"{index:index}/_stats/{metric:metric}"), ctx, null, RequestParams(requestParameters)); ///POST on /_aliases https://opensearch.org/docs/latest/opensearch/rest-api/alias/ ///The definition of `actions` to perform ///Request specific configuration such as querystring parameters & request specific connection settings. diff --git a/src/OpenSearch.Net/_Generated/Api/Enums.cs b/src/OpenSearch.Net/_Generated/Api/Enums.cs index 4d6b5f99f4..90b8a319f3 100644 --- a/src/OpenSearch.Net/_Generated/Api/Enums.cs +++ b/src/OpenSearch.Net/_Generated/Api/Enums.cs @@ -108,6 +108,19 @@ public enum ExpandWildcards Open = 1 << 4 } + [StringEnum] + public enum Level + { + [EnumMember(Value = "cluster")] + Cluster, + + [EnumMember(Value = "indices")] + Indices, + + [EnumMember(Value = "shards")] + Shards + } + [StringEnum] public enum TimeUnit { @@ -139,6 +152,7 @@ static partial void RegisterEnumStringResolvers() { AddEnumStringResolver(GetStringValue); AddEnumStringResolver(GetStringValue); + AddEnumStringResolver(GetStringValue); AddEnumStringResolver(GetStringValue); } @@ -178,6 +192,18 @@ public static string GetStringValue(this ExpandWildcards enumValue) return string.Join(",", list); } + public static string GetStringValue(this Level enumValue) => + enumValue switch + { + Level.Cluster => "cluster", + Level.Indices => "indices", + Level.Shards => "shards", + _ + => throw new ArgumentException( + $"'{enumValue.ToString()}' is not a valid value for enum 'Level'" + ) + }; + public static string GetStringValue(this TimeUnit enumValue) => enumValue switch { diff --git a/src/OpenSearch.Net/_Generated/Api/RequestParameters/RequestParameters.Indices.cs b/src/OpenSearch.Net/_Generated/Api/RequestParameters/RequestParameters.Indices.cs index e3a2850b14..cf2e13ba8a 100644 --- a/src/OpenSearch.Net/_Generated/Api/RequestParameters/RequestParameters.Indices.cs +++ b/src/OpenSearch.Net/_Generated/Api/RequestParameters/RequestParameters.Indices.cs @@ -216,4 +216,78 @@ public TimeSpan MasterTimeout set => Q("master_timeout", value); } } + + /// Request options for Stats https://opensearch.org/docs/latest + public partial class IndicesStatsRequestParameters + : RequestParameters + { + public override HttpMethod DefaultHttpMethod => HttpMethod.GET; + public override bool SupportsBody => false; + + /// Comma-separated list or wildcard expressions of fields to include in fielddata and suggest statistics. + public string[] CompletionFields + { + get => Q("completion_fields"); + set => Q("completion_fields", value); + } + + /// + /// Type of index that wildcard patterns can match. If the request can target data streams, this argument determines whether wildcard + /// expressions match hidden data streams. Supports comma-separated values, such as `open,hidden`. + /// + public ExpandWildcards? ExpandWildcards + { + get => Q("expand_wildcards"); + set => Q("expand_wildcards", value); + } + + /// Comma-separated list or wildcard expressions of fields to include in fielddata statistics. + public string[] FielddataFields + { + get => Q("fielddata_fields"); + set => Q("fielddata_fields", value); + } + + /// Comma-separated list or wildcard expressions of fields to include in the statistics. + public string[] Fields + { + get => Q("fields"); + set => Q("fields", value); + } + + /// If true, statistics are not collected from closed indices. + public bool? ForbidClosedIndices + { + get => Q("forbid_closed_indices"); + set => Q("forbid_closed_indices", value); + } + + /// Comma-separated list of search groups to include in the search statistics. + public string[] Groups + { + get => Q("groups"); + set => Q("groups", value); + } + + /// If true, the call reports the aggregated disk usage of each one of the Lucene index files (only applies if segment stats are requested). + public bool? IncludeSegmentFileSizes + { + get => Q("include_segment_file_sizes"); + set => Q("include_segment_file_sizes", value); + } + + /// If true, the response includes information from segments that are not loaded into memory. + public bool? IncludeUnloadedSegments + { + get => Q("include_unloaded_segments"); + set => Q("include_unloaded_segments", value); + } + + /// Indicates whether statistics are aggregated at the cluster, index, or shard level. + public Level? Level + { + get => Q("level"); + set => Q("level", value); + } + } } diff --git a/src/OpenSearch.Net/_Generated/OpenSearchLowLevelClient.Indices.cs b/src/OpenSearch.Net/_Generated/OpenSearchLowLevelClient.Indices.cs index a9a60148f7..1811e068c4 100644 --- a/src/OpenSearch.Net/_Generated/OpenSearchLowLevelClient.Indices.cs +++ b/src/OpenSearch.Net/_Generated/OpenSearchLowLevelClient.Indices.cs @@ -228,5 +228,126 @@ public Task PutComposableTemplateForAllAsync( body, RequestParams(requestParameters) ); + + /// GET on /_stats https://opensearch.org/docs/latest + /// Request specific configuration such as querystring parameters & request specific connection settings. + public TResponse StatsForAll( + IndicesStatsRequestParameters requestParameters = null + ) + where TResponse : class, IOpenSearchResponse, new() => + DoRequest(GET, "_stats", null, RequestParams(requestParameters)); + + /// GET on /_stats https://opensearch.org/docs/latest + /// Request specific configuration such as querystring parameters & request specific connection settings. + [MapsApi("indices.stats", "")] + public Task StatsForAllAsync( + IndicesStatsRequestParameters requestParameters = null, + CancellationToken ctx = default + ) + where TResponse : class, IOpenSearchResponse, new() => + DoRequestAsync(GET, "_stats", ctx, null, RequestParams(requestParameters)); + + /// GET on /{index}/_stats https://opensearch.org/docs/latest + /// A comma-separated list of index names; use the special string `_all` or Indices.All to perform the operation on all indices. + /// Request specific configuration such as querystring parameters & request specific connection settings. + public TResponse Stats( + string index, + IndicesStatsRequestParameters requestParameters = null + ) + where TResponse : class, IOpenSearchResponse, new() => + DoRequest( + GET, + Url($"{index:index}/_stats"), + null, + RequestParams(requestParameters) + ); + + /// GET on /{index}/_stats https://opensearch.org/docs/latest + /// A comma-separated list of index names; use the special string `_all` or Indices.All to perform the operation on all indices. + /// Request specific configuration such as querystring parameters & request specific connection settings. + [MapsApi("indices.stats", "index")] + public Task StatsAsync( + string index, + IndicesStatsRequestParameters requestParameters = null, + CancellationToken ctx = default + ) + where TResponse : class, IOpenSearchResponse, new() => + DoRequestAsync( + GET, + Url($"{index:index}/_stats"), + ctx, + null, + RequestParams(requestParameters) + ); + + /// GET on /{index}/_stats/{metric} https://opensearch.org/docs/latest + /// A comma-separated list of index names; use the special string `_all` or Indices.All to perform the operation on all indices. + /// Limit the information returned the specific metrics. + /// Request specific configuration such as querystring parameters & request specific connection settings. + public TResponse Stats( + string index, + string metric, + IndicesStatsRequestParameters requestParameters = null + ) + where TResponse : class, IOpenSearchResponse, new() => + DoRequest( + GET, + Url($"{index:index}/_stats/{metric:metric}"), + null, + RequestParams(requestParameters) + ); + + /// GET on /{index}/_stats/{metric} https://opensearch.org/docs/latest + /// A comma-separated list of index names; use the special string `_all` or Indices.All to perform the operation on all indices. + /// Limit the information returned the specific metrics. + /// Request specific configuration such as querystring parameters & request specific connection settings. + [MapsApi("indices.stats", "index, metric")] + public Task StatsAsync( + string index, + string metric, + IndicesStatsRequestParameters requestParameters = null, + CancellationToken ctx = default + ) + where TResponse : class, IOpenSearchResponse, new() => + DoRequestAsync( + GET, + Url($"{index:index}/_stats/{metric:metric}"), + ctx, + null, + RequestParams(requestParameters) + ); + + /// GET on /_stats/{metric} https://opensearch.org/docs/latest + /// Limit the information returned the specific metrics. + /// Request specific configuration such as querystring parameters & request specific connection settings. + public TResponse StatsForAll( + string metric, + IndicesStatsRequestParameters requestParameters = null + ) + where TResponse : class, IOpenSearchResponse, new() => + DoRequest( + GET, + Url($"_stats/{metric:metric}"), + null, + RequestParams(requestParameters) + ); + + /// GET on /_stats/{metric} https://opensearch.org/docs/latest + /// Limit the information returned the specific metrics. + /// Request specific configuration such as querystring parameters & request specific connection settings. + [MapsApi("indices.stats", "metric")] + public Task StatsForAllAsync( + string metric, + IndicesStatsRequestParameters requestParameters = null, + CancellationToken ctx = default + ) + where TResponse : class, IOpenSearchResponse, new() => + DoRequestAsync( + GET, + Url($"_stats/{metric:metric}"), + ctx, + null, + RequestParams(requestParameters) + ); } } diff --git a/tests/Tests.Core/ManagedOpenSearch/NodeSeeders/DefaultSeeder.cs b/tests/Tests.Core/ManagedOpenSearch/NodeSeeders/DefaultSeeder.cs index c766f1cd3f..f87ea48a94 100644 --- a/tests/Tests.Core/ManagedOpenSearch/NodeSeeders/DefaultSeeder.cs +++ b/tests/Tests.Core/ManagedOpenSearch/NodeSeeders/DefaultSeeder.cs @@ -220,10 +220,7 @@ private Task CreateDeveloperIndexAsync() => Client.Indices. #pragma warning disable 618 private Task CreateProjectIndexAsync() => Client.Indices.CreateAsync(typeof(Project), c => c - .Settings(settings => settings - .Analysis(ProjectAnalysisSettings) - .Setting("index.knn", true) - .Setting("index.knn.algo_param.ef_search", 100)) + .Settings(ProjectIndexSettings) .Mappings(ProjectMappings) .Aliases(aliases => aliases .Alias(ProjectsAliasName) @@ -264,6 +261,12 @@ public static ITypeMapping ProjectTypeMappings(TypeMappingDescriptor ma return mapping; } + public static IndexSettingsDescriptor ProjectIndexSettings(IndexSettingsDescriptor settings) => + settings + .Analysis(ProjectAnalysisSettings) + .Setting("index.knn", true) + .Setting("index.knn.algo_param.ef_search", 100); + public static IAnalysis ProjectAnalysisSettings(AnalysisDescriptor analysis) { analysis @@ -287,12 +290,11 @@ public static IAnalysis ProjectAnalysisSettings(AnalysisDescriptor analysis) return analysis; } + public static IndexSettingsDescriptor PercolatorIndexSettings(IndexSettingsDescriptor settings) => + ProjectIndexSettings(settings).AutoExpandReplicas("0-all"); private Task CreatePercolatorIndexAsync() => Client.Indices.CreateAsync(typeof(ProjectPercolation), c => c - .Settings(s => s - .AutoExpandReplicas("0-all") - .Analysis(ProjectAnalysisSettings) - ) + .Settings(PercolatorIndexSettings) .Map(m => m .AutoMap() .Properties(PercolatedQueryProperties) diff --git a/tests/Tests/Cluster/ClusterReroute/ClusterRerouteApiTests.cs b/tests/Tests/Cluster/ClusterReroute/ClusterRerouteApiTests.cs index 82aea6cecd..f81c0c3c6f 100644 --- a/tests/Tests/Cluster/ClusterReroute/ClusterRerouteApiTests.cs +++ b/tests/Tests/Cluster/ClusterReroute/ClusterRerouteApiTests.cs @@ -52,7 +52,7 @@ protected override void IntegrationSetup(IOpenSearchClient client, CallUniqueVal foreach (var (_, index) in values) { var createIndex = client.Indices.Create(index, i => i - .Settings(settings => settings.Analysis(DefaultSeeder.ProjectAnalysisSettings)) + .Settings(DefaultSeeder.ProjectIndexSettings) .Map(DefaultSeeder.ProjectTypeMappings) ); createIndex.ShouldBeValid(); diff --git a/tests/Tests/Cluster/TaskManagement/GetTask/GetTaskApiTests.cs b/tests/Tests/Cluster/TaskManagement/GetTask/GetTaskApiTests.cs index f016434645..b2f8cc472e 100644 --- a/tests/Tests/Cluster/TaskManagement/GetTask/GetTaskApiTests.cs +++ b/tests/Tests/Cluster/TaskManagement/GetTask/GetTaskApiTests.cs @@ -89,7 +89,7 @@ protected override void IntegrationSetup(IOpenSearchClient client, CallUniqueVal throw new Exception("failure in setting up integration"); var createIndex = client.Indices.Create(targetIndex, i => i - .Settings(settings => settings.Analysis(DefaultSeeder.ProjectAnalysisSettings)) + .Settings(DefaultSeeder.ProjectIndexSettings) .Map(DefaultSeeder.ProjectTypeMappings) ); createIndex.ShouldBeValid(); @@ -169,7 +169,7 @@ protected override void IntegrationSetup(IOpenSearchClient client, CallUniqueVal throw new Exception($"failure in setting up integration for {nameof(GetTaskApiCompletedTaskTests)}. {bulkResponse.DebugInformation}"); var createIndex = client.Indices.Create(targetIndex, i => i - .Settings(settings => settings.Analysis(DefaultSeeder.ProjectAnalysisSettings)) + .Settings(DefaultSeeder.ProjectIndexSettings) .Map(DefaultSeeder.ProjectTypeMappings) ); createIndex.ShouldBeValid(); diff --git a/tests/Tests/Cluster/TaskManagement/TasksList/TasksListApiTests.cs b/tests/Tests/Cluster/TaskManagement/TasksList/TasksListApiTests.cs index 1129f90ba6..9b629ed7c2 100644 --- a/tests/Tests/Cluster/TaskManagement/TasksList/TasksListApiTests.cs +++ b/tests/Tests/Cluster/TaskManagement/TasksList/TasksListApiTests.cs @@ -135,7 +135,7 @@ protected override void IntegrationSetup(IOpenSearchClient client, CallUniqueVal client.Indices.Refresh(sourceIndex); var createIndex = client.Indices.Create(targetIndex, i => i - .Settings(settings => settings.Analysis(DefaultSeeder.ProjectAnalysisSettings)) + .Settings(DefaultSeeder.ProjectIndexSettings) .Map(DefaultSeeder.ProjectTypeMappings) ); createIndex.ShouldBeValid(); diff --git a/tests/Tests/Document/Multiple/DeleteByQuery/DeleteByQueryApiTests.cs b/tests/Tests/Document/Multiple/DeleteByQuery/DeleteByQueryApiTests.cs index f9cadbfc03..b76e95a835 100644 --- a/tests/Tests/Document/Multiple/DeleteByQuery/DeleteByQueryApiTests.cs +++ b/tests/Tests/Document/Multiple/DeleteByQuery/DeleteByQueryApiTests.cs @@ -98,10 +98,9 @@ protected override void IntegrationSetup(IOpenSearchClient client, CallUniqueVal foreach (var index in values.Values) { Client.Indices.Create(index, c => c - .Settings(s => s + .Settings(s => DefaultSeeder.ProjectIndexSettings(s) .NumberOfShards(2) .NumberOfReplicas(0) - .Analysis(DefaultSeeder.ProjectAnalysisSettings) ) .Map(p => p .AutoMap() diff --git a/tests/Tests/Indices/MappingManagement/PutMapping/PutMappingApiTest.cs b/tests/Tests/Indices/MappingManagement/PutMapping/PutMappingApiTest.cs index b5cf2f7d07..24817ec8de 100644 --- a/tests/Tests/Indices/MappingManagement/PutMapping/PutMappingApiTest.cs +++ b/tests/Tests/Indices/MappingManagement/PutMapping/PutMappingApiTest.cs @@ -27,7 +27,6 @@ */ using System; -using OpenSearch.OpenSearch.Xunit.XunitPlumbing; using OpenSearch.Net; using OpenSearch.Client; using Tests.Core.ManagedOpenSearch.Clusters; @@ -35,354 +34,369 @@ using Tests.Framework.EndpointTests; using Tests.Framework.EndpointTests.TestState; -namespace Tests.Indices.MappingManagement.PutMapping +namespace Tests.Indices.MappingManagement.PutMapping; + +public class PutMappingApiTests + : ApiIntegrationAgainstNewIndexTestBase + , PutMappingRequest> { - public class PutMappingApiTests - : ApiIntegrationAgainstNewIndexTestBase - , PutMappingRequest> - { - public PutMappingApiTests(WritableCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + public PutMappingApiTests(WritableCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + + protected override bool ExpectIsValid => true; + + protected override object ExpectJson { get; } = new + { + properties = new + { + branches = new + { + fields = new + { + keyword = new + { + type = "keyword", + ignore_above = 256 + } + }, + type = "text" + }, + curatedTags = new + { + properties = new + { + added = new { type = "date" }, + name = new { type = "text" } + }, + type = "object" + }, + type = new { type = "text" }, + dateString = new { type = "text" }, + description = new { type = "text" }, + join = new + { + relations = new { project = "commits" }, + type = "join" + }, + lastActivity = new { type = "date" }, + leadDeveloper = new + { + properties = new + { + firstName = new { type = "text" }, + gender = new { type = "keyword" }, + id = new { type = "long" }, + ipAddress = new { type = "text" }, + jobTitle = new { type = "text" }, + lastName = new { type = "text" }, + location = new { type = "geo_point" }, + nickname = new { type = "text" }, + geoIp = new { type = "object" } + }, + type = "object" + }, + locationPoint = new + { + properties = new + { + lat = new { type = "double" }, + lon = new { type = "double" } + }, + type = "object" + }, + locationShape = new + { + type = "geo_shape" + }, + metadata = new { type = "object" }, + name = new + { + index = false, + type = "text" + }, + numberOfCommits = new { type = "integer" }, + numberOfContributors = new { type = "integer" }, + sourceOnly = new { properties = new { }, type = "object" }, + startedOn = new { type = "date" }, + state = new { type = "keyword" }, + visibility = new { type = "keyword" }, + suggest = new { type = "completion" }, + ranges = new + { + properties = new + { + dates = new { type = "date_range" }, + doubles = new { type = "double_range" }, + floats = new { type = "float_range" }, + integers = new { type = "integer_range" }, + longs = new { type = "long_range" }, + ips = new { type = "ip_range" } + }, + type = "object" + }, + requiredBranches = new + { + type = "integer" + }, + tags = new + { + properties = new + { + added = new { type = "date" }, + name = new { type = "text" } + }, + type = "object" + }, + rank = new + { + type = "rank_feature" + }, + versionControl = new + { + type = "keyword" + }, + vector = new + { + type = "knn_vector", + dimension = 2, + method = new { + name = "hnsw", + space_type = "l2", + engine = "nmslib", + parameters = new + { + ef_construction = 128, + m = 24 + } + } + } + } + }; - protected override bool ExpectIsValid => true; + protected override int ExpectStatusCode => 200; - protected override object ExpectJson { get; } = new - { - properties = new - { - branches = new - { - fields = new - { - keyword = new - { - type = "keyword", - ignore_above = 256 - } - }, - type = "text" - }, - curatedTags = new - { - properties = new - { - added = new { type = "date" }, - name = new { type = "text" } - }, - type = "object" - }, - type = new { type = "text" }, - dateString = new { type = "text" }, - description = new { type = "text" }, - join = new - { - relations = new { project = "commits" }, - type = "join" - }, - lastActivity = new { type = "date" }, - leadDeveloper = new - { - properties = new - { - firstName = new { type = "text" }, - gender = new { type = "keyword" }, - id = new { type = "long" }, - ipAddress = new { type = "text" }, - jobTitle = new { type = "text" }, - lastName = new { type = "text" }, - location = new { type = "geo_point" }, - nickname = new { type = "text" }, - geoIp = new { type = "object" } - }, - type = "object" - }, - locationPoint = new - { - properties = new - { - lat = new { type = "double" }, - lon = new { type = "double" } - }, - type = "object" - }, - locationShape = new - { - type = "geo_shape" - }, - metadata = new { type = "object" }, - name = new - { - index = false, - type = "text" - }, - numberOfCommits = new { type = "integer" }, - numberOfContributors = new { type = "integer" }, - sourceOnly = new { properties = new { }, type = "object" }, - startedOn = new { type = "date" }, - state = new { type = "keyword" }, - visibility = new { type = "keyword" }, - suggest = new { type = "completion" }, - ranges = new - { - properties = new - { - dates = new { type = "date_range" }, - doubles = new { type = "double_range" }, - floats = new { type = "float_range" }, - integers = new { type = "integer_range" }, - longs = new { type = "long_range" }, - ips = new { type = "ip_range" } - }, - type = "object" - }, - requiredBranches = new - { - type = "integer" - }, - tags = new - { - properties = new - { - added = new { type = "date" }, - name = new { type = "text" } - }, - type = "object" - }, - rank = new - { - type = "rank_feature" - }, - versionControl = new - { - type = "keyword" - }, - vector = new - { - type = "knn_vector", - dimension = 2, - method = new { - name = "hnsw", - space_type = "l2", - engine = "nmslib", - parameters = new - { - ef_construction = 128, - m = 24 - } - } - } - } - }; + protected override Func, IPutMappingRequest> Fluent => d => d + .Index(CallIsolatedValue) + .AutoMap() + .Properties(prop => prop + .Join(join => join + .Name(p => p.Join) + .Relations(relations => relations + .Join() + ) + ) + .Object(o => o + .Name(p => p.CuratedTags) + .AutoMap() + .Properties(ps => ps + .Text(t => t + .Name(tag => tag.Name) + ) + ) + ) + .Text(t => t.Name(p => p.Description)) + .Text(t => t.Name(p => p.DateString)) + .Text(t => t.Name(p => p.Type)) + .Text(s => s + .Name(p => p.Name) + .Index(false) + ) + .Object(o => o + .Name(p => p.LeadDeveloper) + .AutoMap() + .Properties(ps => ps + .Text(t => t.Name(dv => dv.FirstName)) + .Text(t => t.Name(dv => dv.IpAddress)) + .Text(t => t.Name(dv => dv.JobTitle)) + .Text(t => t.Name(dv => dv.LastName)) + .Text(t => t.Name(dv => dv.OnlineHandle)) + .Object(t => t.Name(dv => dv.GeoIp)) + ) + ) + .Object(o => o + .Name(p => p.Metadata) + ) + .Object(o => o + .AutoMap() + .Name(p => p.Tags) + .Properties(ps => ps + .Text(t => t + .Name(tag => tag.Name) + ) + ) + ) + .RankFeature(rf => rf + .Name(p => p.Rank) + ) + .Keyword(k => k + .Name(n => n.VersionControl) + ) + .KnnVector(k => k + .Name(p => p.Vector) + .Dimension(2) + .Method(m => m + .Name("hnsw") + .SpaceType("l2") + .Engine("nmslib") + .Parameters(p => p + .Parameter("ef_construction", 128) + .Parameter("m", 24) + ) + ) + ) + ); - protected override int ExpectStatusCode => 200; + protected override HttpMethod HttpMethod => HttpMethod.PUT; - protected override Func, IPutMappingRequest> Fluent => d => d - .Index(CallIsolatedValue) - .AutoMap() - .Properties(prop => prop - .Join(join => join - .Name(p => p.Join) - .Relations(relations => relations - .Join() - ) - ) - .Object(o => o - .Name(p => p.CuratedTags) - .AutoMap() - .Properties(ps => ps - .Text(t => t - .Name(tag => tag.Name) - ) - ) - ) - .Text(t => t.Name(p => p.Description)) - .Text(t => t.Name(p => p.DateString)) - .Text(t => t.Name(p => p.Type)) - .Text(s => s - .Name(p => p.Name) - .Index(false) - ) - .Object(o => o - .Name(p => p.LeadDeveloper) - .AutoMap() - .Properties(ps => ps - .Text(t => t.Name(dv => dv.FirstName)) - .Text(t => t.Name(dv => dv.IpAddress)) - .Text(t => t.Name(dv => dv.JobTitle)) - .Text(t => t.Name(dv => dv.LastName)) - .Text(t => t.Name(dv => dv.OnlineHandle)) - .Object(t => t.Name(dv => dv.GeoIp)) - ) - ) - .Object(o => o - .Name(p => p.Metadata) - ) - .Object(o => o - .AutoMap() - .Name(p => p.Tags) - .Properties(ps => ps - .Text(t => t - .Name(tag => tag.Name) - ) - ) - ) - .RankFeature(rf => rf - .Name(p => p.Rank) - ) - .Keyword(k => k - .Name(n => n.VersionControl) - ) - .KnnVector(k => k - .Name(p => p.Vector) - .Dimension(2) - .Method(m => m - .Name("hnsw") - .SpaceType("l2") - .Engine("nmslib") - .Parameters(p => p - .Parameter("ef_construction", 128) - .Parameter("m", 24) - ) - ) - ) - ); + protected override PutMappingRequest Initializer => new PutMappingRequest(CallIsolatedValue) + { + Properties = new Properties + { + { + p => p.Join, new JoinProperty + { + Relations = new Relations + { + { typeof(Project), typeof(CommitActivity) } + } + } + }, + { + p => p.Branches, new TextProperty + { + Fields = new Properties + { + { + "keyword", new KeywordProperty + { + IgnoreAbove = 256 + } + } + } + } + }, + { + p => p.CuratedTags, new ObjectProperty + { + Properties = new Properties + { + { p => p.Added, new DateProperty() }, + { p => p.Name, new TextProperty() }, + } + } + }, + { p => p.Description, new TextProperty() }, + { p => p.DateString, new TextProperty() }, + { p => p.Type, new TextProperty() }, + { p => p.LastActivity, new DateProperty() }, + { + p => p.LeadDeveloper, new ObjectProperty + { + Properties = new Properties + { + { p => p.FirstName, new TextProperty() }, + { p => p.Gender, new KeywordProperty() }, + { p => p.Id, new NumberProperty(NumberType.Long) }, + { p => p.IpAddress, new TextProperty() }, + { p => p.JobTitle, new TextProperty() }, + { p => p.LastName, new TextProperty() }, + { p => p.Location, new GeoPointProperty() }, + { p => p.OnlineHandle, new TextProperty() }, + { p => p.GeoIp, new ObjectProperty() }, + } + } + }, + { + p => p.LocationPoint, new ObjectProperty + { + Properties = new Properties + { + { p => p.Lat, new NumberProperty(NumberType.Double) }, + { p => p.Lon, new NumberProperty(NumberType.Double) }, + } + } + }, + { p => p.LocationShape, new GeoShapeProperty() }, + { p => p.Metadata, new ObjectProperty() }, + { p => p.Name, new TextProperty { Index = false } }, + { p => p.NumberOfCommits, new NumberProperty(NumberType.Integer) }, + { p => p.NumberOfContributors, new NumberProperty(NumberType.Integer) }, + { + p => p.SourceOnly, new ObjectProperty() + { + Properties = new Properties() + } + }, + { p => p.StartedOn, new DateProperty() }, + { p => p.State, new KeywordProperty() }, + { p => p.Visibility, new KeywordProperty() }, + { p => p.Suggest, new CompletionProperty() }, + { + p => p.Ranges, new ObjectProperty + { + Properties = new Properties + { + { p => p.Dates, new DateRangeProperty() }, + { p => p.Doubles, new DoubleRangeProperty() }, + { p => p.Floats, new FloatRangeProperty() }, + { p => p.Integers, new IntegerRangeProperty() }, + { p => p.Longs, new LongRangeProperty() }, + { p => p.Ips, new IpRangeProperty() }, + } + } + }, + { p => p.RequiredBranches, new NumberProperty(NumberType.Integer) }, + { + p => p.Tags, new ObjectProperty + { + Properties = new Properties + { + { p => p.Added, new DateProperty() }, + { p => p.Name, new TextProperty() }, + } + } + }, + { p => p.Rank, new RankFeatureProperty() }, + { p => p.VersionControl, new KeywordProperty() }, + { p => p.Vector, new KnnVectorProperty + { + Dimension = 2, + Method = new KnnMethod + { + Name = "hnsw", + SpaceType = "l2", + Engine = "nmslib", + Parameters = new KnnMethodParameters + { + {"ef_construction", 128}, + {"m", 24} + } + } + } } + } + }; - protected override HttpMethod HttpMethod => HttpMethod.PUT; + protected override string UrlPath => $"/{CallIsolatedValue}/_mapping"; - protected override PutMappingRequest Initializer => new PutMappingRequest(CallIsolatedValue) - { - Properties = new Properties - { - { - p => p.Join, new JoinProperty - { - Relations = new Relations - { - { typeof(Project), typeof(CommitActivity) } - } - } - }, - { - p => p.Branches, new TextProperty - { - Fields = new Properties - { - { - "keyword", new KeywordProperty - { - IgnoreAbove = 256 - } - } - } - } - }, - { - p => p.CuratedTags, new ObjectProperty - { - Properties = new Properties - { - { p => p.Added, new DateProperty() }, - { p => p.Name, new TextProperty() }, - } - } - }, - { p => p.Description, new TextProperty() }, - { p => p.DateString, new TextProperty() }, - { p => p.Type, new TextProperty() }, - { p => p.LastActivity, new DateProperty() }, - { - p => p.LeadDeveloper, new ObjectProperty - { - Properties = new Properties - { - { p => p.FirstName, new TextProperty() }, - { p => p.Gender, new KeywordProperty() }, - { p => p.Id, new NumberProperty(NumberType.Long) }, - { p => p.IpAddress, new TextProperty() }, - { p => p.JobTitle, new TextProperty() }, - { p => p.LastName, new TextProperty() }, - { p => p.Location, new GeoPointProperty() }, - { p => p.OnlineHandle, new TextProperty() }, - { p => p.GeoIp, new ObjectProperty() }, - } - } - }, - { - p => p.LocationPoint, new ObjectProperty - { - Properties = new Properties - { - { p => p.Lat, new NumberProperty(NumberType.Double) }, - { p => p.Lon, new NumberProperty(NumberType.Double) }, - } - } - }, - { p => p.LocationShape, new GeoShapeProperty() }, - { p => p.Metadata, new ObjectProperty() }, - { p => p.Name, new TextProperty { Index = false } }, - { p => p.NumberOfCommits, new NumberProperty(NumberType.Integer) }, - { p => p.NumberOfContributors, new NumberProperty(NumberType.Integer) }, - { - p => p.SourceOnly, new ObjectProperty() - { - Properties = new Properties() - } - }, - { p => p.StartedOn, new DateProperty() }, - { p => p.State, new KeywordProperty() }, - { p => p.Visibility, new KeywordProperty() }, - { p => p.Suggest, new CompletionProperty() }, - { - p => p.Ranges, new ObjectProperty - { - Properties = new Properties - { - { p => p.Dates, new DateRangeProperty() }, - { p => p.Doubles, new DoubleRangeProperty() }, - { p => p.Floats, new FloatRangeProperty() }, - { p => p.Integers, new IntegerRangeProperty() }, - { p => p.Longs, new LongRangeProperty() }, - { p => p.Ips, new IpRangeProperty() }, - } - } - }, - { p => p.RequiredBranches, new NumberProperty(NumberType.Integer) }, - { - p => p.Tags, new ObjectProperty - { - Properties = new Properties - { - { p => p.Added, new DateProperty() }, - { p => p.Name, new TextProperty() }, - } - } - }, - { p => p.Rank, new RankFeatureProperty() }, - { p => p.VersionControl, new KeywordProperty() }, - { p => p.Vector, new KnnVectorProperty - { - Dimension = 2, - Method = new KnnMethod - { - Name = "hnsw", - SpaceType = "l2", - Engine = "nmslib", - Parameters = new KnnMethodParameters - { - {"ef_construction", 128}, - {"m", 24} - } - } - } } - } - }; + protected override LazyResponses ClientUsage() => Calls( + (client, f) => client.Map(f), + (client, f) => client.MapAsync(f), + (client, r) => client.Map(r), + (client, r) => client.MapAsync(r) + ); - protected override string UrlPath => $"/{CallIsolatedValue}/_mapping"; + protected override void IntegrationSetup(IOpenSearchClient client, CallUniqueValues values) + { + foreach (var v in values.Values) + { + client.Indices.Create(v, d => d + .Settings(s => s + .Setting("index.knn", true) + .Setting("index.knn.algo_param.ef_search", 100))); + } + } - protected override LazyResponses ClientUsage() => Calls( - (client, f) => client.Map(f), - (client, f) => client.MapAsync(f), - (client, r) => client.Map(r), - (client, r) => client.MapAsync(r) - ); - } + protected override void IntegrationTeardown(IOpenSearchClient client, CallUniqueValues values) + { + foreach (var v in values.Values) client.Indices.Delete(v); + } } diff --git a/tests/Tests/Indices/Stats/IndicesStatsApiTests.cs b/tests/Tests/Indices/Stats/IndicesStatsApiTests.cs new file mode 100644 index 0000000000..a2f180b851 --- /dev/null +++ b/tests/Tests/Indices/Stats/IndicesStatsApiTests.cs @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: Apache-2.0 +* +* The OpenSearch Contributors require contributions made to +* this file be licensed under the Apache-2.0 license or a +* compatible open source license. +*/ + +using System; +using FluentAssertions; +using OpenSearch.Client; +using OpenSearch.Net; +using Tests.Core.Extensions; +using Tests.Core.ManagedOpenSearch.Clusters; +using Tests.Domain; +using Tests.Framework.EndpointTests; +using Tests.Framework.EndpointTests.TestState; + +namespace Tests.Indices.Stats; + +public class IndicesStatsApiTests + : ApiIntegrationTestBase +{ + private static readonly IndexName ProjectIndex = Infer.Index(); + + public IndicesStatsApiTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + + protected override bool ExpectIsValid => true; + protected override int ExpectStatusCode => 200; + protected override HttpMethod HttpMethod => HttpMethod.GET; + + protected override IndicesStatsRequest Initializer => new (ProjectIndex, IndicesStatsMetric.Docs | IndicesStatsMetric.Segments); + + protected override Func Fluent => + d => d.Metric(IndicesStatsMetric.Docs | IndicesStatsMetric.Segments); + + protected override string UrlPath => "/project/_stats/docs%2Csegments"; + + protected override LazyResponses ClientUsage() => Calls( + (client, f) => client.Indices.Stats(typeof(Project), f), + (client, f) => client.Indices.StatsAsync(typeof(Project), f), + (client, r) => client.Indices.Stats(r), + (client, r) => client.Indices.StatsAsync(r) + ); + + protected override void ExpectResponse(IndicesStatsResponse response) + { + response.ShouldBeValid(); + + response.Indices.Should().NotBeNull(); + response.Indices.Count.Should().BeGreaterThan(0); + + var projectIndex = response.Indices[ProjectIndex]; + projectIndex.Should().NotBeNull(); + + var primaries = projectIndex.Primaries; + primaries.Should().NotBeNull(); + + var documents = primaries.Documents; + documents.Should().NotBeNull(); + documents.Count.Should().BeGreaterThan(0); + + var segments = primaries.Segments; + segments.Should().NotBeNull(); + segments.Count.Should().BeGreaterThan(0); + } +} diff --git a/tests/Tests/Indices/Stats/IndicesStatsUrlsTests.cs b/tests/Tests/Indices/Stats/IndicesStatsUrlsTests.cs new file mode 100644 index 0000000000..473ea0700b --- /dev/null +++ b/tests/Tests/Indices/Stats/IndicesStatsUrlsTests.cs @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: Apache-2.0 +* +* The OpenSearch Contributors require contributions made to +* this file be licensed under the Apache-2.0 license or a +* compatible open source license. +*/ + +using System.Threading.Tasks; +using OpenSearch.OpenSearch.Xunit.XunitPlumbing; +using OpenSearch.Client; +using OpenSearch.Net; +using Tests.Framework.EndpointTests; +using static Tests.Framework.EndpointTests.UrlTester; + +namespace Tests.Indices.Stats; + +public class IndexStatsUrlsTests +{ + [U] public async Task Urls() + { + // "_stats", "{index}/_stats", "{index}/_stats/{metric}", "_stats/{metric}" + const string index = "test_index_1"; + const IndicesStatsMetric metrics = IndicesStatsMetric.Docs | IndicesStatsMetric.Segments; + + await GET("/_stats") + .Fluent(c => c.Indices.Stats()) + .Request(c => c.Indices.Stats(new IndicesStatsRequest())) + .FluentAsync(c => c.Indices.StatsAsync()) + .RequestAsync(c => c.Indices.StatsAsync(new IndicesStatsRequest())); + + await GET("/_stats/docs%2Csegments") + .Fluent(c => c.Indices.Stats(null, d => d.Metric(metrics))) + .Request(c => c.Indices.Stats(new IndicesStatsRequest(metrics))) + .FluentAsync(c => c.Indices.StatsAsync(null, d => d.Metric(metrics))) + .RequestAsync(c => c.Indices.StatsAsync(new IndicesStatsRequest(metrics))); + + await GET($"/{index}/_stats") + .Fluent(c => c.Indices.Stats(index, d => d)) + .Request(c => c.Indices.Stats(new IndicesStatsRequest(index))) + .FluentAsync(c => c.Indices.StatsAsync(index, d => d)) + .RequestAsync(c => c.Indices.StatsAsync(new IndicesStatsRequest(index))); + + await GET($"/{index}/_stats/docs%2Csegments") + .Fluent(c => c.Indices.Stats(index, d => d.Metric(metrics))) + .Request(c => c.Indices.Stats(new IndicesStatsRequest(index, metrics))) + .FluentAsync(c => c.Indices.StatsAsync(index, d => d.Metric(metrics))) + .RequestAsync(c => c.Indices.StatsAsync(new IndicesStatsRequest(index, metrics))); + } +} diff --git a/tests/Tests/Mapping/Types/Specialized/Knn/KnnVectorPropertyTests.cs b/tests/Tests/Mapping/Types/Specialized/Knn/KnnVectorPropertyTests.cs index 47b070ed23..fcbf858f35 100644 --- a/tests/Tests/Mapping/Types/Specialized/Knn/KnnVectorPropertyTests.cs +++ b/tests/Tests/Mapping/Types/Specialized/Knn/KnnVectorPropertyTests.cs @@ -11,69 +11,84 @@ using Tests.Domain; using Tests.Framework.EndpointTests.TestState; -namespace Tests.Mapping.Types.Specialized.Knn +namespace Tests.Mapping.Types.Specialized.Knn; + +public class KnnVectorPropertyTests : PropertyTestsBase { - public class KnnVectorPropertyTests : PropertyTestsBase - { - public KnnVectorPropertyTests(WritableCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + public KnnVectorPropertyTests(WritableCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + + protected override object ExpectJson => new + { + properties = new + { + name = new + { + type = "knn_vector", + dimension = 2, + method = new + { + name = "hnsw", + space_type = "l2", + engine = "nmslib", + parameters = new + { + ef_construction = 128, + m = 24 + } + } + } + } + }; + + protected override Func, IPromise> FluentProperties => f => f + .KnnVector(k => k + .Name(p => p.Name) + .Dimension(2) + .Method(m => m + .Name("hnsw") + .SpaceType("l2") + .Engine("nmslib") + .Parameters(p => p + .Parameter("ef_construction", 128) + .Parameter("m", 24) + ) + ) + ); - protected override object ExpectJson => new - { - properties = new - { - name = new - { - type = "knn_vector", - dimension = 2, - method = new - { - name = "hnsw", - space_type = "l2", - engine = "nmslib", - parameters = new - { - ef_construction = 128, - m = 24 - } - } - } - } - }; + protected override IProperties InitializerProperties => new Properties + { + { + "name", new KnnVectorProperty + { + Dimension = 2, + Method = new KnnMethod + { + Name = "hnsw", + SpaceType = "l2", + Engine = "nmslib", + Parameters = new KnnMethodParameters + { + {"ef_construction", 128}, + {"m", 24} + } + } + } + } + }; - protected override Func, IPromise> FluentProperties => f => f - .KnnVector(k => k - .Name(p => p.Name) - .Dimension(2) - .Method(m => m - .Name("hnsw") - .SpaceType("l2") - .Engine("nmslib") - .Parameters(p => p - .Parameter("ef_construction", 128) - .Parameter("m", 24) - ) - ) - ); + protected override void IntegrationSetup(IOpenSearchClient client, CallUniqueValues values) + { + foreach (var v in values.Values) + { + client.Indices.Create(v, d => d + .Settings(s => s + .Setting("index.knn", true) + .Setting("index.knn.algo_param.ef_search", 100))); + } + } - protected override IProperties InitializerProperties => new Properties - { - { - "name", new KnnVectorProperty - { - Dimension = 2, - Method = new KnnMethod - { - Name = "hnsw", - SpaceType = "l2", - Engine = "nmslib", - Parameters = new KnnMethodParameters - { - {"ef_construction", 128}, - {"m", 24} - } - } - } - } - }; - } + protected override void IntegrationTeardown(IOpenSearchClient client, CallUniqueValues values) + { + foreach (var v in values.Values) client.Indices.Delete(v); + } } diff --git a/tests/Tests/QueryDsl/Specialized/Percolate/PercolateQueryUsageTests.cs b/tests/Tests/QueryDsl/Specialized/Percolate/PercolateQueryUsageTests.cs index 64a0005622..d89bbff335 100644 --- a/tests/Tests/QueryDsl/Specialized/Percolate/PercolateQueryUsageTests.cs +++ b/tests/Tests/QueryDsl/Specialized/Percolate/PercolateQueryUsageTests.cs @@ -89,10 +89,9 @@ protected override void IntegrationSetup(IOpenSearchClient client, CallUniqueVal foreach (var index in values.Values) { Client.Indices.Create(index, c => c - .Settings(settings => settings + .Settings(settings => DefaultSeeder.ProjectIndexSettings(settings) .NumberOfShards(1) .NumberOfReplicas(0) - .Analysis(DefaultSeeder.ProjectAnalysisSettings) ) .Map(mm => mm.AutoMap() .Properties(DefaultSeeder.ProjectProperties) @@ -100,10 +99,9 @@ protected override void IntegrationSetup(IOpenSearchClient client, CallUniqueVal ); var percolationIndex = index + "-queries"; Client.Indices.Create(percolationIndex, c => c - .Settings(settings => settings + .Settings(settings => DefaultSeeder.ProjectIndexSettings(settings) .NumberOfShards(1) .NumberOfReplicas(0) - .Analysis(DefaultSeeder.ProjectAnalysisSettings) ) .Map(mm => mm.AutoMap() .Properties(DefaultSeeder.PercolatedQueryProperties)