delsolr 0.0.6 → 0.1.0

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/README.txt CHANGED
@@ -30,10 +30,10 @@ Example:
30
30
 
31
31
  c = DelSolr::Client.new(:server => 'solr1', :port => 8983)
32
32
  rsp = c.query('dismax', :query => 'mp3 player',
33
- :filters => {:cost => (50..100)},
33
+ :filters => {:cost => (50..100), :localparams => {:tag => 'cost_filter'}},
34
34
  :facets => [{:field => 'brand', :limit => 10},
35
35
  {:query => {:onsale => true, :brand => 'Apple'},
36
- :name => 'cheap_apple'}])
36
+ :localparams => {:key => 'cheap_apple', :ex => 'cost_filter'}}])
37
37
 
38
38
  # output total matches
39
39
  puts rsp.total
@@ -47,7 +47,7 @@ Example:
47
47
  end
48
48
 
49
49
  # output a query facet
50
- puts "Cheap Apple stuff: #{rsp.facet_query_count_by_name('cheap_apple')}"
50
+ puts "Cheap Apple stuff: #{rsp.facet_query_count_by_key('cheap_apple')}"
51
51
 
52
52
  # adding things
53
53
  doc = DelSolr::Document.new
@@ -60,10 +60,13 @@ Example:
60
60
  rsp = c.query('dismax', :query => 'shuffle mp3 player')
61
61
  puts rsp.ids[0]
62
62
 
63
+ # using local params for filters / facets
64
+ Use :localparams => {} syntax to add local params to filters and facets
65
+
63
66
 
64
67
  == REQUIREMENTS:
65
68
 
66
- You need Solr installed somewhere so you can query it ;)
69
+ You need Solr(1.4 or higher) installed somewhere so you can query it ;)
67
70
 
68
71
  == INSTALL:
69
72
 
@@ -1,13 +1,13 @@
1
1
  require 'cgi'
2
2
 
3
3
  module DelSolr
4
-
4
+
5
5
  class Client
6
-
6
+
7
7
  class QueryBuilder
8
-
8
+
9
9
  FL_DEFAULTS = 'id,unique_id,score' # redefine if you really want to change this.
10
-
10
+
11
11
  attr_accessor :query_name, :options
12
12
 
13
13
  # ops can basically be straight solr URL params, but it also supports some other formats
@@ -21,22 +21,17 @@ module DelSolr
21
21
  def request_string
22
22
  @request_string ||= build_request_string
23
23
  end
24
-
25
- # returns the query string of the facet query for the given query name (used for resolving counts for given queries)
26
- def facet_query_by_name(query_name)
27
- name_to_facet_query[query_name]
28
- end
29
-
30
- private
31
-
24
+
25
+ private
26
+
32
27
  def build_request_string()
33
28
  raise "query_name must be set" if query_name.blank?
34
-
29
+
35
30
  opts = self.options.dup
36
-
31
+
37
32
  # cleanup the nils
38
33
  opts.delete_if {|k,v| v.nil?}
39
-
34
+
40
35
  # resolve "rubyish" names to solr names
41
36
  opts[:q] ||= opts[:query]
42
37
  opts[:rows] ||= opts[:limit] || 10
@@ -46,9 +41,9 @@ module DelSolr
46
41
  opts[:bq] ||= opts[:boost]
47
42
  opts[:suggestionCount] ||= opts[:suggestion_count]
48
43
  opts[:onlyMorePopular] ||= opts[:only_more_popular]
49
-
44
+
50
45
  raise ":query or :q must be set" if opts[:q].nil? || opts[:q].empty?
51
-
46
+
52
47
  # clear out the "rubyish" versions, what's left will go straight to solr
53
48
  opts.delete(:query)
54
49
  opts.delete(:limit)
@@ -57,7 +52,7 @@ module DelSolr
57
52
  opts.delete(:boost)
58
53
  opts.delete(:suggestion_count)
59
54
  opts.delete(:only_more_popular)
60
-
55
+
61
56
  # needs to be an array of hashs because it's acceptable to have the same key present > once.
62
57
  params = []
63
58
 
@@ -88,7 +83,7 @@ module DelSolr
88
83
  raise 'facets must either be a Hash or an Array'
89
84
  end
90
85
  end
91
-
86
+
92
87
  # handle friendly highlight name
93
88
  if opts.delete(:highlight)
94
89
  params << {:hl => 'true'}
@@ -109,12 +104,12 @@ module DelSolr
109
104
  raise "All params should be a Hash or String"
110
105
  end
111
106
  end
112
-
107
+
113
108
  "/select?#{param_strings.join('&')}"
