Index Tags to Elasticsearch after they are created (#5958) [deploy]

* Index tags to Elasticsearch after they are created
* add rules_html to Tag index since we show it in search drop down
* change get method to find_document to make it more explicit
This commit is contained in:
Molly Struve 2020-02-11 11:58:58 -05:00 committed by GitHub
parent 38e980917d
commit 3fed9338d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 106 additions and 8 deletions

View file

@ -26,7 +26,7 @@ class Tag < ActsAsTaggableOn::Tag
before_validation :evaluate_markdown
before_validation :pound_it
before_save :calculate_hotness_score
after_commit :bust_cache
after_commit :bust_cache, :index_to_elasticsearch
before_save :mark_as_updated
algoliasearch per_environment: true do
@ -36,6 +36,22 @@ class Tag < ActsAsTaggableOn::Tag
searchableAttributes %w[name short_summary]
end
def index_to_elasticsearch
Search::TagEsIndexWorker.perform_async(id)
end
def index_to_elasticsearch_inline
Search::Tag.index(id, serialized_search_hash)
end
def serialized_search_hash
Search::TagSerializer.new(self).serializable_hash.dig(:data, :attributes)
end
def elasticsearch_doc
Search::Tag.find_document(id)
end
def submission_template_customized(param_0 = nil)
submission_template&.gsub("PARAM_0", param_0)
end

View file

@ -0,0 +1,7 @@
module Search
class TagSerializer
include FastJsonapi::ObjectSerializer
attributes :id, :name, :hotness_score, :supported, :short_summary, :rules_html
end
end

View file

@ -12,7 +12,7 @@ module Search
)
end
def get(tag_id)
def find_document(tag_id)
SearchClient.get(id: tag_id, index: INDEX_ALIAS)
end
@ -75,6 +75,9 @@ module Search
},
short_summary: {
type: "text"
},
rules_html: {
type: "text"
}
}
}

View file

@ -0,0 +1,12 @@
module Search
class TagEsIndexWorker
include Sidekiq::Worker
sidekiq_options queue: :high_priority
def perform(tag_id)
tag = ::Tag.find_by!(id: tag_id)
tag.index_to_elasticsearch_inline
end
end
end

View file

@ -75,4 +75,44 @@ RSpec.describe Tag, type: :model do
tag.mod_chat_channel_id = channel.id
expect(tag.mod_chat_channel).to eq(channel)
end
describe "#index_to_elasticsearch" do
it "enqueues job to index tag to elasticsearch" do
sidekiq_assert_enqueued_with(job: Search::TagEsIndexWorker, args: [tag.id]) do
tag.index_to_elasticsearch
end
end
end
describe "#index_to_elasticsearch_inline" do
it "indexed tag to elasticsearch inline" do
allow(Search::Tag).to receive(:index)
tag.index_to_elasticsearch_inline
expect(Search::Tag).to have_received(:index).with(tag.id, hash_including(:id, :name))
end
end
describe "#after_commit" do
it "enqueues job to index tag to elasticsearch" do
tag.save
sidekiq_assert_enqueued_with(job: Search::TagEsIndexWorker, args: [tag.id]) do
tag.save
end
end
end
describe "#serialized_search_hash" do
it "creates a valid serialized hash to send to elasticsearch" do
mapping_keys = Search::Tag.send("mappings").dig(:properties).keys
expect(tag.serialized_search_hash.symbolize_keys.keys).to eq(mapping_keys)
end
end
describe "#elasticsearch_doc" do
it "finds document in elasticsearch", elasticsearch: true do
allow(Search::Tag).to receive(:find_document)
tag.elasticsearch_doc
expect(Search::Tag).to have_received(:find_document)
end
end
end

View file

@ -4,17 +4,17 @@ RSpec.describe Search::Tag, type: :service, elasticsearch: true do
describe "::index" do
it "indexes a tag to elasticsearch" do
tag = FactoryBot.create(:tag)
expect { described_class.get(tag.id) }.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
described_class.index(tag.id, id: tag.id)
expect(described_class.get(tag.id)).not_to be_nil
expect { described_class.find_document(tag.id) }.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
described_class.index(tag.id, tag.serialized_search_hash)
expect(described_class.find_document(tag.id)).not_to be_nil
end
end
describe "::get" do
describe "::find_document" do
it "fetches a document for a given ID from elasticsearch" do
tag = FactoryBot.create(:tag)
described_class.index(tag.id, id: tag.id)
expect { described_class.get(tag.id) }.not_to raise_error
described_class.index(tag.id, tag.serialized_search_hash)
expect { described_class.find_document(tag.id) }.not_to raise_error
end
end

View file

@ -0,0 +1,20 @@
require "rails_helper"
RSpec.describe Search::TagEsIndexWorker, type: :worker, elasticsearch: true do
let(:worker) { subject }
include_examples "#enqueues_on_correct_queue", "high_priority", [1]
it "raises an error if record is not found" do
expect { worker.perform(1234) }.to raise_error(ActiveRecord::RecordNotFound)
end
it "indexes tag" do
tag = FactoryBot.create(:tag)
expect { tag.elasticsearch_doc }.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
worker.perform(tag.id)
expect(tag.elasticsearch_doc.dig("_source")).to eq(
tag.serialized_search_hash.stringify_keys,
)
end
end