meilisearch-rails 0.11.1 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 75f8a8a3ebfe381cbb7c9b40072dcf859882ccf9bf78bc5bb8ab0b94c05231d9
4
- data.tar.gz: b3b5ec98f2524a08c738847a6b70671201f27cf466a62730f1aabbb0e177e08e
3
+ metadata.gz: 6f0751c88921f9665ac4a8d2f74d401c99eff1e1a82e16831196044725e8b01a
4
+ data.tar.gz: 4566fa5403529656cb21262456472fc4ec4d4c103ae750d2b48fc9076ff9c03c
5
5
  SHA512:
6
- metadata.gz: 5602abb0df9c02912553d45b6afbef167b735e1a585e5f19484b2bc0a38f366b34d2081130cd0e6257b3228023798e4e36ea5bbea85e5e9a1beed60370f7f0e4
7
- data.tar.gz: d40ba9defa8b7eeb754a8aff10ad9dfccdef04911c867a89c8a7d236c183582e60100573a1305e76e52da4d871d7a59d3413f0c8e0cdfe50405bb8f43072fdac
6
+ metadata.gz: b1302ec85a68c7774c2d31304738fbaec99845dd5993bfa2d414ac74e1647e833ffa624411670432cce4fb8335766bcfd684d04be4065397ef9d593692f0f080
7
+ data.tar.gz: 8b45f8cdd06fcf7b75f6d5d5dbffc1266650e69c8a30e49e018ca42f51bf7445b2ef8b357280691bea526628dfc7b0a40f0704f48c9545ba4e2933908e152d3f
data/Gemfile CHANGED
@@ -31,7 +31,7 @@ group :test do
31
31
  gem 'jdbc-sqlite3', platform: :jruby
32
32
  gem 'rspec', '~> 3.0'
33
33
  gem 'simplecov', require: 'false'
34
- gem 'codecov', require: 'false'
34
+ gem 'simplecov-cobertura', require: 'false'
35
35
  gem 'threads'
36
36
 
37
37
  gem 'byebug'
