telvue-rsolr 2.2.2

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8206df30839209477712ca57220df5bc89ffef4502b343b7160a08ead5e18328
4
+ data.tar.gz: 173b7730bb208f49a3fa4745c06b087e9047437ca42393c48f41001b872c4582
5
+ SHA512:
6
+ metadata.gz: 841eb4744fb76c3cf57490b90cf27532191a3bf3400c4dd1c39fa28261ea46810f23843aecb0a95ae870b96afc080f36e15e79f27d21dbb1e2dc3a807e46fc28
7
+ data.tar.gz: a02c86754b9bda6a4469dc22b3d8f0b5074e04dc4602380efea3dd78a2e8856f2b9e9c807b5a9695e5826163c74e3074ee7709a48a298515bdf34542e4f8a62e
@@ -0,0 +1,13 @@
1
+ .DS_Store
2
+ .yardoc/
3
+ pkg/*
4
+ apache-solr-3.3.0/
5
+ coverage/
6
+ doc/
7
+ example/
8
+
9
+ Gemfile.lock
10
+
11
+ *.gem
12
+ .bundle
13
+ /spec/examples.txt
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ sudo: false
3
+ rvm:
4
+ - 2.4.0
5
+ - 2.3.3
6
+ - 2.2.6
7
+ - jruby-9.1.7.0
8
+
9
+ env:
10
+ global:
11
+ - JRUBY_OPTS="-J-Xms512m -J-Xmx1024m"
12
+ - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
13
+
14
+ jdk: oraclejdk8
@@ -0,0 +1,47 @@
1
+ 2.0.0.pre1
2
+
3
+ In this release, we've added many new features, including:
4
+
5
+ - a new JSON request generator (enabled by default, replacing the XML-based requests) (@mootprinter)
6
+ - using Faraday for added flexibility for HTTP configuration
7
+ - native support for nested child documents and atomic updates in RSolr::Document and RSolr::Client.add
8
+ - better support for custom field value converters (@solenko)
9
+ - removing code deprecated in RSolr 1.x (@vipulnsward, and others)
10
+
11
+
12
+ 1.0.12
13
+ - Fix bug where specifying the wt property as a string, would add the supplied value to the default ('ruby') rather than overriding it.
14
+
15
+ 1.0.11
16
+ - add RSolr.solr_escape method and add deprecation messages to RSolr.escape (ndushay)
17
+ - use stdlib URI.escape methods instead of homegrown in RSolr::URI (ndushay)
18
+ - fix bug with Rsolr::Uri.create adding trailing slash if query params (ndushay)
19
+ - update rake tasks (cbeer)
20
+ - add Ruby 2.2.0 to travis ci build (ndushay)
21
+ - Housekeeping (badges to README, license in gemspec, correct url in gemspec ...) (ndushay)
22
+ - Improve rdoc styling (udaykadaboina)
23
+ - Support setting default_wt per connection via its options. (jcoleman)
24
+ - eliminates the usage of per-instance `extend` (jcoleman)
25
+ - Upgrade to RSpec 3 (blackwinter, adamjonas, cbeer)
26
+ - Fixed RSolr::Error to_s (PofMagicfingers)
27
+ 1.0.10 xxx
28
+
29
+ 1.0.8
30
+ - Fix connection refused errors in specs + add basic auth support (Denis Goeury)
31
+ - Ability to set :retry_503, the number of retry attempts for a 503 response
32
+ with a Retry-After header.
33
+ 1.0.7
34
+ - Response body encoding is set to response charset in Ruby >= 1.9
35
+ - Ability to set :read_timeout and :open_timeout when creating new instance of RSolr
36
+ 1.0.6
37
+ - More dependency fixups
38
+ 1.0.5
39
+ - Dependency fixups
40
+ 1.0.4
41
+ - The "builder" gem dependency is less strict: ~> 2.1.2
42
+ - RSolr.version is no longer read from a file
43
+ - Gemspec updated -- less strict dev/test versions
44
+ - Jeweler is no longer used for building the gemspec
45
+ 1.0.3
46
+ - Proper encodings in Ruby 1.9
47
+ - Applied pull request from https://github.com/mwmitchell/rsolr/pull/20
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "builder", ">= 2.1.2"
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2008-2010 Matt Mitchell
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,229 @@
1
+ == This is a TelVue Corp fork of the rsolr gem
2
+
3
+ =RSolr
4
+ {<img src="https://travis-ci.org/rsolr/rsolr.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/rsolr/rsolr] {<img src="https://badge.fury.io/rb/rsolr.svg" alt="Gem Version" />}[http://badge.fury.io/rb/rsolr]
5
+
6
+
7
+ A simple, extensible Ruby client for Apache Solr.
8
+
9
+ ==Documentation
10
+ The code docs http://www.rubydoc.info/gems/rsolr
11
+
12
+ == Installation:
13
+ gem install telvue-rsolr
14
+
15
+ == Example:
16
+ require 'rsolr'
17
+
18
+ # Direct connection
19
+ solr = RSolr.connect :url => 'http://solrserver.com'
20
+
21
+ # Connecting over a proxy server
22
+ solr = RSolr.connect :url => 'http://solrserver.com', :proxy=>'http://user:pass@proxy.example.com:8080'
23
+
24
+ # Using an alternate Faraday adapter
25
+ solr = RSolr.connect :url => 'http://solrserver.com', :adapter => :em_http
26
+
27
+ # Using a custom Faraday connection
28
+ conn = Faraday.new do |faraday|
29
+ faraday.response :logger # log requests to STDOUT
30
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
31
+ end
32
+ solr = RSolr.connect conn, :url => 'http://solrserver.com'
33
+
34
+ # send a request to /select
35
+ response = solr.get 'select', :params => {:q => '*:*'}
36
+
37
+ # send a request to /catalog
38
+ response = solr.get 'catalog', :params => {:q => '*:*'}
39
+
40
+ When the Solr +:wt+ is +:ruby+, then the response will be a Hash. This Hash is the same object returned by Solr, but evaluated as Ruby. If the +:wt+ is not +:ruby+, then the response will be a String.
41
+
42
+ The response also exposes 2 attribute readers (for any +:wt+ value), +:request+ and +:response+. Both are Hash objects with symbolized keys.
43
+
44
+ The +:request+ attribute contains the original request context. You can use this for debugging or logging. Some of the keys this object contains are +:uri+, +:query+, +:method+ etc..
45
+
46
+ The +:response+ attribute contains the original response. This object contains the +:status+, +:body+ and +:headers+ keys.
47
+
48
+ == Request formats
49
+
50
+ By default, RSolr uses the Solr JSON command format for all requests.
51
+
52
+ RSolr.connect :url => 'http://solrserver.com', update_format: :json # the default
53
+ # or
54
+ RSolr.connect :url => 'http://solrserver.com', update_format: :xml
55
+
56
+ == Timeouts
57
+ The read and connect timeout settings can be set when creating a new instance of RSolr:
58
+ solr = RSolr.connect(:read_timeout => 120, :open_timeout => 120)
59
+
60
+ == Retry 503s
61
+ A 503 is usually a temporary error which RSolr may retry if requested. You may specify the number of retry attempts with the +:retry_503+ option.
62
+
63
+ Only requests which specify a Retry-After header will be retried, after waiting the indicated retry interval, otherwise RSolr will treat the request as a 500. You may specify a maximum Retry-After interval to wait with the +:retry_after_limit+ option (default: one second).
64
+ solr = RSolr.connect(:retry_503 => 1, :retry_after_limit => 1)
65
+
66
+ For additional control, consider using a custom Faraday connection (see above) using its `retry` middleware.
67
+
68
+ == Querying
69
+ Use the #get / #post method to send search requests to the /select handler:
70
+ response = solr.get 'select', :params => {
71
+ :q=>'washington',
72
+ :start=>0,
73
+ :rows=>10
74
+ }
75
+ response["response"]["docs"].each{|doc| puts doc["id"] }
76
+
77
+ The +:params+ sent into the method are sent to Solr as-is, which is to say they are converted to Solr url style, but no special mapping is used.
78
+ When an array is used, multiple parameters *with the same name* are generated for the Solr query. Example:
79
+
80
+ solr.get 'select', :params => {:q=>'roses', :fq=>['red', 'violet']}
81
+
82
+ The above statement generates this Solr query:
83
+
84
+ select?q=roses&fq=red&fq=violet
85
+
86
+ ===Pagination
87
+ To paginate through a set of Solr documents, use the paginate method:
88
+ solr.paginate 1, 10, "select", :params => {:q => "test"}
89
+
90
+ The first argument is the current page, the second is how many documents to return for each page. In other words, "page" is the "start" Solr param and "per-page" is the "rows" Solr param.
91
+
92
+ The paginate method returns WillPaginate ready "docs" objects, so for example in a Rails application, paginating is as simple as:
93
+ <%= will_paginate @solr_response["response"]["docs"] %>
94
+
95
+ ===Method Missing
96
+ The +RSolr::Client+ class also uses +method_missing+ for setting the request handler/path:
97
+
98
+ solr.paintings :params => {:q=>'roses', :fq=>['red', 'violet']}
99
+
100
+ This is sent to Solr as:
101
+ paintings?q=roses&fq=red&fq=violet
102
+
103
+ This works with pagination as well:
104
+
105
+ solr.paginate_paintings 1, 10, {:q=>'roses', :fq=>['red', 'violet']}
106
+
107
+ ===Using POST for Search Queries
108
+ There may be cases where the query string is too long for a GET request. RSolr solves this issue by converting hash objects into form-encoded strings:
109
+ response = solr.music :data => {:q => "*:*"}
110
+
111
+ The +:data+ hash is serialized as a form-encoded query string, and the correct content-type headers are sent along to Solr.
112
+
113
+ ===Sending HEAD Requests
114
+ There may be cases where you'd like to send a HEAD request to Solr:
115
+ solr.head("admin/ping").response[:status] == 200
116
+
117
+ ==Sending HTTP Headers
118
+ Solr responds to the request headers listed here: http://wiki.apache.org/solr/SolrAndHTTPCaches
119
+ To send header information to Solr using RSolr, just use the +:headers+ option:
120
+ response = solr.head "admin/ping", :headers => {"Cache-Control" => "If-None-Match"}
121
+
122
+ ===Building a Request
123
+ +RSolr::Client+ provides a method for building a request context, which can be useful for debugging or logging etc.:
124
+ request_context = solr.build_request "select", :data => {:q => "*:*"}, :method => :post, :headers => {}
125
+
126
+ To build a paginated request use build_paginated_request:
127
+ request_context = solr.build_paginated_request 1, 10, "select", ...
128
+
129
+ == Updating Solr
130
+ Updating is done using native Ruby objects. Hashes are used for single documents and arrays are used for a collection of documents (hashes). These objects get turned into simple XML "messages". Raw XML strings can also be used.
131
+
132
+ Single document via #add
133
+ solr.add :id=>1, :price=>1.00
134
+
135
+ Multiple documents via #add
136
+ documents = [{:id=>1, :price=>1.00}, {:id=>2, :price=>10.50}]
137
+ solr.add documents
138
+
139
+ The optional +:add_attributes+ hash can also be used to set Solr "add" document attributes:
140
+ solr.add documents, :add_attributes => {:commitWithin => 10}
141
+
142
+ Raw commands via #update
143
+ solr.update data: '<commit/>', headers: { 'Content-Type' => 'text/xml' }
144
+ solr.update data: { optimize: true }.to_json, headers: { 'Content-Type' => 'application/json' }
145
+
146
+ When adding, you can also supply "add" xml element attributes and/or a block for manipulating other "add" related elements (docs and fields) by calling the +xml+ method directly:
147
+
148
+ doc = {:id=>1, :price=>1.00}
149
+ add_attributes = {:allowDups=>false, :commitWithin=>10}
150
+ add_xml = solr.xml.add(doc, add_attributes) do |doc|
151
+ # boost each document
152
+ doc.attrs[:boost] = 1.5
153
+ # boost the price field:
154
+ doc.field_by_name(:price).attrs[:boost] = 2.0
155
+ end
156
+
157
+ Now the "add_xml" object can be sent to Solr like:
158
+ solr.update :data => add_xml
159
+
160
+ ===Deleting
161
+ Delete by id
162
+ solr.delete_by_id 1
163
+ or an array of ids
164
+ solr.delete_by_id [1, 2, 3, 4]
165
+
166
+ Delete by query:
167
+ solr.delete_by_query 'price:1.00'
168
+ Delete by array of queries
169
+ solr.delete_by_query ['price:1.00', 'price:10.00']
170
+
171
+ ===Commit / Optimize
172
+ solr.commit, :commit_attributes => {}
173
+ solr.optimize, :optimize_attributes => {}
174
+
175
+ == Response Formats
176
+ The default response format is Ruby. When the +:wt+ param is set to +:ruby+, the response is eval'd resulting in a Hash. You can get a raw response by setting the +:wt+ to +"ruby"+ - notice, the string -- not a symbol. RSolr will eval the Ruby string ONLY if the :wt value is :ruby. All other response formats are available as expected, +:wt=>'xml'+ etc..
177
+
178
+ ===Evaluated Ruby:
179
+ solr.get 'select', :params => {:wt => :ruby} # notice :ruby is a Symbol
180
+ ===Raw Ruby:
181
+ solr.get 'select', :params => {:wt => 'ruby'} # notice 'ruby' is a String
182
+ ===XML:
183
+ solr.get 'select', :params => {:wt => :xml}
184
+ ===JSON (default):
185
+ solr.get 'select', :params => {:wt => :json}
186
+
187
+ ==Related Resources & Projects
188
+ * {RSolr Google Group}[http://groups.google.com/group/rsolr] -- The RSolr discussion group
189
+ * {rsolr-ext}[http://github.com/mwmitchell/rsolr-ext] -- An extension kit for RSolr
190
+ * {rsolr-direct}[http://github.com/mwmitchell/rsolr-direct] -- JRuby direct connection for RSolr
191
+ * {rsolr-nokogiri}[http://github.com/mwmitchell/rsolr-nokogiri] -- Gives RSolr Nokogiri for XML generation.
192
+ * {SunSpot}[http://github.com/sunspot/sunspot] -- An awesome Solr DSL, built with RSolr
193
+ * {Blacklight}[http://blacklightopac.org] -- A "next generation" Library OPAC, built with RSolr
194
+ * {java_bin}[http://github.com/kennyj/java_bin] -- Provides javabin/binary parsing for RSolr
195
+ * {Solr}[http://lucene.apache.org/solr/] -- The Apache Solr project
196
+ * {solr-ruby}[http://wiki.apache.org/solr/solr-ruby] -- The original Solr Ruby Gem!
197
+
198
+ == Note on Patches/Pull Requests
199
+ * Fork the project.
200
+ * Make your feature addition or bug fix.
201
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
202
+ * Commit, do not mess with rakefile, version, or history
203
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
204
+ * Send me a pull request. Bonus points for topic branches.
205
+
206
+ ==Contributors
207
+ * Nathan Witmer
208
+ * Magnus Bergmark
209
+ * shima
210
+ * Randy Souza
211
+ * Mat Brown
212
+ * Jeremy Hinegardner
213
+ * Denis Goeury
214
+ * shairon toledo
215
+ * Rob Di Marco
216
+ * Peter Kieltyka
217
+ * Mike Perham
218
+ * Lucas Souza
219
+ * Dmitry Lihachev
220
+ * Antoine Latter
221
+ * Naomi Dushay
222
+
223
+ ==Author
224
+
225
+ Matt Mitchell <mailto:goodieboy@gmail.com>
226
+
227
+ ==Copyright
228
+
229
+ Copyright (c) 2008-2010 Matt Mitchell. See LICENSE for details.
@@ -0,0 +1,19 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ task default: ['spec']
4
+
5
+ require 'rspec/core/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ # Rdoc
10
+ require 'rdoc/task'
11
+
12
+ desc 'Generate documentation for the rsolr gem.'
13
+ RDoc::Task.new(:doc) do |rdoc|
14
+ rdoc.rdoc_dir = 'doc'
15
+ rdoc.title = 'RSolr'
16
+ rdoc.options << '--line-numbers' << '--inline-source'
17
+ rdoc.rdoc_files.include('README.rdoc')
18
+ rdoc.rdoc_files.include('lib/**/*.rb')
19
+ end
@@ -0,0 +1,52 @@
1
+ module RSolr
2
+ require 'rsolr/version'
3
+
4
+ autoload :Char, 'rsolr/char'
5
+ autoload :Client, 'rsolr/client'
6
+ autoload :Document, 'rsolr/document'
7
+ autoload :Error, 'rsolr/error'
8
+ autoload :Field, 'rsolr/field'
9
+ autoload :Generator, 'rsolr/generator'
10
+ autoload :HashWithResponse, 'rsolr/response'
11
+ autoload :JSON, 'rsolr/json'
12
+ autoload :Response, 'rsolr/response'
13
+ autoload :Uri, 'rsolr/uri'
14
+ autoload :Xml, 'rsolr/xml'
15
+
16
+ def self.connect *args
17
+ opts = args.pop if args.last.is_a?(::Hash)
18
+ opts ||= {}
19
+
20
+ connection = args.first
21
+
22
+ Client.new connection, opts
23
+ end
24
+
25
+ # backslash escape characters that have special meaning to Solr query parser
26
+ # per http://lucene.apache.org/core/4_0_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Escaping_Special_Characters
27
+ # + - & | ! ( ) { } [ ] ^ " ~ * ? : \ /
28
+ # see also http://svn.apache.org/repos/asf/lucene/dev/tags/lucene_solr_4_9_1/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java
29
+ # escapeQueryChars method
30
+ # @return [String] str with special chars preceded by a backslash
31
+ def self.solr_escape(str)
32
+ # note that the gsub will parse the escaped backslashes, as will the ruby code sending the query to Solr
33
+ # so the result sent to Solr is ultimately a single backslash in front of the particular character
34
+ str.gsub(/([+\-&|!\(\)\{\}\[\]\^"~\*\?:\\\/])/, '\\\\\1')
35
+ end
36
+
37
+ module Array
38
+ def self.wrap(object)
39
+ if object.nil?
40
+ [nil]
41
+ elsif object.respond_to?(:to_ary)
42
+ object.to_ary || [object]
43
+ elsif object.is_a? Hash
44
+ [object]
45
+ elsif object.is_a? Enumerable
46
+ object
47
+ else
48
+ [object]
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,6 @@
1
+ # :nodoc:
2
+ module RSolr::Char
3
+ def self.included(*)
4
+ warn 'RSolr::Char is deprecated without replacement, and will be removed in RSolr 3.x'
5
+ end
6
+ end
@@ -0,0 +1,342 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'faraday'
5
+ require 'uri'
6
+
7
+ class RSolr::Client
8
+ DEFAULT_URL = 'http://127.0.0.1:8983/solr/'
9
+
10
+ class << self
11
+ def default_wt
12
+ @default_wt ||= :json
13
+ end
14
+
15
+ def default_wt= value
16
+ @default_wt = value
17
+ end
18
+ end
19
+
20
+ attr_reader :uri, :proxy, :update_format, :options, :update_path
21
+
22
+ def initialize connection, options = {}
23
+ @proxy = @uri = nil
24
+ @connection = connection
25
+ unless false === options[:url]
26
+ @uri = extract_url_from_options(options)
27
+ if options[:proxy]
28
+ proxy_url = options[:proxy].dup
29
+ proxy_url << "/" unless proxy_url.nil? or proxy_url[-1] == ?/
30
+ @proxy = ::URI.parse proxy_url if proxy_url
31
+ elsif options[:proxy] == false
32
+ @proxy = false # used to avoid setting the proxy from the environment.
33
+ end
34
+ end
35
+ @update_format = options.delete(:update_format) || RSolr::JSON::Generator
36
+ @update_path = options.fetch(:update_path, 'update')
37
+ @options = options
38
+ end
39
+
40
+ def extract_url_from_options(options)
41
+ url = options[:url] ? options[:url].dup : DEFAULT_URL
42
+ url << "/" unless url[-1] == ?/
43
+ uri = ::URI.parse(url)
44
+ # URI::HTTPS is a subclass of URI::HTTP, so this check accepts HTTP(S)
45
+ raise ArgumentError, "You must provide an HTTP(S) url." unless uri.kind_of?(URI::HTTP)
46
+ uri
47
+ end
48
+
49
+ # returns the request uri object.
50
+ def base_request_uri
51
+ base_uri.request_uri if base_uri
52
+ end
53
+
54
+ # returns the URI uri object.
55
+ def base_uri
56
+ @uri
57
+ end
58
+
59
+ # Create the get, post, and head methods
60
+ %W(get post head).each do |meth|
61
+ class_eval <<-RUBY
62
+ def #{meth} path, opts = {}, &block
63
+ send_and_receive path, opts.merge(:method => :#{meth}), &block
64
+ end
65
+ RUBY
66
+ end
67
+
68
+ # A paginated request method.
69
+ # Converts the page and per_page
70
+ # arguments into "rows" and "start".
71
+ def paginate page, per_page, path, opts = nil
72
+ opts ||= {}
73
+ opts[:params] ||= {}
74
+ raise "'rows' or 'start' params should not be set when using +paginate+" if ["start", "rows"].include?(opts[:params].keys)
75
+ execute build_paginated_request(page, per_page, path, opts)
76
+ end
77
+
78
+ # POST XML messages to /update with optional params.
79
+ #
80
+ # http://wiki.apache.org/solr/UpdateXmlMessages#add.2BAC8-update
81
+ #
82
+ # If not set, opts[:headers] will be set to a hash with the key
83
+ # 'Content-Type' set to 'text/xml'
84
+ #
85
+ # +opts+ can/should contain:
86
+ #
87
+ # :data - posted data
88
+ # :headers - http headers
89
+ # :params - solr query parameter hash
90
+ #
91
+ def update opts = {}
92
+ opts[:headers] ||= {}
93
+ opts[:headers]['Content-Type'] ||= builder.content_type
94
+ post opts.fetch(:path, update_path), opts
95
+ end
96
+
97
+ # +add+ creates xml "add" documents and sends the xml data to the +update+ method
98
+ #
99
+ # http://wiki.apache.org/solr/UpdateXmlMessages#add.2BAC8-update
100
+ #
101
+ # single record:
102
+ # solr.add(:id=>1, :name=>'one')
103
+ #
104
+ # add using an array
105
+ #
106
+ # solr.add(
107
+ # [{:id=>1, :name=>'one'}, {:id=>2, :name=>'two'}],
108
+ # :add_attributes => {:boost=>5.0, :commitWithin=>10}
109
+ # )
110
+ #
111
+ def add doc, opts = {}
112
+ add_attributes = opts.delete :add_attributes
113
+ update opts.merge(:data => builder.add(doc, add_attributes))
114
+ end
115
+
116
+ # send "commit" xml with opts
117
+ #
118
+ # http://wiki.apache.org/solr/UpdateXmlMessages#A.22commit.22_and_.22optimize.22
119
+ #
120
+ def commit opts = {}
121
+ commit_attrs = opts.delete :commit_attributes
122
+ update opts.merge(:data => builder.commit( commit_attrs ))
123
+ end
124
+
125
+ # send "optimize" xml with opts.
126
+ #
127
+ # http://wiki.apache.org/solr/UpdateXmlMessages#A.22commit.22_and_.22optimize.22
128
+ #
129
+ def optimize opts = {}
130
+ optimize_attributes = opts.delete :optimize_attributes
131
+ update opts.merge(:data => builder.optimize(optimize_attributes))
132
+ end
133
+
134
+ # send </rollback>
135
+ #
136
+ # http://wiki.apache.org/solr/UpdateXmlMessages#A.22rollback.22
137
+ #
138
+ # NOTE: solr 1.4 only
139
+ def rollback opts = {}
140
+ update opts.merge(:data => builder.rollback)
141
+ end
142
+
143
+ # Delete one or many documents by id
144
+ # solr.delete_by_id 10
145
+ # solr.delete_by_id([12, 41, 199])
146
+ def delete_by_id id, opts = {}
147
+ update opts.merge(:data => builder.delete_by_id(id))
148
+ end
149
+
150
+ # delete one or many documents by query.
151
+ #
152
+ # http://wiki.apache.org/solr/UpdateXmlMessages#A.22delete.22_by_ID_and_by_Query
153
+ #
154
+ # solr.delete_by_query 'available:0'
155
+ # solr.delete_by_query ['quantity:0', 'manu:"FQ"']
156
+ def delete_by_query query, opts = {}
157
+ update opts.merge(:data => builder.delete_by_query(query))
158
+ end
159
+
160
+ def builder
161
+ @builder ||= if update_format.is_a? Class
162
+ update_format.new
163
+ elsif update_format == :json
164
+ RSolr::JSON::Generator.new
165
+ elsif update_format == :xml
166
+ RSolr::Xml::Generator.new
167
+ else
168
+ update_format
169
+ end
170
+ end
171
+
172
+ # +send_and_receive+ is the main request method responsible for sending requests to the +connection+ object.
173
+ #
174
+ # "path" : A string value that usually represents a solr request handler
175
+ # "opts" : A hash, which can contain the following keys:
176
+ # :method : required - the http method (:get, :post or :head)
177
+ # :params : optional - the query string params in hash form
178
+ # :data : optional - post data -- if a hash is given, it's sent as "application/x-www-form-urlencoded; charset=UTF-8"
179
+ # :headers : optional - hash of request headers
180
+ # All other options are passed right along to the connection's +send_and_receive+ method (:get, :post, or :head)
181
+ #
182
+ # +send_and_receive+ returns either a string or hash on a successful ruby request.
183
+ # When the :params[:wt] => :ruby, the response will be a hash, else a string.
184
+ #
185
+ # creates a request context hash,
186
+ # sends it to the connection's +execute+ method
187
+ # which returns a simple hash,
188
+ # then passes the request/response into +adapt_response+.
189
+ def send_and_receive path, opts
190
+ request_context = build_request path, opts
191
+ execute request_context
192
+ end
193
+
194
+ #
195
+ def execute request_context
196
+ raw_response = begin
197
+ response = connection.send(request_context[:method], request_context[:uri].to_s) do |req|
198
+ req.body = request_context[:data] if request_context[:method] == :post and request_context[:data]
199
+ req.headers.merge!(request_context[:headers]) if request_context[:headers]
200
+ end
201
+
202
+ { status: response.status.to_i, headers: response.headers, body: response.body.dup.force_encoding('utf-8') }
203
+ rescue Errno::ECONNREFUSED, Faraday::Error::ConnectionFailed
204
+ raise RSolr::Error::ConnectionRefused, request_context.inspect
205
+ rescue Faraday::Error => e
206
+ raise RSolr::Error::Http.new(request_context, e.response)
207
+ end
208
+ adapt_response(request_context, raw_response) unless raw_response.nil?
209
+ end
210
+
211
+ # +build_request+ accepts a path and options hash,
212
+ # then prepares a normalized hash to return for sending
213
+ # to a solr connection driver.
214
+ # +build_request+ sets up the uri/query string
215
+ # and converts the +data+ arg to form-urlencoded,
216
+ # if the +data+ arg is a hash.
217
+ # returns a hash with the following keys:
218
+ # :method
219
+ # :params
220
+ # :headers
221
+ # :data
222
+ # :uri
223
+ # :path
224
+ # :query
225
+ def build_request path, opts
226
+ raise "path must be a string or symbol, not #{path.inspect}" unless [String,Symbol].include?(path.class)
227
+ path = path.to_s
228
+ opts[:proxy] = proxy unless proxy.nil?
229
+ opts[:method] ||= :get
230
+ raise "The :data option can only be used if :method => :post" if opts[:method] != :post and opts[:data]
231
+ opts[:params] = params_with_wt(opts[:params])
232
+ query = RSolr::Uri.params_to_solr(opts[:params]) unless opts[:params].empty?
233
+ opts[:query] = query
234
+ if opts[:data].is_a? Hash
235
+ opts[:data] = RSolr::Uri.params_to_solr opts[:data]
236
+ opts[:headers] ||= {}
237
+ opts[:headers]['Content-Type'] ||= 'application/x-www-form-urlencoded; charset=UTF-8'
238
+ end
239
+ opts[:path] = path
240
+ opts[:uri] = base_uri.merge(path.to_s + (query ? "?#{query}" : "")) if base_uri
241
+
242
+ opts
243
+ end
244
+
245
+ def params_with_wt(params)
246
+ return { wt: default_wt } if params.nil?
247
+ return params if params.key?(:wt) || params.key?('wt')
248
+ { wt: default_wt }.merge(params)
249
+ end
250
+
251
+ def build_paginated_request page, per_page, path, opts
252
+ per_page = per_page.to_s.to_i
253
+ page = page.to_s.to_i-1
254
+ page = page < 1 ? 0 : page
255
+ opts[:params]["start"] = page * per_page
256
+ opts[:params]["rows"] = per_page
257
+ build_request path, opts
258
+ end
259
+
260
+ # This method will evaluate the :body value
261
+ # if the params[:uri].params[:wt] == :ruby
262
+ # ... otherwise, the body is returned as is.
263
+ # The return object has methods attached, :request and :response.
264
+ # These methods give you access to the original
265
+ # request and response from the connection.
266
+ #
267
+ # +adapt_response+ will raise an InvalidRubyResponse
268
+ # if :wt == :ruby and the body
269
+ # couldn't be evaluated.
270
+ def adapt_response request, response
271
+ raise "The response does not have the correct keys => :body, :headers, :status" unless
272
+ %W(body headers status) == response.keys.map{|k|k.to_s}.sort
273
+
274
+ result = if respond_to? "evaluate_#{request[:params][:wt]}_response", true
275
+ send "evaluate_#{request[:params][:wt]}_response", request, response
276
+ else
277
+ response[:body]
278
+ end
279
+
280
+ if result.is_a?(Hash) || request[:method] == :head
281
+ result = RSolr::HashWithResponse.new(request, response, result)
282
+ end
283
+
284
+ result
285
+ end
286
+
287
+ def connection
288
+ @connection ||= begin
289
+ conn_opts = { request: {} }
290
+ conn_opts[:url] = uri.to_s
291
+ conn_opts[:proxy] = proxy if proxy
292
+ conn_opts[:request][:open_timeout] = options[:open_timeout] if options[:open_timeout]
293
+ conn_opts[:request][:timeout] = options[:read_timeout] if options[:read_timeout]
294
+ conn_opts[:request][:params_encoder] = Faraday::FlatParamsEncoder
295
+
296
+ Faraday.new(conn_opts) do |conn|
297
+ conn.basic_auth(uri.user, uri.password) if uri.user && uri.password
298
+ conn.response :raise_error
299
+ conn.request :retry, max: options[:retry_after_limit], interval: 0.05,
300
+ interval_randomness: 0.5, backoff_factor: 2,
301
+ exceptions: ['Faraday::Error', 'Timeout::Error'] if options[:retry_503]
302
+ conn.adapter options[:adapter] || Faraday.default_adapter
303
+ end
304
+ end
305
+ end
306
+
307
+ protected
308
+
309
+ # converts the method name for the solr request handler path.
310
+ def method_missing name, *args
311
+ if name.to_s =~ /^paginated?_(.+)$/
312
+ paginate args[0], args[1], $1, *args[2..-1]
313
+ else
314
+ send_and_receive name, *args
315
+ end
316
+ end
317
+
318
+ # evaluates the response[:body],
319
+ # attempts to bring the ruby string to life.
320
+ # If a SyntaxError is raised, then
321
+ # this method intercepts and raises a
322
+ # RSolr::Error::InvalidRubyResponse
323
+ # instead, giving full access to the
324
+ # request/response objects.
325
+ def evaluate_ruby_response request, response
326
+ Kernel.eval response[:body].to_s
327
+ rescue SyntaxError
328
+ raise RSolr::Error::InvalidRubyResponse.new request, response
329
+ end
330
+
331
+ def evaluate_json_response request, response
332
+ return if response[:body].nil? || response[:body].empty?
333
+
334
+ JSON.parse response[:body].to_s
335
+ rescue JSON::ParserError
336
+ raise RSolr::Error::InvalidJsonResponse.new request, response
337
+ end
338
+
339
+ def default_wt
340
+ self.options[:default_wt] || self.class.default_wt
341
+ end
342
+ end