Skip to content

Commit

Permalink
Merge pull request #1840 from elzj/search_overhaul
Browse files Browse the repository at this point in the history
Issue 4044: Search overhaul, part 1
  • Loading branch information
zz9pzza committed Sep 15, 2014
2 parents 50f9689 + ab87444 commit 5b0c761
Show file tree
Hide file tree
Showing 24 changed files with 743 additions and 140 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ gem 'resque_mailer'
gem 'resque-scheduler', :require => 'resque_scheduler'
#gem 'daemon-spawn', :require => 'daemon_spawn'
gem 'tire'
gem 'elasticsearch'
gem 'aws-sdk'
gem 'css_parser'

Expand Down
12 changes: 12 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ GEM
docile (1.1.1)
domain_name (0.5.12)
unf (>= 0.0.5, < 1.0.0)
elasticsearch (1.0.5)
elasticsearch-api (= 1.0.5)
elasticsearch-transport (= 1.0.5)
elasticsearch-api (1.0.5)
multi_json
elasticsearch-transport (1.0.5)
faraday
multi_json
email_spec (1.5.0)
launchy (~> 2.1)
mail (~> 2.2)
Expand All @@ -106,6 +114,8 @@ GEM
activesupport (>= 3.0.0)
faker (1.1.2)
i18n (~> 0.5)
faraday (0.9.0)
multipart-post (>= 1.2, < 3)
fastimage (1.4.0)
gherkin (2.12.0)
multi_json (~> 1.3)
Expand Down Expand Up @@ -149,6 +159,7 @@ GEM
mono_logger (1.1.0)
multi_json (1.10.0)
multi_xml (0.5.5)
multipart-post (2.0.0)
mysql2 (0.3.11)
mysql2 (0.3.11-x86-mingw32)
net-http-digest_auth (1.3)
Expand Down Expand Up @@ -350,6 +361,7 @@ DEPENDENCIES
cucumber-rails
database_cleaner
delorean
elasticsearch
email_spec
escape_utils
factory_girl
Expand Down
85 changes: 36 additions & 49 deletions app/models/external_work.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,55 +7,6 @@ class ExternalWork < ActiveRecord::Base
attr_protected :summary_sanitizer_version

has_many :related_works, :as => :parent

has_many :taggings, :as => :taggable, :dependent => :destroy
has_many :tags, :through => :taggings, :source => :tagger, :source_type => 'Tag'

has_many :filter_taggings, :as => :filterable, :dependent => :destroy
has_many :filters, :through => :filter_taggings

has_many :ratings,
:through => :taggings,
:source => :tagger,
:source_type => 'Tag',
:before_remove => :remove_filter_tagging,
:conditions => "tags.type = 'Rating'"
has_many :categories,
:through => :taggings,
:source => :tagger,
:source_type => 'Tag',
:before_remove => :remove_filter_tagging,
:conditions => "tags.type = 'Category'"
has_many :warnings,
:through => :taggings,
:source => :tagger,
:source_type => 'Tag',
:before_remove => :remove_filter_tagging,
:conditions => "tags.type = 'Warning'"
has_many :fandoms,
:through => :taggings,
:source => :tagger,
:source_type => 'Tag',
:before_remove => :remove_filter_tagging,
:conditions => "tags.type = 'Fandom'"
has_many :relationships,
:through => :taggings,
:source => :tagger,
:source_type => 'Tag',
:before_remove => :remove_filter_tagging,
:conditions => "tags.type = 'Relationship'"
has_many :characters,
:through => :taggings,
:source => :tagger,
:source_type => 'Tag',
:before_remove => :remove_filter_tagging,
:conditions => "tags.type = 'Character'"
has_many :freeforms,
:through => :taggings,
:source => :tagger,
:source_type => 'Tag',
:before_remove => :remove_filter_tagging,
:conditions => "tags.type = 'Freeform'"

belongs_to :language

Expand Down Expand Up @@ -189,4 +140,40 @@ def tag_groups
self.tags.group_by { |t| t.type.to_s }
end

