groonga-client 0.5.9 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,85 @@
1
+ # Copyright (C) 2019 Sutou Kouhei <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ module Groonga
18
+ class Client
19
+ module Response
20
+ module Drilldownable
21
+ # @return [::Array<Groonga::Client::Response::Select::Drilldown>,
22
+ # ::Hash<String, Groonga::Client::Response::Select::Drilldown>]
23
+ # If labeled drilldowns are used or command version 3 or
24
+ # later is used, `{"label1" => drilldown1, "label2" => drilldown2}`
25
+ # is returned since 0.3.1.
26
+ #
27
+ # Otherwise, `[drilldown1, drilldown2]` is returned.
28
+ attr_accessor :drilldowns
29
+
30
+ private
31
+ def parse_drilldown(label, keys, raw_drilldown)
32
+ if raw_drilldown.is_a?(::Array)
33
+ n_hits = raw_drilldown[0][0]
34
+ raw_columns = raw_drilldown[1]
35
+ raw_records = raw_drilldown[2..-1]
36
+ else
37
+ n_hits = raw_drilldown["n_hits"]
38
+ raw_columns = raw_drilldown["columns"]
39
+ raw_records = raw_drilldown["records"]
40
+ end
41
+ records = parse_records(raw_columns, raw_records)
42
+ Drilldown.new(label,
43
+ keys,
44
+ n_hits,
45
+ records,
46
+ raw_columns,
47
+ raw_records)
48
+ end
49
+
50
+ def parse_drilldowns(keys, raw_drilldowns)
51
+ (raw_drilldowns || []).collect.with_index do |raw_drilldown, i|
52
+ key = keys[i]
53
+ parse_drilldown(key, [key], raw_drilldown)
54
+ end
55
+ end
56
+
57
+ def parse_labeled_drilldowns(labeled_drilldown_requests,
58
+ raw_drilldowns)
59
+ drilldowns = {}
60
+ (raw_drilldowns || {}).each do |label, raw_drilldown|
61
+ labeled_drilldown_request = labeled_drilldown_requests[label]
62
+ drilldowns[label] = parse_drilldown(label,
63
+ labeled_drilldown_request.keys,
64
+ raw_drilldown)
65
+ end
66
+ drilldowns
67
+ end
68
+
69
+ class Drilldown < Struct.new(:label,
70
+ :keys,
71
+ :n_hits,
72
+ :records,
73
+ :raw_columns,
74
+ :raw_records)
75
+ # @deprecated since 0.2.6. Use {#records} instead.
76
+ alias_method :items, :records
77
+
78
+ def key
79
+ keys.join(", ")
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,52 @@
1
+ # Copyright (C) 2019 Sutou Kouhei <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ require "groonga/client/response/base"
18
+ require "groonga/client/response/searchable"
19
+
20
+ module Groonga
21
+ class Client
22
+ module Response
23
+ class LogicalRangeFilter < Base
24
+ Response.register("logical_range_filter", self)
25
+
26
+ include Searchable
27
+
28
+ attr_accessor :records
29
+
30
+ def body=(body)
31
+ super(body)
32
+ parse_body(body)
33
+ end
34
+
35
+ private
36
+ def parse_body(body)
37
+ if body.is_a?(::Array)
38
+ @raw_columns, *@raw_records = body.first
39
+ @raw_records ||= []
40
+ @records = parse_records(raw_columns, raw_records)
41
+ else
42
+ @raw_columns = body["columns"]
43
+ @raw_records = body["records"] || []
44
+ end
45
+ @records = parse_records(@raw_columns, @raw_records)
46
+ body
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,28 @@
1
+ # Copyright (C) 2019 Sutou Kouhei <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ require "groonga/client/response/select"
18
+
19
+ module Groonga
20
+ class Client
21
+ module Response
22
+ class LogicalSelect < Select
23
+ Response.register("logical_select", self)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,97 @@
1
+ # Copyright (C) 2019 Sutou Kouhei <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ module Groonga
18
+ class Client
19
+ module Response
20
+ module Searchable
21
+ include Enumerable
22
+
23
+ attr_accessor :records
24
+ attr_accessor :raw_columns
25
+ attr_accessor :raw_records
26
+
27
+ # For Kaminari
28
+ def limit_value
29
+ (@command[:limit] || 10).to_i
30
+ end
31
+
32
+ # For Kaminari
33
+ def offset_value
34
+ (@command[:offset] || 0).to_i
35
+ end
36
+
37
+ # For Kaminari
38
+ def size
39
+ records.size
40
+ end
41
+
42
+ def each(&block)
43
+ records.each(&block)
44
+ end
45
+
46
+ private
47
+ def parse_records(raw_columns, raw_records)
48
+ column_names = {}
49
+ columns = raw_columns.collect do |column|
50
+ if column.is_a?(::Array)
51
+ name, type = column
52
+ else
53
+ name = column["name"]
54
+ type = column["type"]
55
+ end
56
+ base_column_name = name
57
+ suffix = 2
58
+ while column_names.key?(name)
59
+ name = "#{base_column_name}#{suffix}"
60
+ suffix += 1
61
+ end
62
+ column_names[name] = true
63
+ [name, type]
64
+ end
65
+
66
+ (raw_records || []).collect do |raw_record|
67
+ record = Record.new
68
+ columns.each_with_index do |(name, type), i|
69
+ record[name] = convert_value(raw_record[i], type)
70
+ end
71
+ record
72
+ end
73
+ end
74
+
75
+ def convert_value(value, type)
76
+ case value
77
+ when ::Array
78
+ value.collect do |element|
79
+ convert_value(element, type)
80
+ end
81
+ else
82
+ case type
83
+ when "Time"
84
+ Time.at(value)
85
+ else
86
+ value
87
+ end
88
+ end
89
+ end
90
+
91
+ class Record < ::Hash
92
+ include Hashie::Extensions::MethodAccess
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2013-2016 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2013-2019 Sutou Kouhei <kou@clear-code.com>
2
2
  # Copyright (C) 2013 Kosuke Asami
