Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scope based upsert or delete #1258

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 34 additions & 8 deletions lib/thinking_sphinx/processor.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# frozen_string_literal: true

class ThinkingSphinx::Processor
# @param instance [ActiveRecord::Base] an ActiveRecord object
# @param model [Class] the ActiveRecord model of the instance
# @param id [Integer] the instance indices primary key (might be different from model primary key)
def initialize(instance: nil, model: nil, id: nil)
raise ArgumentError if instance.nil? && (model.nil? || id.nil?)

Expand All @@ -12,16 +15,27 @@ def initialize(instance: nil, model: nil, id: nil)
def delete
return if instance&.new_record?

indices.each { |index|
ThinkingSphinx::Deletion.perform(
index, id || instance.public_send(index.primary_key)
)
}
indices.each { |index| perform_deletion(index) }
end

# Will insert instance into all matching indices
def upsert
real_time_indices.each do |index|
ThinkingSphinx::RealTime::Transcriber.new(index).copy loaded_instance
found = loaded_instance(index)
ThinkingSphinx::RealTime::Transcriber.new(index).copy found if found
end
end

# Will upsert or delete instance into all matching indices based on index scope
def stage
real_time_indices.each do |index|
found = find_in(index)

if found
ThinkingSphinx::RealTime::Transcriber.new(index).copy found
else
ThinkingSphinx::Deletion.perform(index, index_id(index))
end
end
end

Expand All @@ -35,11 +49,23 @@ def indices
).to_a
end

def loaded_instance
@loaded_instance ||= instance || model.find(id)
def find_in(index)
index.scope.find_by(index.primary_key => index_id(index))
end

def loaded_instance(index)
instance || find_in(index)
end

def real_time_indices
indices.select { |index| index.is_a? ThinkingSphinx::RealTime::Index }
end

def perform_deletion(index)
ThinkingSphinx::Deletion.perform(index, index_id(index))
end

def index_id(index)
id || instance.public_send(index.primary_key)
end
end
62 changes: 61 additions & 1 deletion spec/acceptance/real_time_updates_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
expect(Admin::Person.search('Mort').to_a).to eq([person])
end

it "can use a direct interface for processing records" do
it "can use direct interface for upserting records" do
Admin::Person.connection.execute <<~SQL
INSERT INTO admin_people (name, created_at, updated_at)
VALUES ('Pat', now(), now());
Expand All @@ -52,4 +52,64 @@

expect(Admin::Person.search('Patrick').to_a).to eq([instance])
end

it "can use direct interface for processing records outside scope" do
Article.connection.execute <<~SQL
INSERT INTO articles (title, published, created_at, updated_at)
VALUES ('Nice Title', TRUE, now(), now());
SQL

article = Article.last

ThinkingSphinx::Processor.new(model: article.class, id: article.id).stage

expect(ThinkingSphinx.search('Nice', :indices => ["published_articles_core"])).to include(article)

Article.connection.execute <<~SQL
UPDATE articles SET published = FALSE WHERE title = 'Nice Title';
SQL
ThinkingSphinx::Processor.new(model: article.class, id: article.id).stage

expect(ThinkingSphinx.search('Nice', :indices => ["published_articles_core"])).to be_empty
end

it "can use direct interface for processing deleted records" do
Article.connection.execute <<~SQL
INSERT INTO articles (title, published, created_at, updated_at)
VALUES ('Nice Title', TRUE, now(), now());
SQL

article = Article.last
ThinkingSphinx::Processor.new(:instance => article).stage

expect(ThinkingSphinx.search('Nice', :indices => ["published_articles_core"])).to include(article)

Article.connection.execute <<~SQL
DELETE FROM articles where title = 'Nice Title';
SQL

ThinkingSphinx::Processor.new(:instance => article).stage

expect(ThinkingSphinx.search('Nice', :indices => ["published_articles_core"])).to be_empty
end

it "stages records in real-time index with alternate ids" do
Album.connection.execute <<~SQL
INSERT INTO albums (id, name, artist, integer_id)
VALUES ('#{("a".."z").to_a.sample}', 'Sing to the Moon', 'Laura Mvula', #{rand(10000)});
SQL

album = Album.last
ThinkingSphinx::Processor.new(:model => Album, id: album.integer_id).stage

expect(ThinkingSphinx.search('Laura', :indices => ["album_real_core"])).to include(album)

Article.connection.execute <<~SQL
DELETE FROM albums where id = '#{album.id}';
SQL

ThinkingSphinx::Processor.new(:instance => album).stage

expect(ThinkingSphinx.search('Laura', :indices => ["album_real_core"])).to be_empty
end
end
6 changes: 6 additions & 0 deletions spec/internal/app/indices/article_index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@

set_property :morphology => 'stem_en'
end

ThinkingSphinx::Index.define :article, :name => :published_articles, :with => :real_time do
indexes title, content

scope { Article.where :published => true }
end
Loading