manticore-client 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +39 -0
- data/.openapi-generator/FILES +149 -0
- data/.openapi-generator/VERSION +1 -0
- data/.openapi-generator-ignore +5 -0
- data/.rspec +2 -0
- data/.rubocop.yml +160 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +103 -0
- data/LICENSE.txt +21 -0
- data/README.md +136 -0
- data/Rakefile +10 -0
- data/docs/AggComposite.md +20 -0
- data/docs/AggCompositeSource.md +18 -0
- data/docs/AggCompositeTerm.md +18 -0
- data/docs/AggTerms.md +20 -0
- data/docs/Aggregation.md +22 -0
- data/docs/AutocompleteRequest.md +22 -0
- data/docs/BoolFilter.md +22 -0
- data/docs/BulkResponse.md +26 -0
- data/docs/DeleteDocumentRequest.md +24 -0
- data/docs/DeleteResponse.md +26 -0
- data/docs/ErrorResponse.md +20 -0
- data/docs/FulltextFilter.md +24 -0
- data/docs/GeoDistance.md +24 -0
- data/docs/GeoDistanceLocationAnchor.md +20 -0
- data/docs/Highlight.md +62 -0
- data/docs/HighlightAllOfFields.md +15 -0
- data/docs/HighlightFieldOption.md +26 -0
- data/docs/HitsHits.md +22 -0
- data/docs/IndexApi.md +401 -0
- data/docs/InsertDocumentRequest.md +24 -0
- data/docs/Join.md +24 -0
- data/docs/JoinCond.md +22 -0
- data/docs/JoinOn.md +22 -0
- data/docs/KnnQuery.md +28 -0
- data/docs/Match.md +22 -0
- data/docs/MatchAll.md +18 -0
- data/docs/PercolateRequest.md +18 -0
- data/docs/PercolateRequestQuery.md +18 -0
- data/docs/QueryFilter.md +34 -0
- data/docs/Range.md +24 -0
- data/docs/ReplaceDocumentRequest.md +18 -0
- data/docs/ResponseError.md +49 -0
- data/docs/ResponseErrorDetails.md +22 -0
- data/docs/SearchApi.md +204 -0
- data/docs/SearchQuery.md +36 -0
- data/docs/SearchRequest.md +46 -0
- data/docs/SearchResponse.md +30 -0
- data/docs/SearchResponseHits.md +24 -0
- data/docs/SourceRules.md +20 -0
- data/docs/SqlResponse.md +49 -0
- data/docs/SuccessResponse.md +28 -0
- data/docs/UpdateDocumentRequest.md +26 -0
- data/docs/UpdateResponse.md +24 -0
- data/docs/UtilsApi.md +76 -0
- data/lib/manticore/client/api/index_api.rb +442 -0
- data/lib/manticore/client/api/search_api.rb +232 -0
- data/lib/manticore/client/api/utils_api.rb +93 -0
- data/lib/manticore/client/api_client.rb +437 -0
- data/lib/manticore/client/api_error.rb +58 -0
- data/lib/manticore/client/configuration.rb +385 -0
- data/lib/manticore/client/models/agg_composite.rb +233 -0
- data/lib/manticore/client/models/agg_composite_source.rb +238 -0
- data/lib/manticore/client/models/agg_composite_term.rb +239 -0
- data/lib/manticore/client/models/agg_terms.rb +249 -0
- data/lib/manticore/client/models/aggregation.rb +240 -0
- data/lib/manticore/client/models/autocomplete_request.rb +276 -0
- data/lib/manticore/client/models/bool_filter.rb +247 -0
- data/lib/manticore/client/models/bulk_response.rb +264 -0
- data/lib/manticore/client/models/delete_document_request.rb +269 -0
- data/lib/manticore/client/models/delete_response.rb +262 -0
- data/lib/manticore/client/models/error_response.rb +250 -0
- data/lib/manticore/client/models/fulltext_filter.rb +252 -0
- data/lib/manticore/client/models/geo_distance.rb +306 -0
- data/lib/manticore/client/models/geo_distance_location_anchor.rb +232 -0
- data/lib/manticore/client/models/highlight.rb +525 -0
- data/lib/manticore/client/models/highlight_all_of_fields.rb +105 -0
- data/lib/manticore/client/models/highlight_field_option.rb +262 -0
- data/lib/manticore/client/models/hits_hits.rb +242 -0
- data/lib/manticore/client/models/insert_document_request.rb +286 -0
- data/lib/manticore/client/models/join.rb +327 -0
- data/lib/manticore/client/models/join_cond.rb +276 -0
- data/lib/manticore/client/models/join_on.rb +272 -0
- data/lib/manticore/client/models/knn_query.rb +307 -0
- data/lib/manticore/client/models/match.rb +290 -0
- data/lib/manticore/client/models/match_all.rb +262 -0
- data/lib/manticore/client/models/percolate_request.rb +238 -0
- data/lib/manticore/client/models/percolate_request_query.rb +238 -0
- data/lib/manticore/client/models/query_filter.rb +307 -0
- data/lib/manticore/client/models/range.rb +252 -0
- data/lib/manticore/client/models/replace_document_request.rb +239 -0
- data/lib/manticore/client/models/response_error.rb +105 -0
- data/lib/manticore/client/models/response_error_details.rb +261 -0
- data/lib/manticore/client/models/search_query.rb +316 -0
- data/lib/manticore/client/models/search_request.rb +382 -0
- data/lib/manticore/client/models/search_response.rb +281 -0
- data/lib/manticore/client/models/search_response_hits.rb +254 -0
- data/lib/manticore/client/models/source_rules.rb +236 -0
- data/lib/manticore/client/models/sql_response.rb +106 -0
- data/lib/manticore/client/models/success_response.rb +272 -0
- data/lib/manticore/client/models/update_document_request.rb +296 -0
- data/lib/manticore/client/models/update_response.rb +252 -0
- data/lib/manticore/client/version.rb +7 -0
- data/lib/manticore/client.rb +32 -0
- data/lib/manticore-client.rb +3 -0
- data/manticore-client.gemspec +34 -0
- data/spec/api/index_api_spec.rb +179 -0
- data/spec/api/search_api_spec.rb +94 -0
- data/spec/api/utils_api_spec.rb +100 -0
- data/spec/spec_helper.rb +92 -0
- data/spec/support/manticore_sql_helper.rb +33 -0
- metadata +218 -0
@@ -0,0 +1,252 @@
|
|
1
|
+
=begin
|
2
|
+
#Manticore Search Client
|
3
|
+
|
4
|
+
#Сlient for Manticore Search.
|
5
|
+
|
6
|
+
The version of the OpenAPI document: 5.0.0
|
7
|
+
Contact: info@manticoresearch.com
|
8
|
+
Generated by: https://openapi-generator.tech
|
9
|
+
Generator version: 7.13.0
|
10
|
+
|
11
|
+
=end
|
12
|
+
|
13
|
+
require 'date'
|
14
|
+
require 'time'
|
15
|
+
|
16
|
+
module Manticore::Client
|
17
|
+
# Success response returned after updating one or more documents
|
18
|
+
class UpdateResponse
|
19
|
+
# Name of the document table
|
20
|
+
attr_accessor :table
|
21
|
+
|
22
|
+
# Number of documents updated
|
23
|
+
attr_accessor :updated
|
24
|
+
|
25
|
+
# Document ID
|
26
|
+
attr_accessor :id
|
27
|
+
|
28
|
+
# Result of the update operation, typically 'updated'
|
29
|
+
attr_accessor :result
|
30
|
+
|
31
|
+
# Attribute mapping from ruby-style variable name to JSON key.
|
32
|
+
def self.attribute_map
|
33
|
+
{
|
34
|
+
:'table' => :'table',
|
35
|
+
:'updated' => :'updated',
|
36
|
+
:'id' => :'id',
|
37
|
+
:'result' => :'result'
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns attribute mapping this model knows about
|
42
|
+
def self.acceptable_attribute_map
|
43
|
+
attribute_map
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns all the JSON keys this model knows about
|
47
|
+
def self.acceptable_attributes
|
48
|
+
acceptable_attribute_map.values
|
49
|
+
end
|
50
|
+
|
51
|
+
# Attribute type mapping.
|
52
|
+
def self.openapi_types
|
53
|
+
{
|
54
|
+
:'table' => :'String',
|
55
|
+
:'updated' => :'Integer',
|
56
|
+
:'id' => :'Integer',
|
57
|
+
:'result' => :'String'
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
# List of attributes with nullable: true
|
62
|
+
def self.openapi_nullable
|
63
|
+
Set.new([
|
64
|
+
])
|
65
|
+
end
|
66
|
+
|
67
|
+
# Initializes the object
|
68
|
+
# @param [Hash] attributes Model attributes in the form of hash
|
69
|
+
def initialize(attributes = {})
|
70
|
+
if (!attributes.is_a?(Hash))
|
71
|
+
fail ArgumentError, "The input argument (attributes) must be a hash in `Manticore::Client::UpdateResponse` initialize method"
|
72
|
+
end
|
73
|
+
|
74
|
+
# check to see if the attribute exists and convert string to symbol for hash key
|
75
|
+
acceptable_attribute_map = self.class.acceptable_attribute_map
|
76
|
+
attributes = attributes.each_with_object({}) { |(k, v), h|
|
77
|
+
if (!acceptable_attribute_map.key?(k.to_sym))
|
78
|
+
fail ArgumentError, "`#{k}` is not a valid attribute in `Manticore::Client::UpdateResponse`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
|
79
|
+
end
|
80
|
+
h[k.to_sym] = v
|
81
|
+
}
|
82
|
+
|
83
|
+
if attributes.key?(:'table')
|
84
|
+
self.table = attributes[:'table']
|
85
|
+
end
|
86
|
+
|
87
|
+
if attributes.key?(:'updated')
|
88
|
+
self.updated = attributes[:'updated']
|
89
|
+
end
|
90
|
+
|
91
|
+
if attributes.key?(:'id')
|
92
|
+
self.id = attributes[:'id']
|
93
|
+
end
|
94
|
+
|
95
|
+
if attributes.key?(:'result')
|
96
|
+
self.result = attributes[:'result']
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Show invalid properties with the reasons. Usually used together with valid?
|
101
|
+
# @return Array for valid properties with the reasons
|
102
|
+
def list_invalid_properties
|
103
|
+
warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
|
104
|
+
invalid_properties = Array.new
|
105
|
+
invalid_properties
|
106
|
+
end
|
107
|
+
|
108
|
+
# Check to see if the all the properties in the model are valid
|
109
|
+
# @return true if the model is valid
|
110
|
+
def valid?
|
111
|
+
warn '[DEPRECATED] the `valid?` method is obsolete'
|
112
|
+
true
|
113
|
+
end
|
114
|
+
|
115
|
+
# Checks equality by comparing each attribute.
|
116
|
+
# @param [Object] Object to be compared
|
117
|
+
def ==(o)
|
118
|
+
return true if self.equal?(o)
|
119
|
+
self.class == o.class &&
|
120
|
+
table == o.table &&
|
121
|
+
updated == o.updated &&
|
122
|
+
id == o.id &&
|
123
|
+
result == o.result
|
124
|
+
end
|
125
|
+
|
126
|
+
# @see the `==` method
|
127
|
+
# @param [Object] Object to be compared
|
128
|
+
def eql?(o)
|
129
|
+
self == o
|
130
|
+
end
|
131
|
+
|
132
|
+
# Calculates hash code according to all attributes.
|
133
|
+
# @return [Integer] Hash code
|
134
|
+
def hash
|
135
|
+
[table, updated, id, result].hash
|
136
|
+
end
|
137
|
+
|
138
|
+
# Builds the object from hash
|
139
|
+
# @param [Hash] attributes Model attributes in the form of hash
|
140
|
+
# @return [Object] Returns the model itself
|
141
|
+
def self.build_from_hash(attributes)
|
142
|
+
return nil unless attributes.is_a?(Hash)
|
143
|
+
attributes = attributes.transform_keys(&:to_sym)
|
144
|
+
transformed_hash = {}
|
145
|
+
openapi_types.each_pair do |key, type|
|
146
|
+
if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
|
147
|
+
transformed_hash["#{key}"] = nil
|
148
|
+
elsif type =~ /\AArray<(.*)>/i
|
149
|
+
# check to ensure the input is an array given that the attribute
|
150
|
+
# is documented as an array but the input is not
|
151
|
+
if attributes[attribute_map[key]].is_a?(Array)
|
152
|
+
transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
|
153
|
+
end
|
154
|
+
elsif !attributes[attribute_map[key]].nil?
|
155
|
+
transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
|
156
|
+
end
|
157
|
+
end
|
158
|
+
new(transformed_hash)
|
159
|
+
end
|
160
|
+
|
161
|
+
# Deserializes the data based on type
|
162
|
+
# @param string type Data type
|
163
|
+
# @param string value Value to be deserialized
|
164
|
+
# @return [Object] Deserialized data
|
165
|
+
def self._deserialize(type, value)
|
166
|
+
case type.to_sym
|
167
|
+
when :Time
|
168
|
+
Time.parse(value)
|
169
|
+
when :Date
|
170
|
+
Date.parse(value)
|
171
|
+
when :String
|
172
|
+
value.to_s
|
173
|
+
when :Integer
|
174
|
+
value.to_i
|
175
|
+
when :Float
|
176
|
+
value.to_f
|
177
|
+
when :Boolean
|
178
|
+
if value.to_s =~ /\A(true|t|yes|y|1)\z/i
|
179
|
+
true
|
180
|
+
else
|
181
|
+
false
|
182
|
+
end
|
183
|
+
when :Object
|
184
|
+
# generic object (usually a Hash), return directly
|
185
|
+
value
|
186
|
+
when /\AArray<(?<inner_type>.+)>\z/
|
187
|
+
inner_type = Regexp.last_match[:inner_type]
|
188
|
+
value.map { |v| _deserialize(inner_type, v) }
|
189
|
+
when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
|
190
|
+
k_type = Regexp.last_match[:k_type]
|
191
|
+
v_type = Regexp.last_match[:v_type]
|
192
|
+
{}.tap do |hash|
|
193
|
+
value.each do |k, v|
|
194
|
+
hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
else # model
|
198
|
+
# models (e.g. Pet) or oneOf
|
199
|
+
klass = Manticore::Client.const_get(type)
|
200
|
+
klass.respond_to?(:openapi_any_of) || klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Returns the string representation of the object
|
205
|
+
# @return [String] String presentation of the object
|
206
|
+
def to_s
|
207
|
+
to_hash.to_s
|
208
|
+
end
|
209
|
+
|
210
|
+
# to_body is an alias to to_hash (backward compatibility)
|
211
|
+
# @return [Hash] Returns the object in the form of hash
|
212
|
+
def to_body
|
213
|
+
to_hash
|
214
|
+
end
|
215
|
+
|
216
|
+
# Returns the object in the form of hash
|
217
|
+
# @return [Hash] Returns the object in the form of hash
|
218
|
+
def to_hash
|
219
|
+
hash = {}
|
220
|
+
self.class.attribute_map.each_pair do |attr, param|
|
221
|
+
value = self.send(attr)
|
222
|
+
if value.nil?
|
223
|
+
is_nullable = self.class.openapi_nullable.include?(attr)
|
224
|
+
next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
|
225
|
+
end
|
226
|
+
|
227
|
+
hash[param] = _to_hash(value)
|
228
|
+
end
|
229
|
+
hash
|
230
|
+
end
|
231
|
+
|
232
|
+
# Outputs non-array value in the form of hash
|
233
|
+
# For object, use to_hash. Otherwise, just return the value
|
234
|
+
# @param [Object] value Any valid value
|
235
|
+
# @return [Hash] Returns the value in the form of hash
|
236
|
+
def _to_hash(value)
|
237
|
+
if value.is_a?(Array)
|
238
|
+
value.compact.map { |v| _to_hash(v) }
|
239
|
+
elsif value.is_a?(Hash)
|
240
|
+
{}.tap do |hash|
|
241
|
+
value.each { |k, v| hash[k] = _to_hash(v) }
|
242
|
+
end
|
243
|
+
elsif value.respond_to? :to_hash
|
244
|
+
value.to_hash
|
245
|
+
else
|
246
|
+
value
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zeitwerk"
|
4
|
+
|
5
|
+
loader = Zeitwerk::Loader.for_gem
|
6
|
+
loader.push_dir(__dir__, namespace: Manticore)
|
7
|
+
loader.push_dir("#{__dir__}/client/api", namespace: Manticore::Client)
|
8
|
+
loader.push_dir("#{__dir__}/client/models", namespace: Manticore::Client)
|
9
|
+
loader.setup
|
10
|
+
|
11
|
+
module Manticore
|
12
|
+
# The Manticore Search client for Ruby.
|
13
|
+
module Client
|
14
|
+
class << self
|
15
|
+
# Customize default settings for the SDK using block.
|
16
|
+
# Manticore::Client.configure do |config|
|
17
|
+
# config.username = "xxx"
|
18
|
+
# config.password = "xxx"
|
19
|
+
# end
|
20
|
+
# If no block given, return the default Configuration object.
|
21
|
+
def configure
|
22
|
+
if block_given?
|
23
|
+
yield(Configuration.default)
|
24
|
+
else
|
25
|
+
Configuration.default
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
loader.eager_load
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path("lib", __dir__)
|
4
|
+
require "manticore/client/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "manticore-client"
|
8
|
+
spec.version = Manticore::Client::VERSION
|
9
|
+
spec.platform = Gem::Platform::RUBY
|
10
|
+
spec.authors = ["OpenAPI-Generator"]
|
11
|
+
spec.email = ["subbota@gmail.com"]
|
12
|
+
spec.homepage = "https://github.com/numbata/manticore-client"
|
13
|
+
spec.summary = "Autogenerated Manticore Search client"
|
14
|
+
spec.description = "Сlient for Manticore Search. "
|
15
|
+
spec.license = "MIT"
|
16
|
+
spec.required_ruby_version = ">= 2.7"
|
17
|
+
spec.metadata = {
|
18
|
+
"bug_tracker_uri" => "#{spec.homepage}/issues",
|
19
|
+
"changelog_uri" => "#{spec.homepage}/blob/v#{spec.version}/CHANGELOG.md",
|
20
|
+
"homepage_uri" => spec.homepage,
|
21
|
+
"source_code_uri" => spec.homepage,
|
22
|
+
"rubygems_mfa_required" => "true"
|
23
|
+
}
|
24
|
+
|
25
|
+
spec.add_dependency "faraday", ">= 1.0.1", "< 3.0"
|
26
|
+
spec.add_dependency "faraday-multipart"
|
27
|
+
spec.add_dependency "marcel"
|
28
|
+
spec.add_dependency "zeitwerk"
|
29
|
+
|
30
|
+
spec.files = `git ls-files`.split("\n")
|
31
|
+
|
32
|
+
spec.executables = []
|
33
|
+
spec.require_paths = ["lib"]
|
34
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe "IndexApi" do
|
6
|
+
subject(:index_api) { Manticore::Client::IndexApi.new }
|
7
|
+
|
8
|
+
let(:table_name) { "#{TABLE_PREFIX}movies" }
|
9
|
+
|
10
|
+
before do
|
11
|
+
ManticoreSqlHelper.query("CREATE TABLE #{table_name} (title TEXT, rating FLOAT)")
|
12
|
+
ManticoreSqlHelper.query(<<~SQL)
|
13
|
+
INSERT INTO #{table_name} (id, title, rating) VALUES
|
14
|
+
(1, 'Scary movie', 9.5),
|
15
|
+
(2, 'Horror movie', 2.1)
|
16
|
+
SQL
|
17
|
+
end
|
18
|
+
|
19
|
+
after do
|
20
|
+
ManticoreSqlHelper.drop_table(table_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Sends multiple operations like inserts, updates, replaces, or deletes.
|
24
|
+
describe "#bulk" do
|
25
|
+
it "creates batch of documents" do
|
26
|
+
request_body = <<~NDJSON
|
27
|
+
{ "insert": { "index": "#{table_name}", "id": 3, "doc": { "title": "New movie", "rating": 8.5 } } }
|
28
|
+
{ "delete": { "index": "#{table_name}", "id": 2 } }
|
29
|
+
NDJSON
|
30
|
+
|
31
|
+
result = index_api.bulk(request_body)
|
32
|
+
|
33
|
+
expect(result.items[0][:bulk]).to include(
|
34
|
+
table: table_name,
|
35
|
+
created: 1,
|
36
|
+
deleted: 1,
|
37
|
+
result: "updated"
|
38
|
+
)
|
39
|
+
expect(table_name).to have_docs(
|
40
|
+
{ id: 1, title: "Scary movie", rating: 9.5 },
|
41
|
+
{ id: 3, title: "New movie", rating: 8.5 }
|
42
|
+
)
|
43
|
+
expect(table_name).not_to have_docs(
|
44
|
+
{ id: 2, title: "Horror movie", rating: 2.1 }
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Delete one or several documents.
|
50
|
+
describe "#delete" do
|
51
|
+
it "removes one doc from table" do
|
52
|
+
request = Manticore::Client::DeleteDocumentRequest.new(
|
53
|
+
table: table_name,
|
54
|
+
id: 2
|
55
|
+
)
|
56
|
+
|
57
|
+
result = index_api.delete(request)
|
58
|
+
|
59
|
+
expect(result).to be_a(Manticore::Client::DeleteResponse)
|
60
|
+
expect(result).to have_attributes(
|
61
|
+
table: table_name,
|
62
|
+
result: "deleted"
|
63
|
+
)
|
64
|
+
expect(table_name).to have_docs(
|
65
|
+
{ id: 1, title: "Scary movie", rating: 9.5 }
|
66
|
+
)
|
67
|
+
expect(table_name).not_to have_docs(
|
68
|
+
{ id: 2, title: "Horror movie", rating: 2.1 }
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "removes several docs from table" do
|
73
|
+
request = Manticore::Client::DeleteDocumentRequest.new(
|
74
|
+
table: table_name,
|
75
|
+
id: [1, 2]
|
76
|
+
)
|
77
|
+
|
78
|
+
result = index_api.delete(request)
|
79
|
+
|
80
|
+
expect(result).to be_a(Manticore::Client::DeleteResponse)
|
81
|
+
expect(result).to have_attributes(
|
82
|
+
table: table_name,
|
83
|
+
result: "deleted"
|
84
|
+
)
|
85
|
+
expect(table_name).not_to have_docs(
|
86
|
+
{ id: 1, title: "Scary movie", rating: 9.5 },
|
87
|
+
{ id: 2, title: "Horror movie", rating: 2.1 }
|
88
|
+
)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Insert a new document in a table.
|
93
|
+
describe "#insert" do
|
94
|
+
it "inserts a new document" do
|
95
|
+
request = Manticore::Client::InsertDocumentRequest.new(
|
96
|
+
table: table_name,
|
97
|
+
id: 3,
|
98
|
+
doc: { title: "Brand new movie", rating: 7.7 }
|
99
|
+
)
|
100
|
+
|
101
|
+
result = index_api.insert(request)
|
102
|
+
|
103
|
+
expect(result).to be_a(Manticore::Client::SuccessResponse)
|
104
|
+
expect(result).to have_attributes(
|
105
|
+
table: table_name,
|
106
|
+
id: 3,
|
107
|
+
created: true,
|
108
|
+
result: "created"
|
109
|
+
)
|
110
|
+
expect(table_name).to have_docs(
|
111
|
+
{ id: 3, title: "Brand new movie", rating: 7.7 }
|
112
|
+
)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Partially replaces a document in a table.
|
117
|
+
describe "#partial_replace" do
|
118
|
+
it "partially updates a document" do
|
119
|
+
request = Manticore::Client::ReplaceDocumentRequest.new(
|
120
|
+
doc: { rating: 8.8 }
|
121
|
+
)
|
122
|
+
id = 1
|
123
|
+
|
124
|
+
result = index_api.partial_replace(table_name, id, request)
|
125
|
+
|
126
|
+
expect(result).to be_a(Manticore::Client::UpdateResponse)
|
127
|
+
expect(result).to have_attributes(updated: 1)
|
128
|
+
expect(table_name).to have_docs(
|
129
|
+
{ id: 1, title: "Scary movie", rating: 8.8 }
|
130
|
+
)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Replace a document in a table (full replace)
|
135
|
+
describe "#replace" do
|
136
|
+
it "fully replaces a document" do
|
137
|
+
request = Manticore::Client::InsertDocumentRequest.new(
|
138
|
+
table: table_name,
|
139
|
+
id: 1,
|
140
|
+
doc: { title: "Completely new", rating: 5.5 }
|
141
|
+
)
|
142
|
+
|
143
|
+
result = index_api.replace(request)
|
144
|
+
|
145
|
+
expect(result).to be_a(Manticore::Client::SuccessResponse)
|
146
|
+
expect(result).to have_attributes(
|
147
|
+
table: table_name,
|
148
|
+
id: 1,
|
149
|
+
created: false,
|
150
|
+
result: "updated"
|
151
|
+
)
|
152
|
+
expect(table_name).to have_docs(
|
153
|
+
{ id: 1, title: "Completely new", rating: 5.5 }
|
154
|
+
)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Update a document in a table (by id).
|
159
|
+
describe "#update" do
|
160
|
+
it "updates a document by id" do
|
161
|
+
request = Manticore::Client::UpdateDocumentRequest.new(
|
162
|
+
table: table_name,
|
163
|
+
id: 1,
|
164
|
+
doc: { rating: 4.2 }
|
165
|
+
)
|
166
|
+
|
167
|
+
result = index_api.update(request)
|
168
|
+
|
169
|
+
expect(result).to be_a(Manticore::Client::UpdateResponse)
|
170
|
+
expect(result).to have_attributes(
|
171
|
+
table: table_name,
|
172
|
+
result: "updated"
|
173
|
+
)
|
174
|
+
expect(table_name).to have_docs(
|
175
|
+
{ id: 1, title: "Scary movie", rating: 4.2 }
|
176
|
+
)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe "SearchApi" do
|
6
|
+
let(:table_name) { "#{TABLE_PREFIX}movies" }
|
7
|
+
let(:percolate_table_name) { "#{TABLE_PREFIX}pq" }
|
8
|
+
let(:api_instance) { Manticore::Client::SearchApi.new }
|
9
|
+
let(:index_api) { Manticore::Client::IndexApi.new }
|
10
|
+
|
11
|
+
before do
|
12
|
+
# Create a simple table for testing
|
13
|
+
ManticoreSqlHelper.query(<<~SQL)
|
14
|
+
CREATE TABLE #{table_name}(title text, rating float) min_infix_len = '3'
|
15
|
+
SQL
|
16
|
+
# Insert test data
|
17
|
+
ManticoreSqlHelper.query(<<~SQL)
|
18
|
+
INSERT INTO #{table_name} (id, title, rating) VALUES
|
19
|
+
(1, 'Hello world', 9.5), (2, 'Helium', 7.1), (3, 'Other', 5.0)
|
20
|
+
SQL
|
21
|
+
end
|
22
|
+
|
23
|
+
after do
|
24
|
+
ManticoreSqlHelper.drop_table(table_name)
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#autocomplete" do
|
28
|
+
it "returns suggestions for prefix" do
|
29
|
+
request = Manticore::Client::AutocompleteRequest.new(table: table_name, query: "Hel")
|
30
|
+
result = api_instance.autocomplete(request)
|
31
|
+
suggestions = result.first[:data].map { |row| row[:query] }
|
32
|
+
expect(suggestions).to include("hello", "helium")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#search" do
|
37
|
+
it "returns matching documents" do
|
38
|
+
request = Manticore::Client::SearchRequest.new(table: table_name, query: { match: { title: "Hello" } })
|
39
|
+
result = api_instance.search(request)
|
40
|
+
expect(result.hits.total).to eq(1)
|
41
|
+
expect(result.hits.hits.first._source[:title]).to eq("Hello world")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#percolate" do
|
46
|
+
before do
|
47
|
+
# Create a percolate table with explicit schema following the docs
|
48
|
+
ManticoreSqlHelper.query(<<~SQL)
|
49
|
+
CREATE TABLE #{percolate_table_name}(title text, rating float) type='pq'
|
50
|
+
SQL
|
51
|
+
|
52
|
+
# Insert queries in the format shown in the official docs
|
53
|
+
ManticoreSqlHelper.query(<<~SQL)
|
54
|
+
INSERT INTO #{percolate_table_name}(id, query, filters) VALUES
|
55
|
+
(1, '@title hello', ''),
|
56
|
+
(2, '@title world', ''),
|
57
|
+
(3, '@title high', 'rating > 8.0')
|
58
|
+
SQL
|
59
|
+
end
|
60
|
+
|
61
|
+
after do
|
62
|
+
ManticoreSqlHelper.drop_table(percolate_table_name)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "matches document against stored queries" do
|
66
|
+
# Create a document to test against the stored queries
|
67
|
+
# Include 'high' in the title to match query 3 and rating > 8.0 to match the filter
|
68
|
+
document = { title: "Hello world high", rating: 9.0 }
|
69
|
+
|
70
|
+
# Create a percolate request following the docs
|
71
|
+
request = Manticore::Client::PercolateRequest.new(
|
72
|
+
query: {
|
73
|
+
percolate: {
|
74
|
+
document: document
|
75
|
+
}
|
76
|
+
}
|
77
|
+
)
|
78
|
+
|
79
|
+
# Perform the percolate search
|
80
|
+
result = api_instance.percolate(percolate_table_name, request)
|
81
|
+
|
82
|
+
# Verify the results
|
83
|
+
expect(result.hits.total).to be >= 2 # Should match queries 1, 2, and 3
|
84
|
+
|
85
|
+
# Extract the matched query IDs
|
86
|
+
query_ids = result.hits.hits.map { |hit| hit._id.to_i }
|
87
|
+
|
88
|
+
# Verify specific matches
|
89
|
+
expect(query_ids).to include(1) # '@title hello' query
|
90
|
+
expect(query_ids).to include(2) # '@title world' query
|
91
|
+
expect(query_ids).to include(3) # '@title high' with 'rating > 8.0' filter
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe "UtilsApi" do
|
6
|
+
let(:table_name) { "#{TABLE_PREFIX}utils_test" }
|
7
|
+
let(:api_instance) { Manticore::Client::UtilsApi.new }
|
8
|
+
|
9
|
+
before do
|
10
|
+
# Create a test table
|
11
|
+
sql = "CREATE TABLE #{table_name} (title text, rating float)"
|
12
|
+
api_instance.sql("query=#{URI.encode_www_form_component(sql)}", query_params: { mode: "raw" })
|
13
|
+
end
|
14
|
+
|
15
|
+
after do
|
16
|
+
# Drop the test table
|
17
|
+
|
18
|
+
sql = "DROP TABLE #{table_name}"
|
19
|
+
api_instance.sql("query=#{URI.encode_www_form_component(sql)}", query_params: { mode: "raw" })
|
20
|
+
rescue StandardError => e
|
21
|
+
puts "Warning: Could not drop table #{table_name}: #{e.message}"
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#sql" do
|
25
|
+
it "creates an instance of UtilsApi" do
|
26
|
+
expect(api_instance).to be_instance_of(Manticore::Client::UtilsApi)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "executes INSERT statement" do
|
30
|
+
# Insert test data
|
31
|
+
sql = "INSERT INTO #{table_name} (id, title, rating) VALUES (1, 'Test Movie', 8.5)"
|
32
|
+
result = api_instance.sql("query=#{URI.encode_www_form_component(sql)}", query_params: { mode: "raw" })
|
33
|
+
|
34
|
+
# Verify the result
|
35
|
+
expect(result).to be_an(Array)
|
36
|
+
expect(result.first[:total]).to eq(1) # 1 row affected
|
37
|
+
expect(result.first[:error]).to be_empty
|
38
|
+
end
|
39
|
+
|
40
|
+
it "executes SELECT statement" do
|
41
|
+
# Insert test data
|
42
|
+
sql = "INSERT INTO #{table_name} (id, title, rating) VALUES (1, 'Test Movie', 8.5)"
|
43
|
+
api_instance.sql("query=#{URI.encode_www_form_component(sql)}", query_params: { mode: "raw" })
|
44
|
+
|
45
|
+
# Query the data
|
46
|
+
sql = "SELECT * FROM #{table_name}"
|
47
|
+
result = api_instance.sql("query=#{URI.encode_www_form_component(sql)}", query_params: { mode: "raw" })
|
48
|
+
|
49
|
+
# Verify the result
|
50
|
+
expect(result).to be_an(Array)
|
51
|
+
expect(result.first[:data]).to be_an(Array)
|
52
|
+
expect(result.first[:data].size).to eq(1)
|
53
|
+
expect(result.first[:data].first[:title]).to eq("Test Movie")
|
54
|
+
expect(result.first[:data].first[:rating]).to eq(8.5)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "executes SHOW TABLES statement" do
|
58
|
+
# Query tables
|
59
|
+
sql = "SHOW TABLES"
|
60
|
+
result = api_instance.sql("query=#{URI.encode_www_form_component(sql)}", query_params: { mode: "raw" })
|
61
|
+
|
62
|
+
# Verify the result
|
63
|
+
expect(result).to be_an(Array)
|
64
|
+
expect(result.first[:columns]).to be_an(Array)
|
65
|
+
expect(result.first[:data]).to be_an(Array)
|
66
|
+
|
67
|
+
# The test table should be in the list
|
68
|
+
table_names = result.first[:data].map { |row| row[:Table] }
|
69
|
+
expect(table_names).to include(table_name)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "handles errors gracefully" do
|
73
|
+
# Execute an invalid SQL statement
|
74
|
+
sql = "SELECT * FROM non_existent_table"
|
75
|
+
|
76
|
+
# The API should raise an exception
|
77
|
+
expect { api_instance.sql("query=#{URI.encode_www_form_component(sql)}", query_params: { mode: "raw" }) }
|
78
|
+
.to raise_error(Manticore::Client::ApiError) do |error|
|
79
|
+
expect(error.response_body).to include("error")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
it "supports raw_response parameter" do
|
84
|
+
# Insert test data
|
85
|
+
sql = "INSERT INTO #{table_name} (id, title, rating) VALUES (2, 'Another Movie', 7.0)"
|
86
|
+
api_instance.sql("query=#{URI.encode_www_form_component(sql)}", query_params: { mode: "raw" })
|
87
|
+
|
88
|
+
# Query with raw_response=false and mode=raw
|
89
|
+
sql = "SELECT * FROM #{table_name} WHERE id = 2"
|
90
|
+
result = api_instance.sql("query=#{URI.encode_www_form_component(sql)}",
|
91
|
+
query_params: { raw_response: false, mode: "raw" })
|
92
|
+
|
93
|
+
# Verify the result format is different with raw_response=false
|
94
|
+
expect(result).to be_an(Array)
|
95
|
+
expect(result.first[:data]).to be_an(Array)
|
96
|
+
expect(result.first[:data].size).to eq(1)
|
97
|
+
expect(result.first[:data].first[:title]).to eq("Another Movie")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|