3
3
  # Copyright (C) 2016 Masafumi Yokoyama <yokoyama@clear-code.com>
4
4
  #
@@ -17,6 +17,8 @@
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  require "groonga/client/response/base"
20
+ require "groonga/client/response/drilldownable"
21
+ require "groonga/client/response/searchable"
20
22
 
21
23
  module Groonga
22
24
  class Client
@@ -174,23 +176,14 @@ module Groonga
174
176
  end
175
177
  end
176
178
 
177
- include Enumerable
179
+ include Drilldownable
180
+ include Searchable
178
181
 
179
182
  # @return [Integer] The number of records that match againt
180
183
  # a search condition.
181
184
  attr_accessor :n_hits
182
185
  # For Kaminari
183
186
  alias_method :total_count, :n_hits
184
- attr_accessor :records
185
-
186
- # @return [::Array<Groonga::Client::Response::Select::Drilldown>,
187
- # ::Hash<String, Groonga::Client::Response::Select::Drilldown>]
188
- # If labeled drilldowns are used or command version 3 or
189
- # later is used, `{"label1" => drilldown1, "label2" => drilldown2}`
190
- # is returned since 0.3.1.
191
- #
192
- # Otherwise, `[drilldown1, drilldown2]` is returned.
193
- attr_accessor :drilldowns
194
187
 
195
188
  # @return [::Hash<String, Groonga::Client::Response::Select::Slice>]
196
189
  #
@@ -202,29 +195,11 @@ module Groonga
202
195
  parse_body(body)
203
196
  end
204
197
 
205
- # For Kaminari
206
- def limit_value
207
- (@command[:limit] || 10).to_i
208
- end
209
-
210
- # For Kaminari
211
- def offset_value
212
- (@command[:offset] || 0).to_i
213
- end
214
-
215
- # For Kaminari
216
- def size
217
- records.size
218
- end
219
-
220
- def each(&block)
221
- records.each(&block)
222
- end
223
-
224
198
  private
