meilisearch / meilisearch-rails

Meilisearch integration for Ruby on Rails
https://www.meilisearch.com
MIT License
295 stars 48 forks source link

Polymorphic shared indexes #340

Closed ellnix closed 6 months ago

ellnix commented 6 months ago

Description The current implementation of shared indexes is deeply flawed, it:


require 'bundler/inline'

gemfile do
  gem "rails", "~> 7.1.3"
  gem "sqlite3", "~> 1.4"
  gem "meilisearch-rails", "~> 0.11.1"
end

MeiliSearch::Rails.configuration = {
  meilisearch_url: ENV.fetch('MEILISEARCH_HOST', 'http://localhost:7700'),
  meilisearch_api_key: ENV.fetch('MEILISEARCH_API_KEY', 'masterKey')
}

FileUtils.rm('data.sqlite3') if File.exist?('data.sqlite3')

require 'active_record'

ActiveRecord::Base.establish_connection(
  'adapter' => defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3',
  'database' => 'data.sqlite3',
  'pool' => 5,
  'timeout' => 5000
)

ActiveRecord::Schema.define do
  create_table(:dogs) { |t| t.string :name }
end

class Dog < ActiveRecord::Base
  include MeiliSearch::Rails

  meilisearch index_uid: 'animals', primary_key: :ms_id

  def ms_id
    "dog_#{id}"
  end
end

Dog.create name: 'toby' 
Dog.create name: 'spikey'
Dog.create name: 'doggy'

sleep 0.5

p Dog.search 'dog' # Will return all dogs

These problems stem from the fact that the custom primary key cannot be used for lookup or to know the model name of the document in meilisearch.

Basic example

I would suggest instead of allowing the user to specify a primary key for a shared index, we instead allow them to pass a shared_index: 'index_name' option, which would add two non searchable fields in the meilisearch instance: _ms_model and _ms_pk. With this set up:

Example:

class Tiger < ActiveRecord::Base
  include MeiliSearch::Rails

  meilisearch shared_index: 'animals'
end

class Cat < ActiveRecord::Base
  include MeiliSearch::Rails

  meilisearch shared_index: 'animals'
end

class Puma
  include MeiliSearch::Rails

  meilisearch do
    add_shared_index 'animals'
  end
end

Tiger.create name: 'toby'
Cat.create name: 'tobias'
Puma.create name: 'tobs'

p Cat.search 'tob'
# [#<Tiger id: 1, name: "toby">, #<Cat id: 1, name: "tobias">, #<Puma id: 1, name: "tobs">]
brunoocasali commented 6 months ago

p Cat.search 'tob'

Even knowing the user defined the shared indexes everywhere, seems weird to me that they could have a polymorphic list of models while searching from one of the implementations in this case the Cat one.

I like the approach of #341 where we have a clear entity that is responsible for doing that.

ellnix commented 6 months ago

p Cat.search 'tob'

Even knowing the user defined the shared indexes everywhere, seems weird to me that they could have a polymorphic list of models while searching from one of the implementations in this case the Cat one.

Completely agreed, the only reason I suggested this version was if #341 was not good. Without either one of these two systems sharing an index between models seems like useless configuration (unless the meilisearch instance is also being used by something else).

ellnix commented 6 months ago

Closing in favor of #341