114
109
  end
115
-
110
+
116
111
  # returns the query param
117
- def build_query(key, queries)
112
+ def build_query(key, queries, localparams = "")
118
113
  query_string = ''
119
114
  case queries
120
115
  when String
@@ -128,7 +123,9 @@ module DelSolr
128
123
  end
129
124
  query_string = query_string_array.join(' ')
130
125
  end
131
-
126
+
127
+ query_string = localparams + query_string
128
+
132
129
  {key => query_string}
133
130
  end
134
131
 
@@ -144,7 +141,7 @@ module DelSolr
144
141
  str = "#{k}:[#{v.begin} TO #{v.end}]"
145
142
  elsif v.is_a?(String)
146
143
  if v =~ /\s/ && # if it contains a space, we may need to quote it
147
- !(v =~ /^\[.+ TO .+\]$/) # HACK: if the string is a range query, do not wrap it in quotes
144
+ !(v =~ /^\[.+ TO .+\]$/) # HACK: if the string is a range query, do not wrap it in quotes
148
145
  str = "#{k}:\"#{v}\""
149
146
  else
150
147
  str = "#{k}:#{v}"
@@ -154,10 +151,10 @@ module DelSolr
154
151
  end
155
152
  str
156
153
  end
157
-
154
+
158
155
  def build_filters(key, filters)
159
156
  params = []
160
-
157
+
161
158
  # handle "ruby-ish" filters
162
159
  case filters
163
160
  when String
@@ -167,13 +164,15 @@ module DelSolr
167
164
  params += build_filters(key, f) # recusively add all the filters in the array
168
165
  end
169
166
  when Hash
167
+ filters_local_params = build_local_params(filters['localparams'] || filters[:localparams])
170
168
  filters.each do |k,v|
171
- params << {key => key_value_pair_string(k, v)} unless v.nil?
169
+ next if ['localparams', :localparams].include?(k.to_s)
170
+ params << {key => filters_local_params + key_value_pair_string(k, v)} unless v.nil?
172
171
  end
173
172
  end
174
173
  params
175
174
  end
176
-
175
+
177
176
  def build_facets(facet_array)
178
177
  params = []
179
178
  facet_array.each do |facet_hash|
@@ -181,34 +180,53 @@ module DelSolr
181
180
  end
182
181
  params
183
182
  end
184
-
183
+
185
184
  def build_facet(facet_hash)
186
185
  params = []
187
186
  facet_name = facet_hash['name'] || facet_hash[:name]
187
+ unless facet_name.blank?
188
+ facet_hash[:localparams] ||= {}
189
+ facet_hash[:localparams][:key] ||= facet_name
190
+ end
191
+ facet_local_params = build_local_params(facet_hash['localparams'] || facet_hash[:localparams])
188
192
  facet_hash.each do |k,v|
189
193
  # handle some cases specially
190
194
  if 'field' == k.to_s
191
- params << {"facet.field" => v}
195
+ params << {"facet.field" => "#{facet_local_params}#{v}"}
192
196
  elsif 'query' == k.to_s
193
- q = build_query("facet.query", v)
194
- params << q
195
- if facet_name
196
- # keep track of names => facet_queries
197
- name_to_facet_query[facet_name] = q['facet.query']
198
- end
199
- elsif ['name', :name].include?(k.to_s)
197
+ params << build_query("facet.query", v, facet_local_params)
198
+ elsif ['localparams', :localparams, 'name', :name].include?(k.to_s)
200
199
  # do nothing
201
200
  else
202
- params << {"f.#{facet_hash[:field]}.facet.#{k}" => v}
201
+ params << {"f.#{facet_hash[:field]}.facet.#{k}" => "#{facet_local_params}#{v}"}
203
202
  end
204
203
  end
205
204
  params
206
205
  end
207
-
208
- def name_to_facet_query
209
- @name_to_facet_query ||= {}
206
+
207
+ def build_local_params_array(local_params)
208
+ local_params_array = []
209
+ case local_params
210
+ when String
211
+ local_params_array << local_params
212
+ when Array
213
+ local_params.each do |p|
214
+ local_params_array << build_local_params_array(p)
215
+ end
216
+ when Hash
217
+ local_params.each do |k,v|
218
+ local_params_array << "#{k}=#{v}"
219
+ end
220
+ end
221
+ local_params_array
210
222
  end
211
-
223
+
224
+ def build_local_params(local_params)
225
+ local_params_array = build_local_params_array(local_params)
226
+
227
+ local_params_array.empty? ? "" : "{!#{local_params_array.join(" ")}}"
228
+ end
229
+
212
230
  end