225
199
  def parse_body(body)
226
200
  if body.is_a?(::Array)
227
- @n_hits, @records = parse_match_records_v1(body.first)
201
+ @n_hits, @raw_columns, @raw_records, @records =
202
+ parse_record_set_v1(body.first)
228
203
  if @command.slices.empty?
229
204
  raw_slices = nil
230
205
  raw_drilldowns = body[1..-1]
@@ -232,105 +207,74 @@ module Groonga
232
207
  raw_slices, *raw_drilldowns = body[1..-1]
233
208
  end
234
209
  @slices = parse_slices_v1(raw_slices)
235
- @drilldowns = parse_drilldowns_v1(raw_drilldowns)
236
- else
237
- @n_hits, @records = parse_match_records_v3(body)
238
- @drilldowns = parse_drilldowns_v3(body["drilldowns"])
239
- @slices = parse_slices_v3(body["slices"])
240
- end
241
- body
242
- end
243
-
244
- def parse_records(raw_columns, raw_records)
245
- column_names = {}
246
- columns = raw_columns.collect do |column|
247
- if column.is_a?(::Array)
248
- name, type = column
210
+ drilldown_keys = @command.drilldowns
211
+ labeled_drilldowns = @command.labeled_drilldowns
212
+ if drilldown_keys.empty? and !labeled_drilldowns.empty?
213
+ @drilldowns = parse_labeled_drilldowns(labeled_drilldowns,
214
+ raw_drilldowns[0])
249
215
  else
250
- name = column["name"]
251
- type = column["type"]
252
- end
253
- base_column_name = name
254
- suffix = 2
255
- while column_names.key?(name)
256
- name = "#{base_column_name}#{suffix}"
257
- suffix += 1
258
- end
259
- column_names[name] = true
260
- [name, type]
261
- end
262
-
263
- (raw_records || []).collect do |raw_record|
264
- record = Record.new
265
- columns.each_with_index do |(name, type), i|
266
- record[name] = convert_value(raw_record[i], type)
267
- end
268
- record
269
- end
270
- end
271
-
272
- def convert_value(value, type)
273
- case value
274
- when ::Array
275
- value.collect do |element|
276
- convert_value(element, type)
216
+ @drilldowns = parse_drilldowns(drilldown_keys, raw_drilldowns)
277
217
  end
278
218
  else
279
- case type
280
- when "Time"
281
- Time.at(value)
282
- else
283
- value
219
+ @n_hits, @raw_columns, @raw_records, @records =
220
+ parse_record_set_v3(body)
221
+ drilldown_keys = @command.drilldowns
222
+ labeled_drilldowns = @command.labeled_drilldowns
223
+ if labeled_drilldowns.empty?
224
+ drilldown_keys.each do |key|
225
+ labeled_drilldown =
226
+ Groonga::Command::Drilldownable::Drilldown.new
227
+ labeled_drilldown.label = key
228
+ labeled_drilldown.keys = [key]
229
+ labeled_drilldowns[key] = labeled_drilldown
230
+ end
284
231
  end
232
+ @drilldowns = parse_labeled_drilldowns(labeled_drilldowns,
233
+ body["drilldowns"])
234
+ @slices = parse_slices_v3(body["slices"])
285
235
  end
236
+ body
286
237
  end
287
238
 
288
- def parse_match_records_v1(raw_records)
239
+ def parse_record_set_v1(raw_record_set)
240
+ n_hits = raw_record_set.first.first
241
+ raw_columns = raw_record_set[1]
242
+ raw_records = raw_record_set[2..-1] || []
289
243
  [
290
- raw_records.first.first,
291
- parse_records(raw_records[1], raw_records[2..-1]),
244
+ n_hits,
245
+ raw_columns,
246
+ raw_records,
247
+ parse_records(raw_columns, raw_records),
292
248
  ]
293
249
  end
294
250
 
