solrsan 0.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +26 -0
- data/LICENSE +23 -0
- data/README.markdown +54 -0
- data/Rakefile +18 -0
- data/config/solr/conf/elevate.xml +31 -0
- data/config/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
- data/config/solr/conf/protwords.txt +22 -0
- data/config/solr/conf/schema.xml +237 -0
- data/config/solr/conf/solrconfig.xml +430 -0
- data/config/solr/conf/spellings.txt +2 -0
- data/config/solr/conf/stopwords.txt +56 -0
- data/config/solr/conf/synonyms.txt +24 -0
- data/config/solr/conf/xslt/example.xsl +132 -0
- data/config/solr/conf/xslt/example_atom.xsl +67 -0
- data/config/solr/conf/xslt/example_rss.xsl +66 -0
- data/config/solr/conf/xslt/luke.xsl +337 -0
- data/config/solr.yml +12 -0
- data/config/solr.yml.example +13 -0
- data/lib/rails/generators/solrsan/config/config_generator.rb +30 -0
- data/lib/rails/generators/solrsan/config/templates/solr.yml +13 -0
- data/lib/rails/generators/solrsan/config/templates/solrsan.rb +5 -0
- data/lib/rails/generators/solrsan_generator.rb +11 -0
- data/lib/solrsan/config.rb +10 -0
- data/lib/solrsan/indexer.rb +83 -0
- data/lib/solrsan/search.rb +149 -0
- data/lib/solrsan/version.rb +3 -0
- data/lib/solrsan.rb +12 -0
- data/lib/tasks/solr.rake +63 -0
- data/solrsan.gemspec +25 -0
- data/test/models/document.rb +11 -0
- data/test/search_test_helper.rb +13 -0
- data/test/test_helper.rb +24 -0
- data/test/unit/indexer_test.rb +25 -0
- data/test/unit/search_test.rb +171 -0
- metadata +123 -0
@@ -0,0 +1,149 @@
|
|
1
|
+
module Solrsan
|
2
|
+
module Search
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
module ClassMethods
|
5
|
+
def class_name
|
6
|
+
to_s.underscore
|
7
|
+
end
|
8
|
+
|
9
|
+
def perform_solr_command
|
10
|
+
@rsolr = Solrsan::Config.instance.rsolr_object
|
11
|
+
yield(@rsolr)
|
12
|
+
@rsolr.commit
|
13
|
+
end
|
14
|
+
|
15
|
+
def search(search_params={})
|
16
|
+
@rsolr ||= Solrsan::Config.instance.rsolr_object
|
17
|
+
|
18
|
+
start = search_params[:start] || 0
|
19
|
+
rows = search_params[:rows] || 20
|
20
|
+
|
21
|
+
solr_params = parse_params_for_solr(search_params)
|
22
|
+
|
23
|
+
begin
|
24
|
+
solr_response = @rsolr.paginate(start, rows, 'select', :params => solr_params)
|
25
|
+
parse_solr_response(solr_response)
|
26
|
+
rescue RSolr::Error::Http => e
|
27
|
+
{:docs => [],
|
28
|
+
:metadata =>
|
29
|
+
{:error => {:http_status_code => e.response[:status],
|
30
|
+
:http_message_status => RSolr::Error::Http::STATUS_CODES[e.response[:status].to_i],
|
31
|
+
:full_message => e.message}}}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_params_for_solr(search_params={})
|
36
|
+
solr_params = { :echoParams => 'explicit',
|
37
|
+
:q => "*:*",
|
38
|
+
:facet => "on",
|
39
|
+
:'facet.mincount' => 1}.merge(search_params)
|
40
|
+
solr_params[:hl] = true unless search_params[:'hl.fl'].blank?
|
41
|
+
solr_params[:fq] = ["type:#{class_name}"] + parse_fq(search_params[:fq])
|
42
|
+
solr_params
|
43
|
+
end
|
44
|
+
|
45
|
+
def parse_solr_response(solr_response)
|
46
|
+
docs = solr_response['response']['docs']
|
47
|
+
parsed_facet_counts = parse_facet_counts(solr_response['facet_counts'])
|
48
|
+
highlighting = solr_response['highlighting']
|
49
|
+
|
50
|
+
metadata = {
|
51
|
+
:total_count => solr_response['response']['numFound'],
|
52
|
+
:start => solr_response['response']['start'],
|
53
|
+
:rows => solr_response['responseHeader']['params']['rows'],
|
54
|
+
:time => solr_response['responseHeader']['QTime'],
|
55
|
+
:status => solr_response['responseHeader']['status']
|
56
|
+
}
|
57
|
+
|
58
|
+
{:docs => docs, :metadata => metadata,
|
59
|
+
:facet_counts => parsed_facet_counts, :highlighting => highlighting}
|
60
|
+
end
|
61
|
+
|
62
|
+
def parse_fq(fq)
|
63
|
+
return [] if fq.nil?
|
64
|
+
if fq.is_a?(Hash)
|
65
|
+
fq.map{|k,v| parse_element_in_fq({k => v})}.flatten
|
66
|
+
elsif fq.is_a?(Array)
|
67
|
+
fq.map{|ele| parse_element_in_fq(ele)}.flatten
|
68
|
+
else
|
69
|
+
raise "fq must be a hash or array"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def parse_element_in_fq(element)
|
74
|
+
if element.is_a?(String)
|
75
|
+
element
|
76
|
+
elsif element.is_a?(Hash)
|
77
|
+
element.map do |k,values|
|
78
|
+
if values.is_a?(String)
|
79
|
+
key_value_query(k,values)
|
80
|
+
else
|
81
|
+
values.map{|value| key_value_query(k,value) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
else
|
85
|
+
raise "each fq parameter must be a string or hash"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def key_value_query(key, value)
|
90
|
+
if value.starts_with?("[")
|
91
|
+
"#{key}:#{value}"
|
92
|
+
else
|
93
|
+
"#{key}:\"#{value}\""
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def parse_facet_counts(facet_counts)
|
98
|
+
return {} unless facet_counts
|
99
|
+
|
100
|
+
if facet_counts['facet_fields']
|
101
|
+
facet_counts['facet_fields'] = facet_counts['facet_fields'].reduce({}) do |acc, facet_collection|
|
102
|
+
acc[facet_collection[0]] = map_facet_array_to_facet_hash(facet_collection[1])
|
103
|
+
acc
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
if facet_counts['facet_queries']
|
108
|
+
facet_counts['facet_queries'] = facet_counts['facet_queries'].group_by{|k,v| k.split(":").first}.reduce({}) do |acc, facet_collection|
|
109
|
+
facet_name = facet_collection[0]
|
110
|
+
values = facet_collection[1]
|
111
|
+
|
112
|
+
acc[facet_name] = values.reduce({}) do |inner_acc, tuple|
|
113
|
+
range = tuple[0].split(":")[1]
|
114
|
+
inner_acc[range] = tuple[1]
|
115
|
+
inner_acc
|
116
|
+
end
|
117
|
+
acc
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
facet_counts
|
122
|
+
end
|
123
|
+
|
124
|
+
# solr facet_fields comes in tuple array format []
|
125
|
+
def map_facet_array_to_facet_hash(facet_collection)
|
126
|
+
if facet_collection.is_a?(Array)
|
127
|
+
facet_collection.each_slice(2).reduce({}){|acc, tuple| acc[tuple[0]] = tuple[1]; acc}
|
128
|
+
else
|
129
|
+
facet_collection
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# namespace test documents
|
138
|
+
if defined?(Rails) && Rails.env == "test"
|
139
|
+
module Solrsan
|
140
|
+
module Search
|
141
|
+
extend ActiveSupport::Concern
|
142
|
+
module ClassMethods
|
143
|
+
def class_name
|
144
|
+
"#{to_s.underscore}_test"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/lib/solrsan.rb
ADDED
data/lib/tasks/solr.rake
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
namespace :solr do
|
5
|
+
env = "development"
|
6
|
+
base_dir = File.join(File.dirname(__FILE__), "..", "..")
|
7
|
+
|
8
|
+
if defined? Rails
|
9
|
+
env = Rails.env
|
10
|
+
base_dir = Rails.root
|
11
|
+
end
|
12
|
+
|
13
|
+
solr_config = YAML::load( File.open( File.join(base_dir, "config", "solr.yml") ) )
|
14
|
+
solr_home = File.join(base_dir, "config", "solr")
|
15
|
+
solr_data_dir = solr_config[env]['solr_data_dir']
|
16
|
+
solr_server_url = solr_config[env]['solr_server_url']
|
17
|
+
|
18
|
+
jetty_port = URI.parse(solr_server_url).port
|
19
|
+
jetty_path = solr_config[env]['jetty_path']
|
20
|
+
|
21
|
+
solr_server_dir = "cd #{jetty_path};"
|
22
|
+
start_solr_cmd = "java -jar start.jar"
|
23
|
+
jetty_port_opt = "jetty.port=#{jetty_port}"
|
24
|
+
solr_params = "#{jetty_port_opt} -Dsolr.solr.home=#{solr_home} -Dsolr.data.dir=#{solr_data_dir}"
|
25
|
+
|
26
|
+
desc "Start solr"
|
27
|
+
task(:start) do
|
28
|
+
# -Dsolr.clustering.enabled=true
|
29
|
+
cmd = kill_matching_process_cmd(jetty_port_opt)
|
30
|
+
stop_exit_status = run_system_command(cmd)
|
31
|
+
|
32
|
+
sleep(1)
|
33
|
+
|
34
|
+
cmd = "#{solr_server_dir} #{start_solr_cmd } #{solr_params} &"
|
35
|
+
run_system_command(cmd)
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Stop solr"
|
39
|
+
task(:stop) do
|
40
|
+
cmd = kill_matching_process_cmd(jetty_port_opt)
|
41
|
+
run_system_command(cmd)
|
42
|
+
end
|
43
|
+
|
44
|
+
def run_system_command(cmd)
|
45
|
+
puts cmd
|
46
|
+
status = system(cmd)
|
47
|
+
$?.exitstatus
|
48
|
+
end
|
49
|
+
|
50
|
+
def kill_matching_process_cmd(process_name)
|
51
|
+
cmd = "echo `ps -ef | grep -v grep | grep \"#{process_name.gsub("-", "\\-")}\" | awk '{print $2}'` | xargs kill"
|
52
|
+
end
|
53
|
+
|
54
|
+
# #example of a task to index all items
|
55
|
+
# desc "index food"
|
56
|
+
# task(:import_foods, :needs => :environment) do
|
57
|
+
# FoodDescription.find_in_batches do |batch|
|
58
|
+
# FoodIndexer.index(batch)
|
59
|
+
# puts "Done with batch of size: #{batch.size}"
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
end
|
63
|
+
|
data/solrsan.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "solrsan/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "solrsan"
|
7
|
+
s.version = Solrsan::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Tommy Chheng"]
|
10
|
+
s.email = ["tommy.chheng@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/tc/solrsan"
|
12
|
+
s.summary = %q{Lightweight wrapper for using Apache Solr within a Ruby application including Rails and Sinatra.}
|
13
|
+
s.description = %q{solrsan is a lightweight wrapper for using Apache Solr within a Ruby application including Rails and Sinatra.}
|
14
|
+
|
15
|
+
s.add_dependency('rsolr', '~>1.0.0')
|
16
|
+
s.add_dependency('activemodel', '~>3.0.5')
|
17
|
+
s.add_dependency('activesupport', '~>3.0.5')
|
18
|
+
|
19
|
+
s.rubyforge_project = "solrsan"
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
+
s.require_paths = ["lib"]
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module SearchTestHelper
|
2
|
+
def document_mock
|
3
|
+
doc = Document.new({:id => 500,
|
4
|
+
:title => "Solr test document",
|
5
|
+
:author => "Tommy Chheng",
|
6
|
+
:content => "ruby scala search",
|
7
|
+
:review_count => 4,
|
8
|
+
:scores => [1,2,3,4],
|
9
|
+
:created_at => Date.parse("Dec 10 2010")})
|
10
|
+
doc
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
3
|
+
|
4
|
+
MODELS = File.join(File.dirname(__FILE__), "models")
|
5
|
+
$LOAD_PATH.unshift(MODELS)
|
6
|
+
|
7
|
+
#simulate rails env
|
8
|
+
class Rails
|
9
|
+
def self.env
|
10
|
+
"test"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require "rubygems"
|
15
|
+
require "test/unit"
|
16
|
+
require 'solrsan'
|
17
|
+
|
18
|
+
#test models
|
19
|
+
require 'document'
|
20
|
+
|
21
|
+
solr_config = YAML::load( File.open( File.join(File.dirname(__FILE__), "..", "config", "solr.yml") ) )
|
22
|
+
solr_server_url = solr_config["test"]['solr_server_url']
|
23
|
+
|
24
|
+
Solrsan::Config.instance.solr_server_url = solr_server_url
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'search_test_helper'
|
3
|
+
|
4
|
+
class IndexerTest < Test::Unit::TestCase
|
5
|
+
include SearchTestHelper
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@document = document_mock
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_indexed_fields
|
15
|
+
created_doc = @document.indexed_fields
|
16
|
+
assert_equal @document.attributes[:id], created_doc[:db_id]
|
17
|
+
assert_equal @document.attributes[:title], created_doc[:title]
|
18
|
+
assert_equal @document.attributes[:author], created_doc[:author]
|
19
|
+
assert_equal @document.attributes[:content], created_doc[:content]
|
20
|
+
assert_equal @document.attributes[:review_count], created_doc[:review_count]
|
21
|
+
assert_equal @document.attributes[:scores], created_doc[:scores]
|
22
|
+
assert_equal @document.attributes[:created_at].to_time.utc.xmlschema, created_doc[:created_at]
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'search_test_helper'
|
3
|
+
|
4
|
+
class SearchTest < Test::Unit::TestCase
|
5
|
+
include SearchTestHelper
|
6
|
+
|
7
|
+
def setup
|
8
|
+
Document.destroy_all_index_documents!
|
9
|
+
@document = document_mock
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
Document.destroy_all_index_documents!
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_simple_query
|
17
|
+
Document.index(@document)
|
18
|
+
q = @document.attributes[:title]
|
19
|
+
|
20
|
+
response = Document.search(:q => q)
|
21
|
+
metadata = response[:metadata]
|
22
|
+
docs = response[:docs]
|
23
|
+
assert metadata[:total_count] > 0
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_sort
|
27
|
+
Document.index(Document.new(:id => 3, :title => "solar city",:review_count => 10))
|
28
|
+
Document.index(Document.new(:id => 4, :title => "city solar", :review_count => 5))
|
29
|
+
|
30
|
+
q = "solar"
|
31
|
+
response = Document.search(:q => q, :sort => "review_count asc")
|
32
|
+
docs = response[:docs]
|
33
|
+
|
34
|
+
assert_not_nil docs[0], "Not enough docs for #{q} to test."
|
35
|
+
first_result_name = docs[0][:title]
|
36
|
+
assert_not_nil docs[1], "Not enough docs for #{q} to test."
|
37
|
+
second_result_name = docs[1][:title]
|
38
|
+
|
39
|
+
assert_equal [second_result_name, first_result_name].sort, [first_result_name, second_result_name]
|
40
|
+
|
41
|
+
response = Document.search(:q => q, :sort => "review_count desc")
|
42
|
+
docs = response[:docs]
|
43
|
+
|
44
|
+
assert_not_nil docs[0], "Not enough docs for #{q} to test."
|
45
|
+
first_result_name = docs[0][:title]
|
46
|
+
assert_not_nil docs[1], "Not enough docs for #{q} to test."
|
47
|
+
second_result_name = docs[1][:title]
|
48
|
+
|
49
|
+
assert_equal [second_result_name, first_result_name].sort.reverse, [first_result_name, second_result_name]
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_invalid_query_should_return_error_message_in_metadata
|
53
|
+
response = Document.search(:q => "http://tommy.chheng.com")
|
54
|
+
docs = response[:docs]
|
55
|
+
metadata = response[:metadata]
|
56
|
+
|
57
|
+
assert_not_nil response[:metadata][:error]
|
58
|
+
assert_equal 400, response[:metadata][:error][:http_status_code]
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_parse_facet_fields
|
62
|
+
facet_counts = {'facet_queries'=>{},
|
63
|
+
'facet_fields' => {'language' => ["Scala", 2, "Ruby", 1, "Java", 0]},
|
64
|
+
'facet_dates'=>{}}
|
65
|
+
|
66
|
+
facet_counts = Document.parse_facet_counts(facet_counts)
|
67
|
+
|
68
|
+
assert_equal ["Scala", "Ruby", "Java"], facet_counts['facet_fields']['language'].keys
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_parse_facet_queries
|
72
|
+
facet_counts = {"facet_queries"=>{"funding:[0 TO 5000000]"=>1, "funding:[10000000 TO 50000000]"=>0}, "facet_fields"=>{}, "facet_dates"=>{}}
|
73
|
+
|
74
|
+
facet_counts = Document.parse_facet_counts(facet_counts)
|
75
|
+
|
76
|
+
expected = {"funding"=>{"[0 TO 5000000]"=>1, "[10000000 TO 50000000]"=>0}}
|
77
|
+
assert_equal expected, facet_counts['facet_queries']
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_parse_fq_with_hash
|
81
|
+
params = {:fq => {:tags => ["ruby", "scala"]}}
|
82
|
+
filters = Document.parse_fq(params[:fq])
|
83
|
+
|
84
|
+
expected = ["tags:\"ruby\"", "tags:\"scala\""]
|
85
|
+
assert_equal expected, filters
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_parse_fq_with_hash_array_args
|
89
|
+
params = {:fq => [{:tags => ["ruby", "scala"]}]}
|
90
|
+
filters = Document.parse_fq(params[:fq])
|
91
|
+
|
92
|
+
expected = ["tags:\"ruby\"", "tags:\"scala\""]
|
93
|
+
assert_equal expected, filters
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_parse_fq_with_hash_string_args
|
97
|
+
params = {:fq => [{:tags => "ruby"}]}
|
98
|
+
filters = Document.parse_fq(params[:fq])
|
99
|
+
|
100
|
+
expected = ["tags:\"ruby\""]
|
101
|
+
assert_equal expected, filters
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_parse_fq_with_string_args
|
105
|
+
params = {:fq => ["tags:ruby"]}
|
106
|
+
filters = Document.parse_fq(params[:fq])
|
107
|
+
|
108
|
+
expected = ["tags:ruby"]
|
109
|
+
assert_equal expected, filters
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_parse_fq_with_empty
|
113
|
+
filters = Document.parse_fq([])
|
114
|
+
expected = []
|
115
|
+
assert_equal expected, filters
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_filter_query
|
119
|
+
Document.index(Document.new(:id => 3, :author => "Bert", :title => "solr lucene",:review_count => 10, :tags => ['ruby']))
|
120
|
+
Document.index(Document.new(:id => 4, :author => "Ernie", :title => "lucene solr", :review_count => 5, :tags => ['ruby', 'scala']))
|
121
|
+
|
122
|
+
response = Document.search(:q => "solr", :fq => [{:tags => ["scala"]}])
|
123
|
+
docs = response[:docs]
|
124
|
+
metadata = response[:metadata]
|
125
|
+
|
126
|
+
assert_equal 1, metadata[:total_count]
|
127
|
+
|
128
|
+
doc = docs.first
|
129
|
+
assert_not_nil doc['tags']
|
130
|
+
assert doc['tags'].include?("scala")
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_text_faceting
|
134
|
+
Document.index(Document.new(:id => 3, :author => "Bert", :title => "solr lucene",:review_count => 10))
|
135
|
+
Document.index(Document.new(:id => 4, :author => "Ernie", :title => "lucene solr", :review_count => 5))
|
136
|
+
|
137
|
+
response = Document.search(:q => "solr", :'facet.field' => ['author'])
|
138
|
+
docs = response[:docs]
|
139
|
+
facet_counts = response[:facet_counts]
|
140
|
+
assert_not_nil facet_counts["facet_fields"]["author"]
|
141
|
+
|
142
|
+
author_facet_entries = facet_counts["facet_fields"]["author"]
|
143
|
+
assert author_facet_entries.keys.include?("Bert") && author_facet_entries.keys.include?("Ernie")
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_range_faceting
|
147
|
+
Document.index(Document.new(:id => 3, :author => "Bert", :title => "solr lucene",:review_count => 10))
|
148
|
+
Document.index(Document.new(:id => 4, :author => "Ernie", :title => "lucene solr", :review_count => 5))
|
149
|
+
|
150
|
+
response = Document.search(:q => "solr", :'facet.field' => ['author'], :'facet.query' => ["review_count:[1 TO 5]", "review_count:[6 TO 10]"])
|
151
|
+
docs = response[:docs]
|
152
|
+
facet_counts = response[:facet_counts]
|
153
|
+
|
154
|
+
assert_not_nil facet_counts["facet_fields"]["author"]
|
155
|
+
assert_not_nil facet_counts["facet_queries"]["review_count"]
|
156
|
+
assert_equal({"[1 TO 5]"=>1, "[6 TO 10]"=>1}, facet_counts["facet_queries"]["review_count"])
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_highlighting_support
|
160
|
+
Document.index(Document.new(:id => 3, :author => "Bert", :title => "solr lucene",:review_count => 10, :tags => ["solr"]))
|
161
|
+
|
162
|
+
response = Document.search(:q => "solr",
|
163
|
+
:'hl.fl' => "*")
|
164
|
+
docs = response[:docs]
|
165
|
+
highlighting = response[:highlighting]
|
166
|
+
|
167
|
+
first_result = highlighting.first
|
168
|
+
assert first_result[1]['tags'].include?("<em>solr</em>")
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: solrsan
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.20
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tommy Chheng
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-03-18 00:00:00.000000000 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rsolr
|
17
|
+
requirement: &2153183880 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.0.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2153183880
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: activemodel
|
28
|
+
requirement: &2153183260 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.0.5
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *2153183260
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: activesupport
|
39
|
+
requirement: &2153182780 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 3.0.5
|
45
|
+
type: :runtime
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *2153182780
|
48
|
+
description: solrsan is a lightweight wrapper for using Apache Solr within a Ruby
|
49
|
+
application including Rails and Sinatra.
|
50
|
+
email:
|
51
|
+
- tommy.chheng@gmail.com
|
52
|
+
executables: []
|
53
|
+
extensions: []
|
54
|
+
extra_rdoc_files: []
|
55
|
+
files:
|
56
|
+
- .gitignore
|
57
|
+
- Gemfile
|
58
|
+
- Gemfile.lock
|
59
|
+
- LICENSE
|
60
|
+
- README.markdown
|
61
|
+
- Rakefile
|
62
|
+
- config/solr.yml
|
63
|
+
- config/solr.yml.example
|
64
|
+
- config/solr/conf/elevate.xml
|
65
|
+
- config/solr/conf/mapping-ISOLatin1Accent.txt
|
66
|
+
- config/solr/conf/protwords.txt
|
67
|
+
- config/solr/conf/schema.xml
|
68
|
+
- config/solr/conf/solrconfig.xml
|
69
|
+
- config/solr/conf/spellings.txt
|
70
|
+
- config/solr/conf/stopwords.txt
|
71
|
+
- config/solr/conf/synonyms.txt
|
72
|
+
- config/solr/conf/xslt/example.xsl
|
73
|
+
- config/solr/conf/xslt/example_atom.xsl
|
74
|
+
- config/solr/conf/xslt/example_rss.xsl
|
75
|
+
- config/solr/conf/xslt/luke.xsl
|
76
|
+
- lib/rails/generators/solrsan/config/config_generator.rb
|
77
|
+
- lib/rails/generators/solrsan/config/templates/solr.yml
|
78
|
+
- lib/rails/generators/solrsan/config/templates/solrsan.rb
|
79
|
+
- lib/rails/generators/solrsan_generator.rb
|
80
|
+
- lib/solrsan.rb
|
81
|
+
- lib/solrsan/config.rb
|
82
|
+
- lib/solrsan/indexer.rb
|
83
|
+
- lib/solrsan/search.rb
|
84
|
+
- lib/solrsan/version.rb
|
85
|
+
- lib/tasks/solr.rake
|
86
|
+
- solrsan.gemspec
|
87
|
+
- test/models/document.rb
|
88
|
+
- test/search_test_helper.rb
|
89
|
+
- test/test_helper.rb
|
90
|
+
- test/unit/indexer_test.rb
|
91
|
+
- test/unit/search_test.rb
|
92
|
+
has_rdoc: true
|
93
|
+
homepage: http://github.com/tc/solrsan
|
94
|
+
licenses: []
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
requirements: []
|
112
|
+
rubyforge_project: solrsan
|
113
|
+
rubygems_version: 1.6.2
|
114
|
+
signing_key:
|
115
|
+
specification_version: 3
|
116
|
+
summary: Lightweight wrapper for using Apache Solr within a Ruby application including
|
117
|
+
Rails and Sinatra.
|
118
|
+
test_files:
|
119
|
+
- test/models/document.rb
|
120
|
+
- test/search_test_helper.rb
|
121
|
+
- test/test_helper.rb
|
122
|
+
- test/unit/indexer_test.rb
|
123
|
+
- test/unit/search_test.rb
|