213
231
  end
214
232
  end
@@ -174,10 +174,10 @@ module DelSolr
174
174
  end
175
175
 
176
176
  # Returns the counts for a given facet_query_name
177
- def facet_query_count_by_name(facet_query_name)
178
- query_string = query_builder.facet_query_by_name(facet_query_name)
179
- facet_queries[query_string] if query_string
177
+ def facet_query_count_by_key(facet_query_key)
178
+ facet_queries[facet_query_key.to_s]
180
179
  end
180
+ alias :facet_query_count_by_name :facet_query_count_by_key
181
181
 
182
182
  # Returns the url sent to solr
183
183
  def request_url
data/lib/delsolr.rb CHANGED
@@ -100,7 +100,7 @@ module DelSolr
100
100
  #
101
101
  # c.query('standard', :query => 'abc',
102
102
  # :facets => [:query => {:city => 'seattle', :instock => true},
103
- # :name => 'seattle_instock'}])
103
+ # :prefix => {:key => 'seattle_instock'}}])
104
104
  #
105
105
  # ...will request counts for the number of documents where "seattle" matches on the "city" field and "instock" is set to true.
106
106
  # Faceting by query requires you to assign a name to the facet so the counts can easily be fetched from the response. Solr
@@ -109,7 +109,7 @@ module DelSolr
109
109
  #
110
110
  # The count for this facet query can be pulled like so:
111
111
  #
112
- # rsp.facet_query_count_by_name('seattle_instock').
112
+ # rsp.facet_query_count_by_key('seattle_instock').
113
113
  #
114
114
  # [<b><tt>:sorts</tt></b>]
115
115
  # (optional) array or string of sorts in Lucene syntax (<fieldname> <asc/desc>)
@@ -18,10 +18,10 @@ class QueryBuilderTest < Test::Unit::TestCase
18
18
  assert(qb)
19
19
 
20
20
  p = get_params(qb.request_string)
21
- assert_equal(p['start'], '3')
22
- assert_equal(p['rows'], '13')
23
- assert_equal(p['fl'], 'id')
24
- assert_equal(p['q'], 'good book')
21
+ assert_equal('3', p['start'])
22
+ assert_equal('13', p['rows'])
23
+ assert_equal('id', p['fl'])
24
+ assert_equal('good book', p['q'])
25
25
  end
26
26
 
27
27
  def test_002
@@ -36,8 +36,8 @@ class QueryBuilderTest < Test::Unit::TestCase
36
36
  assert(qb)
37
37
 
38
38
  p = get_params(qb.request_string)
39
- assert_equal(p['fl'], 'id,unique_id,score')
40
- assert_equal(p['q'], 'blahblah')
39
+ assert_equal('id,unique_id,score', p['fl'])
40
+ assert_equal('blahblah', p['q'])
41
41
  end
42
42
 
43
43
  def test_003
@@ -52,8 +52,8 @@ class QueryBuilderTest < Test::Unit::TestCase
52
52
  assert(qb)
53
53
 
54
54
  p = get_params(qb.request_string)
55
- assert_equal(p['fl'], 'id,unique_id,score')
56
- assert_equal(p['q'], 'index_type:books')
55
+ assert_equal('id,unique_id,score', p['fl'])
56
+ assert_equal('index_type:books', p['q'])
57
57
  end
58
58
 
59
59
  def test_004
@@ -68,8 +68,8 @@ class QueryBuilderTest < Test::Unit::TestCase
68
68
  assert(qb)
69
69
 
70
70
  p = get_params(qb.request_string)
71
- assert_equal(p['fq'], 'location:seattle')
72
- assert_equal(p['q'], 'index_type:books')
71
+ assert_equal('location:seattle', p['fq'])
72
+ assert_equal('index_type:books', p['q'])
73
73
  end
74
74
 
75
75
  def test_005
@@ -85,8 +85,8 @@ class QueryBuilderTest < Test::Unit::TestCase
85
85
 
86
86
  p = get_params(qb.request_string)
87
87
 
88
- assert_equal(p['fq'], 'location:seattle')
89
- assert_equal(p['q'], 'index_type:books')
88
+ assert_equal('location:seattle', p['fq'])
89
+ assert_equal('index_type:books', p['q'])
90
90
  end
91
91
 
92
92
  def test_facets_001
@@ -101,9 +101,9 @@ class QueryBuilderTest < Test::Unit::TestCase
101
101
 
102
102
  p = get_params(qb.request_string)
103
103
 
