add meilisearch

this thing is way too fast!  only downside is that indexing takes a bit
longer, and the search indexes are big (16Gi for 2.7 million records)

i have no idea how to properly integrate it in the UI, but it seems
promising :^)
This commit is contained in:
Georg Gadinger 2023-10-22 19:39:18 +02:00
parent d5c1e66b1e
commit 44871cbf4a
9 changed files with 63 additions and 19 deletions

View file

@ -119,3 +119,4 @@ gem "mail", "~> 2.7.1"
gem "prometheus-client", "~> 4.2"
gem "meilisearch-rails", "~> 0.10.1"

View file

@ -249,6 +249,10 @@ GEM
mail (2.7.1)
mini_mime (>= 0.1.1)
marcel (1.0.2)
meilisearch (0.25.1)
httparty (>= 0.17.1, < 0.22.0)
meilisearch-rails (0.10.1)
meilisearch (~> 0.25.0)
method_source (1.0.0)
mime-types (3.5.1)
mime-types-data (~> 3.2015)
@ -535,6 +539,7 @@ DEPENDENCIES
letter_opener
lograge
mail (~> 2.7.1)
meilisearch-rails (~> 0.10.1)
mini_magick
net-imap
net-pop

View file

@ -2,3 +2,4 @@ web: unset PORT && bin/rails server
worker: bundle exec sidekiq
css: yarn build:css --watch
js: yarn build --watch
search: meilisearch --no-analytics --env development --db-path tmp/meilisearch/db --dump-dir tmp/meilisearch/dump --master-key justfordev42069e621

View file

@ -1,9 +1,35 @@
class SearchController < ApplicationController
def index
@results = []
query = params[:q]
return if query.blank?
@query = params[:q]
return if @query.blank?
@results = []
@results = if params[:multi_search] == "1"
multi_search_experiment
else
[*Answer.search(@query), *Question.search(@query)]
end
end
private
def multi_search_experiment
MeiliSearch::Rails.client.multi_search(
[Answer, Question].map do |klass|
{
q: @query,
index_uid: klass.name.to_s,
show_ranking_score: true,
}
end
)["results"].flat_map do |h|
model = h["indexUid"].constantize # bad practice!
results = model.find(h["hits"].pluck("id")).map { |r| [r.id.to_s, r] }.to_h
h["hits"].map { |hit| [hit["_rankingScore"], results[hit["id"]]] }
end
.sort_by(&:first)
.reverse
.tap { |results| Rails.logger.debug(results) }
.map(&:last)
end
end

View file

@ -1,6 +1,12 @@
class Answer < ApplicationRecord
extend Answer::TimelineMethods
include MeiliSearch::Rails
meilisearch do
attribute :content
end
belongs_to :user, counter_cache: :answered_count
belongs_to :question, counter_cache: :answer_count
has_many :comments, dependent: :destroy

View file

@ -1,6 +1,12 @@
class Question < ApplicationRecord
include Question::AnswerMethods
include MeiliSearch::Rails
meilisearch do
attribute :content
end
belongs_to :user, optional: true
has_many :answers, dependent: :destroy
has_many :inboxes, dependent: :destroy

View file

@ -3,18 +3,19 @@
.col-sm-10.col-md-10.col-lg-9.mx-auto
.card
.card-body
= bootstrap_form_tag layout: :inline, method: :get do |f|
= f.text_field :q, skip_label: true, append: f.primary("Search")
= bootstrap_form_with url: search_path, layout: :inline, method: :get do |f|
= f.text_field :q, skip_label: true, append: f.primary("Search"), value: params[:q]
= f.check_box :multi_search, label: "Multisearch"
- unless @results.blank?
.container-lg.container--main
.row
.col-sm-10.col-md-10.col-lg-9.mx-auto
- @results.each do |result|
- case result.searchable
- case result
- when Answer
= render "answerbox", a: result.searchable, display_all: false, subscribed_answer_ids: []
= render "answerbox", a: result, display_all: false, subscribed_answer_ids: []
- when Question
= render "shared/question", q: result.searchable, type: nil
= render "shared/question", q: result, type: nil
= render 'shared/links'

View file

@ -0,0 +1,8 @@
# frozen_string_literal: true
return unless ENV["SEARCH_ENABLED"] == "true"
MeiliSearch::Rails.configuration = {
meilisearch_url: ENV.fetch("MEILISEARCH_HOST", "http://localhost:7700"),
meilisearch_api_key: ENV.fetch("MEILISEARCH_API_KEY", "justfordev42069e621")
}

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2023_10_22_155815) do
ActiveRecord::Schema.define(version: 2023_10_18_172518) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -127,15 +127,6 @@ ActiveRecord::Schema.define(version: 2023_10_22_155815) do
t.index ["type"], name: "index_notifications_on_type"
end
create_table "pg_search_documents", force: :cascade do |t|
t.text "content"
t.string "searchable_type"
t.bigint "searchable_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["searchable_type", "searchable_id"], name: "index_pg_search_documents_on_searchable"
end
create_table "profiles", force: :cascade do |t|
t.bigint "user_id"
t.string "display_name"
@ -397,6 +388,5 @@ ActiveRecord::Schema.define(version: 2023_10_22_155815) do
t.index ["user_id"], name: "index_web_push_subscriptions_on_user_id"
end
add_foreign_key "anonymous_blocks", "users", column: "target_user_id"
add_foreign_key "profiles", "users"
end