3aa4a1a562
Create search_index_0 to search_index_15 tables and shard each index by account id. MySQL has no ability to pre-filter fulltext indexes by another field so this is the best bet for improving performance. Each fulltest index internally creates 11 sub tables (see https://dev.mysql.com/doc/refman/8.4/en/innodb-fulltext-index.html) so actually we have 192 tables in total here. The search_index table name is generated dynamically based on the account_id.
67 lines
1.9 KiB
Ruby
67 lines
1.9 KiB
Ruby
module Searchable
|
|
extend ActiveSupport::Concern
|
|
|
|
def self.search_index_table_name(account_id)
|
|
"search_index_#{account_id % 16}"
|
|
end
|
|
|
|
included do
|
|
after_create_commit :create_in_search_index
|
|
after_update_commit :update_in_search_index
|
|
after_destroy_commit :remove_from_search_index
|
|
end
|
|
|
|
def reindex
|
|
update_in_search_index
|
|
end
|
|
|
|
private
|
|
def create_in_search_index
|
|
table_name = Searchable.search_index_table_name(account_id)
|
|
|
|
self.class.connection.execute self.class.sanitize_sql([
|
|
"INSERT INTO #{table_name} (searchable_type, searchable_id, card_id, board_id, title, content, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
self.class.name,
|
|
id,
|
|
search_card_id,
|
|
search_board_id,
|
|
search_title,
|
|
search_content,
|
|
created_at
|
|
])
|
|
end
|
|
|
|
def update_in_search_index
|
|
table_name = Searchable.search_index_table_name(account_id)
|
|
|
|
result = self.class.connection.execute(self.class.sanitize_sql([
|
|
"UPDATE #{table_name} SET card_id = ?, board_id = ?, title = ?, content = ?, created_at = ? WHERE searchable_type = ? AND searchable_id = ?",
|
|
search_card_id,
|
|
search_board_id,
|
|
search_title,
|
|
search_content,
|
|
created_at,
|
|
self.class.name,
|
|
id
|
|
]))
|
|
|
|
create_in_search_index if result.affected_rows == 0
|
|
end
|
|
|
|
def remove_from_search_index
|
|
table_name = Searchable.search_index_table_name(account_id)
|
|
|
|
self.class.connection.execute self.class.sanitize_sql([
|
|
"DELETE FROM #{table_name} WHERE searchable_type = ? AND searchable_id = ?",
|
|
self.class.name,
|
|
id
|
|
])
|
|
end
|
|
|
|
# Models must implement these methods:
|
|
# - search_title: returns title string or nil
|
|
# - search_content: returns content string
|
|
# - search_card_id: returns the card id (self.id for cards, card_id for comments)
|
|
# - search_board_id: returns the board id
|
|
end
|