data/README.md CHANGED
@@ -38,6 +38,7 @@
38
38
  - [Compatibility](#-compatibility)
39
39
  - [⚙️ Settings](#️-settings)
40
40
  - [🔍 Custom search](#-custom-search)
41
+ - [🔍🔍 Multi search](#-multi-search)
41
42
  - [🪛 Options](#-options)
42
43
  - [Meilisearch configuration & environment](#meilisearch-configuration--environment)
43
44
  - [Pagination with `kaminari` or `will_paginate`](#backend-pagination-with-kaminari-or-will_paginate-)
@@ -206,6 +207,7 @@ class Book < ApplicationRecord
206
207
  crop_length 10
207
208
  faceting max_values_per_facet: 2000
208
209
  pagination max_total_hits: 1000
210
+ proximity_precision 'byWord'
209
211
  end
210
212
  end
211
213
  ```
@@ -229,7 +231,7 @@ harry_book.formatted # => {"id"=>"1", "name"=>"<em>Harry</em> Potter", "descript
229
231
  👉 Don't forget that `attributes_to_highlight`, `attributes_to_crop`, and
230
232
  `crop_length` can be set up in the `meilisearch` block of your model.
231
233
 
232
- ## 🔍 Sorted search
234
+ ### 🔍 Sorted search
233
235
 
234
236
  As an example of how to use the sort option, here is how you could achieve
235
237
  returning all books sorted by title in ascending order:
@@ -240,6 +242,58 @@ Book.search('*', sort: ['title:asc'])
240
242
 
241
243
  👉 Don't forget to set up the `sortable_attributes` option in the `meilisearch` block of your model.
242
244
 
245
+ ## 🔍🔍 Multi search
246
+
247
+ Meilisearch supports searching multiple models at the same time (see [🔍 Custom search](#-custom-search) for search options):
248
+
249
+ ```ruby
250
+ multi_search_results = MeiliSearch::Rails.multi_search(
251
+ Book => { q: 'Harry' },
252
+ Manga => { q: 'Attack' }
253
+ )
254
+ ```
255
+
256
+ You can iterate through the results with `.each` or `.each_result`:
257
+
258
+ ```erb
259
+ <% multi_search_results.each do |record| %>
260
+ <p><%= record.title %></p>
261
+ <p><%= record.author %></p>
262
+ <% end %>
263
+
264
+ <p>Harry Potter and the Philosopher's Stone</p>
265
+ <p>J. K. Rowling</p>
266
+ <p>Harry Potter and the Chamber of Secrets</p>
267
+ <p>J. K. Rowling</p>
268
+ <p>Attack on Titan</p>
269
+ <p>Iseyama</p>
270
+ ```
271
+
272
+ ```erb
273
+ <% multi_search_results.each_result do |klass, results| %>
274
+ <p><%= klass.name.pluralize %></p>
275
+
276
+ <ul>
277
+ <% results.each do |record| %>
278
+ <li><%= record.title %></li>
279
+ <% end %>
280
+ </ul>
281
+ <% end %>
282
+
283
+
284
+ <p>Books</p>
285
+ <ul>
286
+ <li>Harry Potter and the Philosopher's Stone</li>
287
+ <li>Harry Potter and the Chamber of Secrets</li>
288
+ </ul>
289
+ <p>Mangas</p>
290
+ <ul>
291
+ <li>Attack on Titan</li>
292
+ </ul>
293
+ ```
294
+
295
+ See the [official multi search documentation](https://www.meilisearch.com/docs/reference/api/multi_search).
296
+
243
297
  ## 🪛 Options
244
298
 
245
299
  ### Meilisearch configuration & environment
@@ -0,0 +1,84 @@
1
+ module MeiliSearch
2
+ module Rails
3
+ class MultiSearchResult
4
+ attr_reader :metadata
5
+
6
+ def initialize(searches, raw_results)
7
+ @results = {}
8
+ @metadata = {}
9
+
10
+ searches.zip(raw_results['results']).each do |(index_target, search_options), result|
11
+ index_target = search_options[:class_name].constantize if search_options[:class_name]
12
+
13
+ @results[index_target] = case index_target
14
+ when String, Symbol
15
+ result['hits']
16
+ else
17
+ load_results(index_target, result)
18
+ end
19
+
20
+ @metadata[index_target] = result.except('hits')
21
+ end
22
+ end
23
+
24
+ include Enumerable
25
+
26
+ def each_hit(&block)
27
+ @results.each do |_index_target, results|
28
+ results.each(&block)
29
+ end
30
+ end
31
+ alias each each_hit
32
+
33
+ def each_result
34
+ @results.each
35
+ end
36
+
37
+ def to_a
38
+ @results.values.flatten(1)
39
+ end
40
+ alias to_ary to_a
41
+
42
+ def to_h
43
+ @results
44
+ end
45
+ alias to_hash to_h
46
+
47
+ private
48
+
49
+ def load_results(klass, result)
50
+ pk_method = klass.ms_primary_key_method
51
+ pk_method = pk_method.in if Utilities.mongo_model?(klass)
52
+
53
+ condition_key = pk_is_virtual?(klass, pk_method) ? klass.primary_key : pk_method
54
+
55
+ hits_by_id =
56
+ result['hits'].index_by { |hit| hit[condition_key.to_s] }
57
+
58
+ records = klass.where(condition_key => hits_by_id.keys)
59
+
60
+ if records.respond_to? :in_order_of
61
+ records.in_order_of(condition_key, hits_by_id.keys).each do |record|
62
+ record.formatted = hits_by_id[record.send(condition_key).to_s]['_formatted']
63
+ end
64
+ else
65
+ results_by_id = records.index_by do |hit|
66
+ hit.send(condition_key).to_s
67
+ end
68
+
69
+ result['hits'].filter_map do |hit|
70
+ record = results_by_id[hit[condition_key.to_s].to_s]
71
+ record&.formatted = hit['_formatted']
72
+ record
73
+ end
74
+ end
75
+ end
76
+
77
+ def pk_is_virtual?(model_class, pk_method)
78
+ model_class.columns
79
+ .map(&(Utilities.sequel_model?(model_class) ? :to_s : :name))
80
+ .exclude?(pk_method.to_s)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,49 @@
1
+ require_relative 'multi_search/result'
2
+
3
+ module MeiliSearch
4
+ module Rails
5
+ class << self
6
+ def multi_search(searches)
7
+ search_parameters = searches.map do |(index_target, options)|
8
+ paginate(options) if pagination_enabled?
9
+ normalize(options, index_target)
10
+ end
11
+
12
+ MultiSearchResult.new(searches, client.multi_search(search_parameters))
13
+ end
14
+
15
+ private
16
+
17
+ def normalize(options, index_target)
18
+ options
19
+ .except(:class_name)
20
+ .merge!(index_uid: index_uid_from_target(index_target))
21
+ end
22
+
23
+ def index_uid_from_target(index_target)
24
+ case index_target
25
+ when String, Symbol
26
+ index_target
27
+ else
28
+ index_target.index.uid
29
+ end
30
+ end
31
+
32
+ def paginate(options)
33
+ %w[page hitsPerPage hits_per_page].each do |key|
34
+ # Deletes hitsPerPage to avoid passing along a meilisearch-ruby warning/exception
35
+ value = options.delete(key) || options.delete(key.to_sym)
36
+ options[key.underscore.to_sym] = value.to_i if value
37
+ end
38
+
39
+ # It is required to activate the finite pagination in Meilisearch v0.30 (or newer),
40
+ # to have at least `hits_per_page` defined or `page` in the search request.
41
+ options[:page] ||= 1
42
+ end
43
+
44
+ def pagination_enabled?
45
+ MeiliSearch::Rails.configuration[:pagination_backend]
46
+ end
47
+ end
48
+ end
49
+ end
@@ -48,6 +48,14 @@ module MeiliSearch
48
48
  true
49
49
  end
50
50
 
51
+ def mongo_model?(model_class)
52
+ defined?(::Mongoid::Document) && model_class.include?(::Mongoid::Document)
53
+ end
54
+
55
+ def sequel_model?(model_class)
56
+ defined?(::Sequel::Model) && model_class < Sequel::Model
57
+ end
58
+
51
59
  private
52
60
 
53
61
  def constraint_passes?(record, constraint)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module MeiliSearch
4
4
  module Rails
5
- VERSION = '0.11.1'
5
+ VERSION = '0.13.0'
6
6
 
7
7
  def self.qualified_version
8
8
  "Meilisearch Rails (v#{VERSION})"
@@ -3,6 +3,7 @@ require 'meilisearch/rails/null_object'
3
3
  require 'meilisearch/rails/version'
4
4
  require 'meilisearch/rails/utilities'
5
5
  require 'meilisearch/rails/errors'
6
+ require 'meilisearch/rails/multi_search'
6
7
 
7
8
  if defined? Rails
8
9
  begin
@@ -66,6 +67,7 @@ module MeiliSearch
66
67
  pagination
67
68
  faceting
68
69
  typo_tolerance
70
+ proximity_precision
69
71
  ].freeze
70
72
 
71
73
  CAMELIZE_OPTIONS = %i[pagination faceting typo_tolerance].freeze
@@ -575,7 +577,7 @@ module MeiliSearch
575
577
  ms_configurations.filter_map do |options, settings|
576
578
  {
577
579
  synchronous: synchronous || options[:synchronous],
578
- index_uid: options[:index_uid],
580
+ index_uid: ms_index_uid(options),
579
581
  primary_key: primary_key
580
582
  }.with_indifferent_access unless ms_indexing_disabled?(options)
581
583
  end
@@ -760,6 +762,11 @@ module MeiliSearch
760
762
  false
761
763
  end
762
764
 
765
+ def ms_primary_key_method(options = nil)
766
+ options ||= meilisearch_options
767
+ options[:primary_key] || options[:id] || :id
768
+ end
769
+
763
770
  protected
764
771
 
765
772
  def ms_ensure_init(options = meilisearch_options, settings = meilisearch_settings, user_configuration = settings.to_settings)
@@ -814,11 +821,6 @@ module MeiliSearch
814
821
  @configurations
815
822
  end
816
823
 
817
- def ms_primary_key_method(options = nil)
818
- options ||= meilisearch_options
819
- options[:primary_key] || options[:id] || :id
820
- end
821
-
822
824
  def ms_primary_key_of(doc, options = nil)
823
825
  doc.send(ms_primary_key_method(options)).to_s
824
826
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meilisearch-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.1
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Meili
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-26 00:00:00.000000000 Z
11
+ date: 2024-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: meilisearch
@@ -42,6 +42,8 @@ files:
42
42
  - lib/meilisearch/rails/errors.rb
43
43
  - lib/meilisearch/rails/ms_clean_up_job.rb
44
44
  - lib/meilisearch/rails/ms_job.rb
45
+ - lib/meilisearch/rails/multi_search.rb
46
+ - lib/meilisearch/rails/multi_search/result.rb
45
47
  - lib/meilisearch/rails/null_object.rb
46
48
  - lib/meilisearch/rails/pagination.rb
47
49
  - lib/meilisearch/rails/pagination/kaminari.rb