104
- assert_equal(p['facet'], 'true')
105
- assert_equal(p['facet.field'].sort, ['instock_b', 'on_sale_b'].sort)
106
- assert_equal(p['f.on_sale_b.facet.limit'], '1')
104
+ assert_equal('true', p['facet'])
105
+ assert_equal(['instock_b', 'on_sale_b'].sort, p['facet.field'].sort)
106
+ assert_equal('1', p['f.on_sale_b.facet.limit'])
107
107
  end
108
108
 
109
109
  def test_facets_002
@@ -118,11 +118,28 @@ class QueryBuilderTest < Test::Unit::TestCase
118
118
 
119
119
  p = get_params(qb.request_string)
120
120
 
121
- assert_equal(p['facet'], 'true')
122
- assert_equal(p['facet.field'], 'language_idm')
123
- assert_equal(p['facet.query'], 'city_idm:19596')
121
+ assert_equal('true', p['facet'])
122
+ assert_equal('language_idm', p['facet.field'])
123
+ assert_equal('{!key=seattle}city_idm:19596', p['facet.query'])
124
124
  end
125
-
125
+
126
+ def test_facets_003
127
+ qb = nil
128
+ opts = {}
129
+ opts[:query] = "games"
130
+ opts[:facets] = [{:query => {:city_idm => 19596}, :localparams => {:key => 'seattle', :ex => 'exclusion'}}, {:field => 'language_idm'}]
131
+
132
+ assert_nothing_raised { qb = DelSolr::Client::QueryBuilder.new('onebox-books', opts) }
133
+
134
+ assert(qb)
135
+
136
+ p = get_params(qb.request_string)
137
+
138
+ assert_equal('true', p['facet'])
139
+ assert_equal('language_idm', p['facet.field'])
140
+ assert_equal('{!key=seattle ex=exclusion}city_idm:19596', p['facet.query'])
141
+ end
142
+
126
143
  def test_range
127
144
  qb = nil
128
145
  opts = {}
@@ -135,7 +152,7 @@ class QueryBuilderTest < Test::Unit::TestCase
135
152
 
136
153
  p = get_params(qb.request_string)
137
154
 
138
- assert_equal('id:[1 TO 3]', p['fq'])
155
+ assert_equal(p['fq'], 'id:[1 TO 3]')
139
156
  end
140
157
 
141
158
 
@@ -75,7 +75,7 @@ class ResponseTest < Test::Unit::TestCase
75
75
  },
76
76
  'facet_counts'=>{
77
77
  'facet_queries'=>{
78
- 'city_idm:19596' => 392},
78
+ '19596' => 392},
79
79
  'facet_fields'=>{
80
80
  'available_b'=>[
81
81
  'false',1328],
@@ -97,7 +97,7 @@ class ResponseTest < Test::Unit::TestCase
97
97
 
98
98
  def test_001
99
99
  r = nil
100
- qb = DelSolr::Client::QueryBuilder.new('standard', :query => {:index_type => 'widget'}, :facets => {:query => 'city_idm:19596', :name => 19596} )
100
+ qb = DelSolr::Client::QueryBuilder.new('standard', :query => {:index_type => 'widget'}, :facets => {:query => 'city_idm:19596', :prefix => {:key => 19596}} )
101
101
  qb.request_string # need to generate this...
102
102
  assert_nothing_raised { r = DelSolr::Client::Response.new(@@test_001, qb) }
103
103
 
@@ -114,12 +114,12 @@ class ResponseTest < Test::Unit::TestCase
114
114
  assert_equal(1182, r.facet_field_count('onsale_b', false))
115
115
  assert_equal(174, r.facet_field_count('onsale_b', true))
116
116
  assert_equal(1328, r.facet_field_count('available_b', false))
117
- assert_equal(392, r.facet_query_count_by_name(19596))
117
+ assert_equal(392, r.facet_query_count_by_key(19596))
118
118
  end
119
119
 
120
120
  def test_shortcuts
121
121
  r = nil
122
- qb = DelSolr::Client::QueryBuilder.new('standard', :query => {:index_type => 'widget'}, :facets => {:query => 'city_idm:19596', :name => 19596} )
122
+ qb = DelSolr::Client::QueryBuilder.new('standard', :query => {:index_type => 'widget'}, :facets => {:query => 'city_idm:19596', :prefix => {:key => 19596}} )
123
123
  qb.request_string # need to generate this...
124
124
  assert_nothing_raised { r = DelSolr::Client::Response.new(@@test_001, qb, :shortcuts => [:index_type, :id]) }
125
125
 
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
+ - 1
7
8
  - 0
8
- - 6
9
- version: 0.0.6
9
+ version: 0.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Ben VandenBos