295
- def parse_match_records_v3(raw_records)
251
+ def parse_record_set_v3(raw_record_set)
252
+ n_hits = raw_record_set["n_hits"]
253
+ raw_columns = raw_record_set["columns"]
254
+ raw_records = raw_record_set["records"] || []
296
255
  [
297
- raw_records["n_hits"],
298
- parse_records(raw_records["columns"], raw_records["records"]),
256
+ n_hits,
257
+ raw_columns,
258
+ raw_records,
259
+ parse_records(raw_columns, raw_records),
299
260
  ]
300
261
  end
301
262
 
302
- def parse_drilldowns_v1(raw_drilldowns)
303
- request_drilldowns = @command.drilldowns
304
- if request_drilldowns.empty? and !@command.labeled_drilldowns.empty?
305
- drilldowns = {}
306
- (raw_drilldowns[0] || {}).each do |label, raw_drilldown|
307
- n_hits, records = parse_match_records_v1(raw_drilldown)
308
- drilldowns[label] = Drilldown.new(label, n_hits, records)
309
- end
310
- drilldowns
311
- else
312
- (raw_drilldowns || []).collect.with_index do |raw_drilldown, i|
313
- key = request_drilldowns[i]
314
- n_hits, records = parse_match_records_v1(raw_drilldown)
315
- Drilldown.new(key, n_hits, records)
316
- end
317
- end
318
- end
319
-
320
- def parse_drilldowns_v3(raw_drilldowns)
321
- drilldowns = {}
322
- (raw_drilldowns || {}).each do |key, raw_drilldown|
323
- n_hits, records = parse_match_records_v3(raw_drilldown)
324
- drilldowns[key] = Drilldown.new(key, n_hits, records)
325
- end
326
- drilldowns
327
- end
328
-
329
263
  def parse_slices_v1(raw_slices)
330
264
  slices = {}
331
265
  (raw_slices || {}).each do |key, raw_slice|
332
- n_hits, records = parse_match_records_v1(raw_slice)
333
- slices[key] = Slice.new(key, n_hits, records)
266
+ requested_slice = @command.slices[key]
267
+ if raw_slice.last.is_a?(::Hash)
268
+ raw_drilldowns = raw_slice.last
269
+ raw_slice = raw_slice[0..-2]
270
+ drilldowns =
271
+ parse_labeled_drilldowns(requested_slice.labeled_drilldowns,
272
+ raw_drilldowns)
273
+ else
274
+ drilldowns = {}
275
+ end
276
+ n_hits, _, _, records = parse_record_set_v1(raw_slice)
277
+ slices[key] = Slice.new(key, n_hits, records, drilldowns)
334
278
  end
335
279
  slices
336
280
  end
@@ -338,22 +282,17 @@ module Groonga
338
282
  def parse_slices_v3(raw_slices)
339
283
  slices = {}
340
284
  (raw_slices || {}).each do |key, raw_slice|
341
- n_hits, records = parse_match_records_v3(raw_slice)
342
- slices[key] = Slice.new(key, n_hits, records)
285
+ requested_slice = @command.slices[key]
286
+ n_hits, _, _, records = parse_record_set_v3(raw_slice)
287
+ drilldowns =
288
+ parse_labeled_drilldowns(requested_slice.labeled_drilldowns,
289
+ raw_slice["drilldowns"])
290
+ slices[key] = Slice.new(key, n_hits, records, drilldowns)
343
291
  end
344
292
  slices
345
293
  end
346
294
 
347
- class Record < ::Hash
348
- include Hashie::Extensions::MethodAccess
349
- end
350
-
351
- class Drilldown < Struct.new(:key, :n_hits, :records)
352
- # @deprecated since 0.2.6. Use {#records} instead.
353
- alias_method :items, :records
354
- end
355
-
356
- class Slice < Struct.new(:key, :n_hits, :records)
295
+ class Slice < Struct.new(:key, :n_hits, :records, :drilldowns)
357
296
  end
358
297
  end
359
298
  end