Skip to content

Commit 0831b70

Browse files
authored
RCBC-469: Support for Scoped Search Indexes (#132)
1 parent c165492 commit 0831b70

File tree

11 files changed

+1832
-1328
lines changed

11 files changed

+1832
-1328
lines changed

ext/couchbase

ext/couchbase.cxx

Lines changed: 131 additions & 26 deletions
Large diffs are not rendered by default.

lib/couchbase/cluster.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def analytics_query(statement, options = Options::Analytics::DEFAULT)
187187
#
188188
# @return [SearchResult]
189189
def search_query(index_name, query, options = Options::Search::DEFAULT)
190-
resp = @backend.document_search(index_name, JSON.generate(query), {}, options.to_backend)
190+
resp = @backend.document_search(nil, nil, index_name, JSON.generate(query), {}, options.to_backend)
191191
convert_search_result(resp, options)
192192
end
193193

@@ -202,7 +202,7 @@ def search_query(index_name, query, options = Options::Search::DEFAULT)
202202
# @return [SearchResult]
203203
def search(index_name, search_request, options = Options::Search::DEFAULT)
204204
encoded_query, encoded_req = search_request.to_backend
205-
resp = @backend.document_search(index_name, encoded_query, encoded_req, options.to_backend(show_request: false))
205+
resp = @backend.document_search(nil, nil, index_name, encoded_query, encoded_req, options.to_backend(show_request: false))
206206
convert_search_result(resp, options)
207207
end
208208

lib/couchbase/management.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ module Management
2424
require "couchbase/management/query_index_manager"
2525
require "couchbase/management/collection_query_index_manager"
2626
require "couchbase/management/search_index_manager"
27+
require "couchbase/management/scope_search_index_manager"
2728
require "couchbase/management/user_manager"
2829
require "couchbase/management/view_index_manager"
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
# Copyright 2024. Couchbase, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
module Couchbase
16+
module Management
17+
# @api volatile
18+
class ScopeSearchIndexManager
19+
alias inspect to_s
20+
21+
# @param [Couchbase::Backend] backend
22+
# @param [String] bucket_name
23+
# @param [String] scope_name
24+
def initialize(backend, bucket_name, scope_name)
25+
@backend = backend
26+
@bucket_name = bucket_name
27+
@scope_name = scope_name
28+
end
29+
30+
# Fetches an index from the server if it exists
31+
#
32+
# @param [String] index_name name of the index
33+
# @param [GetIndexOptions] options
34+
#
35+
# @return [SearchIndex]
36+
#
37+
# @raise [ArgumentError]
38+
# @raise [Error::IndexNotFound]
39+
def get_index(index_name, options = GetIndexOptions.new)
40+
res = @backend.search_index_get(@bucket_name, @scope_name, index_name, options.timeout)
41+
SearchIndexManager.extract_search_index(res)
42+
end
43+
44+
# Fetches all indexes from the server
45+
#
46+
# @param [GetAllIndexesOptions] options
47+
#
48+
# @return [Array<SearchIndex>]
49+
def get_all_indexes(options = GetAllIndexesOptions.new)
50+
res = @backend.search_index_get_all(@bucket_name, @scope_name, options.timeout)
51+
res[:indexes].map { |idx| SearchIndexManager.extract_search_index(idx) }
52+
end
53+
54+
# Creates or updates the index
55+
#
56+
# @param [SearchIndex] index_definition the index definition
57+
# @param [UpsertIndexOptions] options
58+
#
59+
# @return void
60+
#
61+
# @raise [ArgumentError] if name, type or source_type is empty
62+
def upsert_index(index_definition, options = UpsertIndexOptions.new)
63+
@backend.search_index_upsert(@bucket_name, @scope_name, index_definition.to_backend, options.timeout)
64+
end
65+
66+
# Drops the index
67+
#
68+
# @param [String] index_name name of the index
69+
# @param [DropIndexOptions] options
70+
#
71+
# @return void
72+
#
73+
# @raise [ArgumentError]
74+
# @raise [Error::IndexNotFound]
75+
def drop_index(index_name, options = DropIndexOptions.new)
76+
@backend.search_index_drop(@bucket_name, @scope_name, index_name, options.timeout)
77+
end
78+
79+
# Retrieves the number of documents that have been indexed for an index
80+
#
81+
# @param [String] index_name name of the index
82+
# @param [GetIndexedDocumentsCountOptions] options
83+
#
84+
# @return [Integer]
85+
#
86+
# @raise [ArgumentError]
87+
# @raise [Error::IndexNotFound]
88+
def get_indexed_documents_count(index_name, options = GetIndexedDocumentsCountOptions.new)
89+
res = @backend.search_index_get_documents_count(@bucket_name, @scope_name, index_name, options.timeout)
90+
res[:count]
91+
end
92+
93+
# Pauses updates and maintenance for the index
94+
#
95+
# @param [String] index_name name of the index
96+
# @param [PauseIngestOptions] options
97+
#
98+
# @return void
99+
#
100+
# @raise [ArgumentError]
101+
# @raise [Error::IndexNotFound]
102+
def pause_ingest(index_name, options = PauseIngestOptions.new)
103+
@backend.search_index_pause_ingest(@bucket_name, @scope_name, index_name, options.timeout)
104+
end
105+
106+
# Resumes updates and maintenance for an index
107+
#
108+
# @param [String] index_name name of the index
109+
# @param [ResumeIngestOptions] options
110+
#
111+
# @return void
112+
#
113+
# @raise [ArgumentError]
114+
# @raise [Error::IndexNotFound]
115+
def resume_ingest(index_name, options = ResumeIngestOptions.new)
116+
@backend.search_index_resume_ingest(@bucket_name, @scope_name, index_name, options.timeout)
117+
end
118+
119+
# Allows querying against the index
120+
#
121+
# @param [String] index_name name of the index
122+
# @param [AllowQueryingOptions] options
123+
#
124+
# @return void
125+
#
126+
# @raise [ArgumentError]
127+
# @raise [Error::IndexNotFound]
128+
def allow_querying(index_name, options = AllowQueryingOptions.new)
129+
@backend.search_index_allow_querying(@bucket_name, @scope_name, index_name, options.timeout)
130+
end
131+
132+
# Disallows querying against the index
133+
#
134+
# @param [String] index_name name of the index
135+
# @param [DisallowQueryingOptions] options
136+
#
137+
# @return void
138+
#
139+
# @raise [ArgumentError]
140+
# @raise [Error::IndexNotFound]
141+
def disallow_querying(index_name, options = DisallowQueryingOptions.new)
142+
@backend.search_index_disallow_querying(@bucket_name, @scope_name, index_name, options.timeout)
143+
end
144+
145+
# Freeze the assignment of index partitions to nodes
146+
#
147+
# @param [String] index_name name of the index
148+
# @param [FreezePlanOptions] options
149+
#
150+
# @return void
151+
#
152+
# @raise [ArgumentError]
153+
# @raise [Error::IndexNotFound]
154+
def freeze_plan(index_name, options = FreezePlanOptions.new)
155+
@backend.search_index_freeze_plan(@bucket_name, @scope_name, index_name, options.timeout)
156+
end
157+
158+
# Unfreeze the assignment of index partitions to nodes
159+
#
160+
# @param [String] index_name name of the index
161+
# @param [UnfreezePlanOptions] options
162+
#
163+
# @return void
164+
#
165+
# @raise [ArgumentError]
166+
# @raise [Error::IndexNotFound]
167+
def unfreeze_plan(index_name, options = UnfreezePlanOptions.new)
168+
@backend.search_index_unfreeze_plan(@bucket_name, @scope_name, index_name, options.timeout)
169+
end
170+
171+
# Allows to see how a document is analyzed against a specific index
172+
#
173+
# @param [String] index_name name of the index
174+
# @param [Hash] document the document to be analyzed
175+
#
176+
# @return [Array<Hash>]
177+
#
178+
# @raise [ArgumentError]
179+
# @raise [Error::IndexNotFound]
180+
def analyze_document(index_name, document, options = AnalyzeDocumentOptions.new)
181+
res = @backend.search_index_analyze_document(@bucket_name, @scope_name, index_name, JSON.generate(document), options.timeout)
182+
JSON.parse(res[:analysis])
183+
end
184+
185+
GetIndexOptions = SearchIndexManager::GetIndexOptions
186+
GetAllIndexesOptions = SearchIndexManager::GetAllIndexesOptions
187+
UpsertIndexOptions = SearchIndexManager::UpsertIndexOptions
188+
DropIndexOptions = SearchIndexManager::DropIndexOptions
189+
GetIndexedDocumentsCountOptions = SearchIndexManager::GetIndexedDocumentsCountOptions
190+
PauseIngestOptions = SearchIndexManager::PauseIngestOptions
191+
ResumeIngestOptions = SearchIndexManager::ResumeIngestOptions
192+
AllowQueryingOptions = SearchIndexManager::AllowQueryingOptions
193+
DisallowQueryingOptions = SearchIndexManager::DisallowQueryingOptions
194+
FreezePlanOptions = SearchIndexManager::FreezePlanOptions
195+
UnfreezePlanOptions = SearchIndexManager::UnfreezePlanOptions
196+
AnalyzeDocumentOptions = SearchIndexManager::AnalyzeDocumentOptions
197+
end
198+
end
199+
end

lib/couchbase/management/search_index_manager.rb

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ def initialize(backend)
3434
# @raise [ArgumentError]
3535
# @raise [Error::IndexNotFound]
3636
def get_index(index_name, options = GetIndexOptions.new)
37-
res = @backend.search_index_get(index_name, options.timeout)
38-
extract_search_index(res)
37+
res = @backend.search_index_get(nil, nil, index_name, options.timeout)
38+
self.class.extract_search_index(res)
3939
end
4040

4141
# Fetches all indexes from the server
@@ -44,8 +44,8 @@ def get_index(index_name, options = GetIndexOptions.new)
4444
#
4545
# @return [Array<SearchIndex>]
4646
def get_all_indexes(options = GetAllIndexesOptions.new)
47-
res = @backend.search_index_get_all(options.timeout)
48-
res[:indexes].map { |idx| extract_search_index(idx) }
47+
res = @backend.search_index_get_all(nil, nil, options.timeout)
48+
res[:indexes].map { |idx| self.class.extract_search_index(idx) }
4949
end
5050

5151
# Creates or updates the index
@@ -58,6 +58,8 @@ def get_all_indexes(options = GetAllIndexesOptions.new)
5858
# @raise [ArgumentError] if name, type or source_type is empty
5959
def upsert_index(index_definition, options = UpsertIndexOptions.new)
6060
@backend.search_index_upsert(
61+
nil,
62+
nil,
6163
{
6264
name: index_definition.name,
6365
type: index_definition.type,
@@ -82,7 +84,7 @@ def upsert_index(index_definition, options = UpsertIndexOptions.new)
8284
# @raise [ArgumentError]
8385
# @raise [Error::IndexNotFound]
8486
def drop_index(index_name, options = DropIndexOptions.new)
85-
@backend.search_index_drop(index_name, options.timeout)
87+
@backend.search_index_drop(nil, nil, index_name, options.timeout)
8688
end
8789

8890
# Retrieves the number of documents that have been indexed for an index
@@ -95,7 +97,7 @@ def drop_index(index_name, options = DropIndexOptions.new)
9597
# @raise [ArgumentError]
9698
# @raise [Error::IndexNotFound]
9799
def get_indexed_documents_count(index_name, options = GetIndexedDocumentsCountOptions.new)
98-
res = @backend.search_index_get_documents_count(index_name, options.timeout)
100+
res = @backend.search_index_get_documents_count(nil, nil, index_name, options.timeout)
99101
res[:count]
100102
end
101103

@@ -140,7 +142,7 @@ def get_stats(options = GetIndexStatsOptions.new)
140142
# @raise [ArgumentError]
141143
# @raise [Error::IndexNotFound]
142144
def pause_ingest(index_name, options = PauseIngestOptions.new)
143-
@backend.search_index_pause_ingest(index_name, options.timeout)
145+
@backend.search_index_pause_ingest(nil, nil, index_name, options.timeout)
144146
end
145147

146148
# Resumes updates and maintenance for an index
@@ -153,7 +155,7 @@ def pause_ingest(index_name, options = PauseIngestOptions.new)
153155
# @raise [ArgumentError]
154156
# @raise [Error::IndexNotFound]
155157
def resume_ingest(index_name, options = ResumeIngestOptions.new)
156-
@backend.search_index_resume_ingest(index_name, options.timeout)
158+
@backend.search_index_resume_ingest(nil, nil, index_name, options.timeout)
157159
end
158160

159161
# Allows querying against the index
@@ -166,7 +168,7 @@ def resume_ingest(index_name, options = ResumeIngestOptions.new)
166168
# @raise [ArgumentError]
167169
# @raise [Error::IndexNotFound]
168170
def allow_querying(index_name, options = AllowQueryingOptions.new)
169-
@backend.search_index_allow_querying(index_name, options.timeout)
171+
@backend.search_index_allow_querying(nil, nil, index_name, options.timeout)
170172
end
171173

172174
# Disallows querying against the index
@@ -179,7 +181,7 @@ def allow_querying(index_name, options = AllowQueryingOptions.new)
179181
# @raise [ArgumentError]
180182
# @raise [Error::IndexNotFound]
181183
def disallow_querying(index_name, options = DisallowQueryingOptions.new)
182-
@backend.search_index_disallow_querying(index_name, options.timeout)
184+
@backend.search_index_disallow_querying(nil, nil, index_name, options.timeout)
183185
end
184186

185187
# Freeze the assignment of index partitions to nodes
@@ -192,7 +194,7 @@ def disallow_querying(index_name, options = DisallowQueryingOptions.new)
192194
# @raise [ArgumentError]
193195
# @raise [Error::IndexNotFound]
194196
def freeze_plan(index_name, options = FreezePlanOptions.new)
195-
@backend.search_index_freeze_plan(index_name, options.timeout)
197+
@backend.search_index_freeze_plan(nil, nil, index_name, options.timeout)
196198
end
197199

198200
# Unfreeze the assignment of index partitions to nodes
@@ -205,7 +207,7 @@ def freeze_plan(index_name, options = FreezePlanOptions.new)
205207
# @raise [ArgumentError]
206208
# @raise [Error::IndexNotFound]
207209
def unfreeze_plan(index_name, options = UnfreezePlanOptions.new)
208-
@backend.search_index_unfreeze_plan(index_name, options.timeout)
210+
@backend.search_index_unfreeze_plan(nil, nil, index_name, options.timeout)
209211
end
210212

211213
# Allows to see how a document is analyzed against a specific index
@@ -218,7 +220,7 @@ def unfreeze_plan(index_name, options = UnfreezePlanOptions.new)
218220
# @raise [ArgumentError]
219221
# @raise [Error::IndexNotFound]
220222
def analyze_document(index_name, document, options = AnalyzeDocumentOptions.new)
221-
res = @backend.search_index_analyze_document(index_name, JSON.generate(document), options.timeout)
223+
res = @backend.search_index_analyze_document(nil, nil, index_name, JSON.generate(document), options.timeout)
222224
JSON.parse(res[:analysis])
223225
end
224226

@@ -352,9 +354,8 @@ def initialize
352354
end
353355
end
354356

355-
private
356-
357-
def extract_search_index(resp)
357+
# @api private
358+
def self.extract_search_index(resp)
358359
SearchIndex.new do |index|
359360
index.name = resp[:name]
360361
index.type = resp[:type]
@@ -403,6 +404,21 @@ def initialize
403404
@source_type = "couchbase"
404405
yield self if block_given?
405406
end
407+
408+
# @api private
409+
def to_backend
410+
{
411+
name: name,
412+
type: type,
413+
uuid: uuid,
414+
params: (JSON.generate(params) if params),
415+
source_name: source_name,
416+
source_type: source_type,
417+
source_uuid: source_uuid,
418+
source_params: (JSON.generate(source_params) if source_params),
419+
plan_params: (JSON.generate(plan_params) if plan_params),
420+
}
421+
end
406422
end
407423
end
408424
end

0 commit comments

Comments
 (0)