Powering Actions with Elasticsearch Percolate
by Ben Ubois
Actions are built on a great feature of elasticsearch called percolate.
Percolate allows you to register queries ahead of time, then whenever you send a new document to be indexed, elasticsearch can tell you if this document matches any saved queries.
Here’s how it works.
Feedbin is a Rails app and uses the tire gem for working with elasticsearch.
Whenever an action is added or updated, it is also sent to elasticsearch as a percolator query.
Entry.index.register_percolator_query(3) do
string "kittens"
end
The 3
is the id of this action. This is used later on to find what user this action belongs to and which actions should be performed.
A model called Entry
is used for storing RSS articles. Whenever a new entry is added it also gets sent to elasticsearch for indexing.
class Entry < ActiveRecord::Base
include Tire::Model::Search
after_commit :search_index_store, on: :create
private
def search_index_store
result = self.index.store(self, {percolate: true})
ActionsPerform.perform_async(self.id, result['matches'])
end
end
An array of matched actions ids is returned in result['matches']
. So if this entry mentions “kittens” an array like ["3"]
would be returned.
Feedbin uses Sidekiq to process background jobs. The ActionsPerform.perform_async
part is creating a new background job that performs the actions. A simplified version of this looks like:
class ActionsPerform
include Sidekiq::Worker
def perform(entry_id, action_ids)
actions = Action.where(id: action_ids)
actions.each do |action|
if action.actions.include?("send_push_notification")
PushNotificationSend.perform_async(entry_id, user_ids)
end
end
end
end
Get in touch if you have any questions about this or sign up to see it in action.