lucene/client/ruby/solr-ruby/lib/solr/connection.rb

161 lines
4.7 KiB
Ruby
Executable File

# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'net/http'
# TODO: add a convenience method to POST a Solr .xml file, like Solr's example post.sh
class Solr::Connection
attr_reader :url, :autocommit, :connection
# create a connection to a solr instance using the url for the solr
# application context:
#
# conn = Solr::Connection.new("http://example.com:8080/solr")
#
# if you would prefer to have all adds/updates autocommitted,
# use :autocommit => :on
#
# conn = Solr::Connection.new('http://example.com:8080/solr',
# :autocommit => :on)
def initialize(url, opts={})
@url = URI.parse(url)
unless @url.kind_of? URI::HTTP
raise "invalid http url: #{url}"
end
# TODO: Autocommit seems nice at one level, but it currently is confusing because
# only calls to Connection#add/#update/#delete, though a Connection#send(AddDocument.new(...))
# does not autocommit. Maybe #send should check for the request types that require a commit and
# commit in #send instead of the individual methods?
@autocommit = opts[:autocommit] == :on
# Not actually opening the connection yet, just setting up the persistent connection.
@connection = Net::HTTP.new(@url.host, @url.port)
end
# add a document to the index. you can pass in either a hash
#
# conn.add(:id => 123, :title => 'Tlon, Uqbar, Orbis Tertius')
#
# or a Solr::Document
#
# conn.add(Solr::Document.new(:id => 123, :title = 'On Writing')
#
# true/false will be returned to designate success/failure
def add(doc)
request = Solr::Request::AddDocument.new(doc)
response = send(request)
commit if @autocommit
return response.ok?
end
# update a document in the index (really just an alias to add)
def update(doc)
return add(doc)
end
# performs a standard query and returns a Solr::Response::Standard
#
# response = conn.query('borges')
#
# alternative you can pass in a block and iterate over hits
#
# conn.query('borges') do |hit|
# puts hit
# end
def query(query, options={}, &action)
# TODO: Shouldn't this return an exception if the Solr status is not ok? (rather than true/false).
create_and_send_query(Solr::Request::Standard, options.update(:query => query), &action)
end
def search(query, options={}, &action)
create_and_send_query(Solr::Request::Dismax, options.update(:query => query), &action)
end
# sends a commit message to the server
def commit
response = send(Solr::Request::Commit.new)
return response.ok?
end
# sends an optimize message to the server
def optimize
response = send(Solr::Request::Optimize.new)
return response.ok?
end
# pings the connection and returns true/false if it is alive or not
def ping
begin
response = send(Solr::Request::Ping.new)
return response.ok?
rescue
return false
end
end
# delete a document from the index using the document id
def delete(document_id)
response = send(Solr::Request::Delete.new(:id => document_id))
commit if @autocommit
response.ok?
end
# delete using a query
def delete_by_query(query)
response = send(Solr::Request::Delete.new(:query => query))
commit if @autocommit
response.ok?
end
def info
send(Solr::Request::IndexInfo.new)
end
# send a given Solr::Request and return a RubyResponse or XmlResponse
# depending on the type of request
def send(request)
data = post(request)
Solr::Response::Base.make_response(request, data)
end
# send the http post request to solr; for convenience there are shortcuts
# to some requests: add(), query(), commit(), delete() or send()
def post(request)
response = @connection.post(@url.path + "/" + request.handler,
request.to_s,
{ "Content-Type" => "application/x-www-form-urlencoded; charset=utf-8" })
case response
when Net::HTTPSuccess then response.body
else
response.error!
end
end
private
def create_and_send_query(klass, options = {}, &action)
request = klass.new(options)
response = send(request)
return response unless action
response.each {|hit| action.call(hit)}
end
end