xapit 0.2.7 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{CHANGELOG → CHANGELOG.rdoc} +7 -2
- data/Gemfile +19 -0
- data/LICENSE +4 -4
- data/README.rdoc +61 -108
- data/Rakefile +11 -10
- data/features/facets.feature +93 -82
- data/features/finding.feature +196 -138
- data/features/indexing.feature +35 -37
- data/features/remote_server.feature +10 -0
- data/features/step_definitions/xapit_steps.rb +53 -25
- data/features/suggestions.feature +20 -14
- data/features/support/env.rb +13 -6
- data/features/support/xapit_helpers.rb +8 -9
- data/lib/generators/xapit/install_generator.rb +14 -0
- data/lib/generators/xapit/templates/xapit.ru +6 -0
- data/lib/generators/xapit/templates/xapit.yml +11 -0
- data/lib/xapit.rb +106 -64
- data/lib/xapit/client/collection.rb +150 -0
- data/lib/xapit/client/facet.rb +11 -0
- data/lib/xapit/client/facet_option.rb +29 -0
- data/lib/xapit/client/index_builder.rb +67 -0
- data/lib/xapit/client/membership.rb +46 -0
- data/lib/xapit/client/model_adapters/abstract_model_adapter.rb +30 -0
- data/lib/xapit/client/model_adapters/active_record_adapter.rb +27 -0
- data/lib/xapit/client/model_adapters/default_model_adapter.rb +7 -0
- data/lib/xapit/client/railtie.rb +18 -0
- data/lib/xapit/client/remote_database.rb +21 -0
- data/lib/xapit/client/tasks.rb +18 -0
- data/lib/xapit/server/app.rb +27 -0
- data/lib/xapit/server/database.rb +47 -0
- data/lib/xapit/server/indexer.rb +138 -0
- data/lib/xapit/server/query.rb +240 -0
- data/spec/fixtures/blankdb/flintlock +0 -0
- data/spec/fixtures/blankdb/iamchert +1 -0
- data/spec/fixtures/blankdb/postlist.DB +0 -0
- data/spec/fixtures/blankdb/postlist.baseA +0 -0
- data/spec/fixtures/blankdb/record.DB +0 -0
- data/spec/fixtures/blankdb/record.baseA +0 -0
- data/spec/fixtures/blankdb/termlist.DB +0 -0
- data/spec/fixtures/blankdb/termlist.baseA +0 -0
- data/spec/fixtures/xapit.ru +13 -0
- data/spec/fixtures/xapit.yml +4 -0
- data/spec/spec_helper.rb +8 -9
- data/spec/support/spec_macros.rb +6 -0
- data/spec/{xapit_member.rb → support/xapit_member.rb} +14 -16
- data/spec/xapit/client/collection_spec.rb +63 -0
- data/spec/xapit/client/facet_option_spec.rb +26 -0
- data/spec/xapit/client/facet_spec.rb +13 -0
- data/spec/xapit/client/index_builder_spec.rb +66 -0
- data/spec/xapit/client/membership_spec.rb +43 -0
- data/spec/xapit/client/model_adapters/active_record_adapter_spec.rb +62 -0
- data/spec/xapit/client/model_adapters/default_model_adapter_spec.rb +7 -0
- data/spec/xapit/client/remote_database_spec.rb +19 -0
- data/spec/xapit/server/app_spec.rb +22 -0
- data/spec/xapit/server/database_spec.rb +37 -0
- data/spec/xapit/server/indexer_spec.rb +82 -0
- data/spec/xapit/server/query_spec.rb +43 -0
- data/spec/xapit/xapit_spec.rb +28 -0
- metadata +124 -93
- data/Manifest +0 -60
- data/features/sorting.feature +0 -29
- data/init.rb +0 -1
- data/install.rb +0 -8
- data/lib/xapit/adapters/abstract_adapter.rb +0 -47
- data/lib/xapit/adapters/active_record_adapter.rb +0 -20
- data/lib/xapit/adapters/data_mapper_adapter.rb +0 -10
- data/lib/xapit/collection.rb +0 -187
- data/lib/xapit/config.rb +0 -84
- data/lib/xapit/facet.rb +0 -67
- data/lib/xapit/facet_blueprint.rb +0 -59
- data/lib/xapit/facet_option.rb +0 -56
- data/lib/xapit/index_blueprint.rb +0 -147
- data/lib/xapit/indexers/abstract_indexer.rb +0 -116
- data/lib/xapit/indexers/classic_indexer.rb +0 -29
- data/lib/xapit/indexers/simple_indexer.rb +0 -38
- data/lib/xapit/membership.rb +0 -137
- data/lib/xapit/query.rb +0 -89
- data/lib/xapit/query_parsers/abstract_query_parser.rb +0 -174
- data/lib/xapit/query_parsers/classic_query_parser.rb +0 -29
- data/lib/xapit/query_parsers/simple_query_parser.rb +0 -75
- data/lib/xapit/rake_tasks.rb +0 -13
- data/rails_generators/xapit/USAGE +0 -13
- data/rails_generators/xapit/templates/setup_xapit.rb +0 -1
- data/rails_generators/xapit/templates/xapit.rake +0 -4
- data/rails_generators/xapit/xapit_generator.rb +0 -20
- data/spec/xapit/adapters/active_record_adapter_spec.rb +0 -31
- data/spec/xapit/adapters/data_mapper_adapter_spec.rb +0 -10
- data/spec/xapit/collection_spec.rb +0 -176
- data/spec/xapit/config_spec.rb +0 -62
- data/spec/xapit/facet_blueprint_spec.rb +0 -29
- data/spec/xapit/facet_option_spec.rb +0 -80
- data/spec/xapit/facet_spec.rb +0 -73
- data/spec/xapit/index_blueprint_spec.rb +0 -112
- data/spec/xapit/indexers/abstract_indexer_spec.rb +0 -111
- data/spec/xapit/indexers/classic_indexer_spec.rb +0 -35
- data/spec/xapit/indexers/simple_indexer_spec.rb +0 -69
- data/spec/xapit/membership_spec.rb +0 -55
- data/spec/xapit/query_parsers/abstract_query_parser_spec.rb +0 -60
- data/spec/xapit/query_parsers/classic_query_parser_spec.rb +0 -20
- data/spec/xapit/query_parsers/simple_query_parser_spec.rb +0 -86
- data/spec/xapit/query_spec.rb +0 -60
- data/tasks/spec.rb +0 -9
- data/tasks/xapit.rake +0 -1
- data/uninstall.rb +0 -5
- data/xapit.gemspec +0 -30
data/lib/xapit/facet.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
module Xapit
|
2
|
-
# Facets allow users to further filter the result set based on certain attributes.
|
3
|
-
# You should fetch facets by calling "facets" on a Xapit::Collection search result.
|
4
|
-
#
|
5
|
-
# <% for facet in @articles.facets %>
|
6
|
-
# <%= facet.name %>
|
7
|
-
# <% for option in facet.options %>
|
8
|
-
# <%= link_to option.name, :overwrite_params => { :facets => option } %>
|
9
|
-
# (<%= option.count %>)
|
10
|
-
# <% end %>
|
11
|
-
# <% end %>
|
12
|
-
#
|
13
|
-
# See Xapit::FacetBlueprint for details on how to index a facet.
|
14
|
-
class Facet
|
15
|
-
attr_accessor :existing_facet_identifiers
|
16
|
-
|
17
|
-
def initialize(blueprint, query, existing_facet_identifiers)
|
18
|
-
@blueprint = blueprint
|
19
|
-
@query = query
|
20
|
-
@existing_facet_identifiers = existing_facet_identifiers
|
21
|
-
end
|
22
|
-
|
23
|
-
# Xapit::FacetOption objects for this facet which match the current query.
|
24
|
-
# Hides options which don't narrow down results.
|
25
|
-
def options
|
26
|
-
unfiltered_options.select { |o| o.count < @query.count }
|
27
|
-
end
|
28
|
-
|
29
|
-
# Xapit::FacetOption objects for this facet which match the current query.
|
30
|
-
# Includes options which may not narrow down result set.
|
31
|
-
def unfiltered_options
|
32
|
-
matching_identifiers.map do |identifier, count|
|
33
|
-
option = FacetOption.find(identifier)
|
34
|
-
if option.facet.attribute == @blueprint.attribute
|
35
|
-
option.count = count
|
36
|
-
option.existing_facet_identifiers = @existing_facet_identifiers
|
37
|
-
option
|
38
|
-
end
|
39
|
-
end.compact.sort_by(&:name)
|
40
|
-
end
|
41
|
-
|
42
|
-
def matching_identifiers
|
43
|
-
result = {}
|
44
|
-
matches.each do |match|
|
45
|
-
identifiers = match.document.terms.map(&:term).grep(/^F/).map { |t| t[1..-1] }
|
46
|
-
identifiers.each do |identifier|
|
47
|
-
unless existing_facet_identifiers.include? identifier
|
48
|
-
result[identifier] ||= 0
|
49
|
-
result[identifier] += (match.collapse_count + 1)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
result
|
54
|
-
end
|
55
|
-
|
56
|
-
# The name of the facet. See Xapit::FacetBlueprint for details.
|
57
|
-
def name
|
58
|
-
@blueprint.name
|
59
|
-
end
|
60
|
-
|
61
|
-
private
|
62
|
-
|
63
|
-
def matches
|
64
|
-
@query.matches(:offset => 0, :limit => 1000, :collapse_key => @blueprint.position)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
module Xapit
|
2
|
-
# A facet blueprint keeps track of the settings for indexing a given facet. You can specify a custom
|
3
|
-
# name for a given facet by providing a second argument when defining.
|
4
|
-
#
|
5
|
-
# xapit do |index|
|
6
|
-
# index.facet :category_name, "Category"
|
7
|
-
# end
|
8
|
-
#
|
9
|
-
# Multiple facet values are supported for a single record. All you need to do is return an array of
|
10
|
-
# values instead of a single string.
|
11
|
-
#
|
12
|
-
# def category_names
|
13
|
-
# categories.map(&:name) # => ["Toys", "Clothing"]
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
class FacetBlueprint
|
17
|
-
attr_reader :member_class
|
18
|
-
attr_reader :position
|
19
|
-
attr_reader :attribute
|
20
|
-
|
21
|
-
def initialize(member_class, position, attribute, custom_name = nil)
|
22
|
-
@member_class = member_class
|
23
|
-
@position = position
|
24
|
-
@attribute = attribute
|
25
|
-
@custom_name = custom_name
|
26
|
-
end
|
27
|
-
|
28
|
-
def identifiers_for(member)
|
29
|
-
values_for(member).map do |value|
|
30
|
-
Digest::SHA1.hexdigest(@attribute.to_s + value)[0..6]
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# The name of the facet. This will return the custom name if given while setting up the index,
|
35
|
-
# or default to humanizing the attribute name.
|
36
|
-
def name
|
37
|
-
@custom_name || @attribute.to_s.humanize
|
38
|
-
end
|
39
|
-
|
40
|
-
def save_facet_options_for(member)
|
41
|
-
values_for(member).map do |value|
|
42
|
-
option = FacetOption.new(member.class.name, @attribute.to_s, value)
|
43
|
-
option.save
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def values_for(member)
|
50
|
-
value = member.send(@attribute)
|
51
|
-
if value.kind_of? Array
|
52
|
-
value.map(&:to_s).reject(&:empty?)
|
53
|
-
else
|
54
|
-
[value].map(&:to_s).reject(&:empty?)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
data/lib/xapit/facet_option.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
module Xapit
|
2
|
-
# A facet option is a specific value or choice for a facet. See Xapit::Facet for details on how to use it.
|
3
|
-
class FacetOption
|
4
|
-
attr_accessor :facet, :name, :existing_facet_identifiers, :count
|
5
|
-
|
6
|
-
# Fetch a facet option given an id.
|
7
|
-
def self.find(id)
|
8
|
-
match = Query.new("Q#{name}-#{id}").matches(:offset => 0, :limit => 1).first
|
9
|
-
if match.nil?
|
10
|
-
raise "Unable to find facet option for #{id}."
|
11
|
-
else
|
12
|
-
class_name, facet_attribute, name = match.document.data.split('|||')
|
13
|
-
new(class_name.to_s, facet_attribute.to_s, name.to_s)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
# See if the given facet option exists with this id.
|
18
|
-
def self.exist?(id)
|
19
|
-
Query.new("Q#{name}-#{id}").count >= 1
|
20
|
-
end
|
21
|
-
|
22
|
-
def initialize(class_name, facet_attribute, name)
|
23
|
-
@facet = class_name.constantize.xapit_facet_blueprint(facet_attribute) if class_name && facet_attribute
|
24
|
-
@name = name
|
25
|
-
end
|
26
|
-
|
27
|
-
def identifier
|
28
|
-
Digest::SHA1.hexdigest(facet.attribute.to_s + name)[0..6]
|
29
|
-
end
|
30
|
-
|
31
|
-
# Saves the given facet option to the database if it hasn't been already.
|
32
|
-
def save
|
33
|
-
unless self.class.exist?(identifier)
|
34
|
-
doc = Xapian::Document.new
|
35
|
-
doc.data = [facet.member_class.name, facet.attribute, name].join("|||")
|
36
|
-
doc.add_term("Q#{self.class.name}-#{identifier}")
|
37
|
-
Xapit::Config.writable_database.add_document(doc)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# Converts the facet to be used in a URL. It adds to the existing ones for convenience.
|
42
|
-
# If this facet option is currently selected, then this will return all selected facets except
|
43
|
-
# this one. This conveniently allows you to use this as both an "add this facet" and "remove this facet" link.
|
44
|
-
def to_param
|
45
|
-
if existing_facet_identifiers.include? identifier
|
46
|
-
if Xapit::Config.breadcrumb_facets?
|
47
|
-
existing_facet_identifiers[0..existing_facet_identifiers.index(identifier)].join('-')
|
48
|
-
else
|
49
|
-
(existing_facet_identifiers - [identifier]).join('-')
|
50
|
-
end
|
51
|
-
else
|
52
|
-
(existing_facet_identifiers + [identifier]).join('-')
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,147 +0,0 @@
|
|
1
|
-
module Xapit
|
2
|
-
# This is the object used in the block of the xapit method in Xapit::Membership. It keeps track of the
|
3
|
-
# index settings for a given class. It also provides some indexing functionality.
|
4
|
-
class IndexBlueprint
|
5
|
-
attr_reader :text_attributes
|
6
|
-
attr_reader :field_attributes
|
7
|
-
attr_reader :sortable_attributes
|
8
|
-
attr_reader :facets
|
9
|
-
|
10
|
-
# Indexes all classes known to have an index blueprint defined.
|
11
|
-
def self.index_all
|
12
|
-
load_models
|
13
|
-
@@instances.each do |member_class, blueprint|
|
14
|
-
yield(member_class) if block_given?
|
15
|
-
blueprint.index_all
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def initialize(member_class, *args)
|
20
|
-
@member_class = member_class
|
21
|
-
@args = args
|
22
|
-
@text_attributes = {}
|
23
|
-
@field_attributes = []
|
24
|
-
@sortable_attributes = []
|
25
|
-
@facets = []
|
26
|
-
@@instances ||= {}
|
27
|
-
@@instances[member_class] = self # TODO make this thread safe
|
28
|
-
@indexer = SimpleIndexer.new(self)
|
29
|
-
end
|
30
|
-
|
31
|
-
# Adds a text attribute. Each word in the text will be indexed as a separate term allowing full text searching.
|
32
|
-
# Text terms are what is searched by the primary string in a search query.
|
33
|
-
#
|
34
|
-
# Article.search("kite")
|
35
|
-
#
|
36
|
-
# You can specify a :weight option to give a text attribute more importance. This will cause search terms matching
|
37
|
-
# that attribute to have a higher rank. The default weight is 1. Decimal (0.5) weight values are not supported.
|
38
|
-
#
|
39
|
-
# index.text :name, :weight => 10
|
40
|
-
#
|
41
|
-
def text(*attributes, &proc)
|
42
|
-
options = attributes.extract_options!
|
43
|
-
options[:proc] ||= proc
|
44
|
-
attributes.each do |attribute|
|
45
|
-
@text_attributes[attribute] = options
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# Adds a field attribute. Field terms are not split by word so it is not designed for full text search.
|
50
|
-
# Instead you can filter through a field using the :conditions hash in a search query.
|
51
|
-
#
|
52
|
-
# Article.search(:conditions => { :priority => 5 })
|
53
|
-
#
|
54
|
-
# Multiple field values are supported if the given attribute is an array.
|
55
|
-
#
|
56
|
-
# def priority
|
57
|
-
# [3, 5] # will match priority search for 3 or 5
|
58
|
-
# end
|
59
|
-
#
|
60
|
-
def field(*attributes)
|
61
|
-
@field_attributes += attributes
|
62
|
-
end
|
63
|
-
|
64
|
-
# Adds a facet attribute. See Xapit::FacetBlueprint and Xapit::Facet for details.
|
65
|
-
def facet(*args, &block)
|
66
|
-
@facets << FacetBlueprint.new(@member_class, @facets.size, *args, &block)
|
67
|
-
end
|
68
|
-
|
69
|
-
# Adds a sortable attribute for use with the :order option in a search call.
|
70
|
-
def sortable(*attributes)
|
71
|
-
@sortable_attributes += attributes
|
72
|
-
end
|
73
|
-
|
74
|
-
# Indexes all records of this blueprint class. It does this using the ".find_each" method on the member class.
|
75
|
-
# You will likely want to call Xapit.remove_database before this.
|
76
|
-
def index_all
|
77
|
-
@member_class.xapit_adapter.find_each(*@args) do |member|
|
78
|
-
@indexer.add_member(member)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# The Xapian value index position of a sortable attribute
|
83
|
-
def position_of_sortable(sortable_attribute)
|
84
|
-
index = sortable_attributes.map(&:to_s).index(sortable_attribute.to_s)
|
85
|
-
raise "Unable to find indexed sortable attribute \"#{sortable_attribute}\" in #{@member_class} sortable attributes: #{sortable_attributes.inspect}" if index.nil?
|
86
|
-
index + facets.size
|
87
|
-
end
|
88
|
-
|
89
|
-
# The Xapian value index position of a field attribute
|
90
|
-
def position_of_field(field_attribute)
|
91
|
-
index = field_attributes.map(&:to_s).index(field_attribute.to_s)
|
92
|
-
raise "Unable to find indexed field attribute \"#{field_attribute}\" in #{@member_class} field attributes: #{field_attributes.inspect}" if index.nil?
|
93
|
-
index + facets.size + sortable_attributes.size
|
94
|
-
end
|
95
|
-
|
96
|
-
# Add a single record to the index if it matches the xapit options.
|
97
|
-
def create_record(member_id)
|
98
|
-
member = @member_class.xapit_adapter.find_single(member_id, *@args)
|
99
|
-
@indexer.add_member(member) if member
|
100
|
-
end
|
101
|
-
|
102
|
-
# Update a single record in the index. If the record does not match the xapit
|
103
|
-
# conditions then it is removed from the index instead.
|
104
|
-
def update_record(member_id)
|
105
|
-
member = @member_class.xapit_adapter.find_single(member_id, *@args)
|
106
|
-
if member
|
107
|
-
@indexer.update_member(member)
|
108
|
-
else
|
109
|
-
destroy_record(member_id)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# Remove a single record from the index.
|
114
|
-
def destroy_record(member_id)
|
115
|
-
Xapit::Config.writable_database.delete_document("Q#{@member_class}-#{member_id}")
|
116
|
-
end
|
117
|
-
|
118
|
-
private
|
119
|
-
|
120
|
-
# Make sure all models are loaded - without reloading any that
|
121
|
-
# ActiveRecord::Base is already aware of (otherwise we start to hit some
|
122
|
-
# messy dependencies issues).
|
123
|
-
#
|
124
|
-
# Taken from thinking-sphinx
|
125
|
-
def self.load_models
|
126
|
-
if defined? Rails
|
127
|
-
base = "#{Rails.root}/app/models/"
|
128
|
-
Dir["#{base}**/*.rb"].each do |file|
|
129
|
-
model_name = file.gsub(/^#{base}([\w_\/\\]+)\.rb/, '\1')
|
130
|
-
|
131
|
-
next if model_name.nil?
|
132
|
-
next if ::ActiveRecord::Base.send(:subclasses).detect { |model|
|
133
|
-
model.name == model_name
|
134
|
-
}
|
135
|
-
|
136
|
-
begin
|
137
|
-
model_name.camelize.constantize
|
138
|
-
rescue LoadError
|
139
|
-
model_name.gsub!(/.*[\/\\]/, '').nil? ? next : retry
|
140
|
-
rescue NameError
|
141
|
-
next
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
@@ -1,116 +0,0 @@
|
|
1
|
-
module Xapit
|
2
|
-
class AbstractIndexer
|
3
|
-
def initialize(blueprint)
|
4
|
-
@blueprint = blueprint
|
5
|
-
end
|
6
|
-
|
7
|
-
def add_member(member)
|
8
|
-
database.add_document(document_for(member))
|
9
|
-
end
|
10
|
-
|
11
|
-
def update_member(member)
|
12
|
-
database.replace_document("Q#{member.class}-#{member.id}", document_for(member))
|
13
|
-
end
|
14
|
-
|
15
|
-
def document_for(member)
|
16
|
-
document = Xapian::Document.new
|
17
|
-
document.data = "#{member.class}-#{member.id}"
|
18
|
-
index_text_attributes(member, document)
|
19
|
-
index_terms(other_terms(member), document)
|
20
|
-
values(member).each_with_index do |value, index|
|
21
|
-
document.add_value(index, value)
|
22
|
-
end
|
23
|
-
save_facet_options_for(member)
|
24
|
-
document
|
25
|
-
end
|
26
|
-
|
27
|
-
def index_terms(terms, document)
|
28
|
-
terms.each do |term|
|
29
|
-
document.add_term(term)
|
30
|
-
database.add_spelling(term) if Config.spelling?
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def index_text_attributes(member, document)
|
35
|
-
# to be overridden by subclass
|
36
|
-
end
|
37
|
-
|
38
|
-
def other_terms(member)
|
39
|
-
base_terms(member) + field_terms(member) + facet_terms(member)
|
40
|
-
end
|
41
|
-
|
42
|
-
def base_terms(member)
|
43
|
-
["C#{member.class}", "Q#{member.class}-#{member.id}"]
|
44
|
-
end
|
45
|
-
|
46
|
-
def field_terms(member)
|
47
|
-
@blueprint.field_attributes.map do |name|
|
48
|
-
[member.send(name)].flatten.map do |value|
|
49
|
-
if value.kind_of? Time
|
50
|
-
value = value.to_i
|
51
|
-
elsif value.kind_of? Date
|
52
|
-
value = value.to_time.to_i
|
53
|
-
end
|
54
|
-
"X#{name}-#{value.to_s.downcase}"
|
55
|
-
end
|
56
|
-
end.flatten
|
57
|
-
end
|
58
|
-
|
59
|
-
def facet_terms(member)
|
60
|
-
@blueprint.facets.map do |facet|
|
61
|
-
facet.identifiers_for(member).map { |id| "F#{id}" }
|
62
|
-
end.flatten
|
63
|
-
end
|
64
|
-
|
65
|
-
# used primarily by search similar functionality
|
66
|
-
def text_terms(member) # REFACTORME some duplicaiton with simple indexer
|
67
|
-
@blueprint.text_attributes.map do |name, options|
|
68
|
-
content = member.send(name).to_s
|
69
|
-
if options[:proc]
|
70
|
-
options[:proc].call(content).reject(&:blank?).map(&:to_s).map(&:downcase)
|
71
|
-
else
|
72
|
-
content.scan(/\w+/u).map(&:downcase)
|
73
|
-
end
|
74
|
-
end.flatten
|
75
|
-
end
|
76
|
-
|
77
|
-
def values(member)
|
78
|
-
facet_values(member) + sortable_values(member) + field_values(member)
|
79
|
-
end
|
80
|
-
|
81
|
-
def sortable_values(member)
|
82
|
-
@blueprint.sortable_attributes.map do |sortable|
|
83
|
-
value = member.send(sortable)
|
84
|
-
value = value.first if value.kind_of? Array
|
85
|
-
Xapit.serialize_value(value)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# TODO remove duplication with sortable_values
|
90
|
-
def field_values(member)
|
91
|
-
@blueprint.field_attributes.map do |sortable|
|
92
|
-
value = member.send(sortable)
|
93
|
-
value = value.first if value.kind_of? Array
|
94
|
-
Xapit.serialize_value(value)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def facet_values(member)
|
99
|
-
@blueprint.facets.map do |facet|
|
100
|
-
facet.identifiers_for(member).join("-")
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def save_facet_options_for(member)
|
105
|
-
@blueprint.facets.each do |facet|
|
106
|
-
facet.save_facet_options_for(member)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
private
|
111
|
-
|
112
|
-
def database
|
113
|
-
Config.writable_database
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|