######################
# SEARCH
######################

def bookmarkable_json
as_json(
root: false,
only: [
:title, :summary, :hidden_by_admin, :created_at, :language_id
],
methods: [
:posted, :restricted, :tag, :filter_ids, :rating_ids,
:warning_ids, :category_ids, :fandom_ids, :character_ids,
:relationship_ids, :freeform_ids, :creators, :revised_at
]
).merge(bookmarkable_type: "ExternalWork")
end

def posted
true
end
alias_method :posted?, :posted

def restricted
false
end
alias_method :restricted?, :restricted

def creators
[author]
end

def revised_at
created_at
end

end
74 changes: 74 additions & 0 deletions app/models/search/bookmark_indexer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
class BookmarkIndexer < Indexer

def self.klass
'Bookmark'
end

def self.index_all(options={})
options[:skip_delete] = true
BookmarkableIndexer.delete_index
BookmarkableIndexer.create_index
create_mapping
BookmarkedExternalWorkIndexer.index_all(skip_delete: true)
BookmarkedSeriesIndexer.index_all(skip_delete: true)
BookmarkedWorkIndexer.index_all(skip_delete: true)
super
end

def self.mapping
{
"bookmark" => {
"_parent" => {
type: 'bookmarkable'
},
properties: {
bookmarkable_type: {
type: 'string',
index: 'not_analyzed'
},
bookmarker: {
type: 'string',
analyzer: 'simple'
},
notes: {
type: 'string',
analyzer: 'snowball'
},
tag: {
type: 'string',
analyzer: 'simple'
}
}
}
}
end

####################
# INSTANCE METHODS
####################

# TODO: Make this work for deleted bookmarks
def routing_info(id)
{
'_index' => index_name,
'_type' => document_type,
'_id' => id,
'parent' => objects[id.to_i].bookmarkable_id
}
end

def document(object)
tags = object.tags
filters = tags.map{ |t| t.filter }.compact

object.as_json(
root: false,
except: [:notes_sanitizer_version, :delta],
methods: [:bookmarker, :collection_ids, :with_notes]
).merge(
tag: (tags + filters).map(&:name).uniq,
tag_ids: tags.map(&:id),
filter_ids: filters.map(&:id)
)
end
end
2 changes: 2 additions & 0 deletions app/models/search/bookmark_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class BookmarkQuery < Query
end
50 changes: 50 additions & 0 deletions app/models/search/bookmarkable_indexer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
class BookmarkableIndexer < Indexer

def self.index_name
"ao3_#{Rails.env}_bookmarks"
end

def self.document_type
'bookmarkable'
end

def self.mapping
{
'bookmarkable' => {
properties: {
title: {
type: 'string',
analyzer: 'simple'
},
creators: {
type: 'string',
analyzer: 'simple',
index_name: 'creator'
},
tag: {
type: 'string',
analyzer: 'simple'
},
work_types: {
type: 'string',
index: 'not_analyzed',
index_name: 'work_type'
}
}
}
}
end

def routing_info(id)
{
'_index' => index_name,
'_type' => document_type,
'_id' => "#{id}-#{klass.underscore}"
}
end

def document(object)
object.bookmarkable_json
end

end
5 changes: 5 additions & 0 deletions app/models/search/bookmarked_external_work_indexer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class BookmarkedExternalWorkIndexer < BookmarkableIndexer
def self.klass
"ExternalWork"
end
end
5 changes: 5 additions & 0 deletions app/models/search/bookmarked_series_indexer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class BookmarkedSeriesIndexer < BookmarkableIndexer
def self.klass
"Series"
end
end
10 changes: 10 additions & 0 deletions app/models/search/bookmarked_work_indexer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class BookmarkedWorkIndexer < BookmarkableIndexer
def self.klass
"Work"
end

# Only index works with bookmarks
def self.indexables
Work.joins(:stat_counter).where("bookmarks_count > 0")
end
end
Loading

0 comments on commit 5b0c761

Please sign in to comment.