mirror of https://github.com/apache/lucene.git
Start work on flare as a plugin
git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@520716 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c537524e01
commit
e10ac8f652
|
@ -0,0 +1,11 @@
|
|||
# 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.
|
|
@ -0,0 +1,34 @@
|
|||
# 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 'rake'
|
||||
require 'rake/testtask'
|
||||
require 'rake/rdoctask'
|
||||
|
||||
desc 'Default: run unit tests.'
|
||||
task :default => :test
|
||||
|
||||
desc 'Test the flare plugin.'
|
||||
Rake::TestTask.new(:test) do |t|
|
||||
t.libs << 'lib'
|
||||
t.pattern = 'test/**/*_test.rb'
|
||||
t.verbose = true
|
||||
end
|
||||
|
||||
desc 'Generate documentation for the flare plugin.'
|
||||
Rake::RDocTask.new(:rdoc) do |rdoc|
|
||||
rdoc.rdoc_dir = 'rdoc'
|
||||
rdoc.title = 'Flare'
|
||||
rdoc.options << '--line-numbers' << '--inline-source'
|
||||
rdoc.rdoc_files.include('README')
|
||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
# 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 'flare'
|
|
@ -0,0 +1,15 @@
|
|||
# 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.
|
||||
|
||||
module Flare; end
|
||||
require 'flare/context'
|
||||
require 'flare/controller_extensions'
|
|
@ -0,0 +1,121 @@
|
|||
# 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.
|
||||
|
||||
class Flare::Context
|
||||
attr_accessor :queries, :filters, :facet_queries, :applied_facet_queries
|
||||
attr_reader :facet_fields, :text_fields
|
||||
|
||||
def initialize(solr_config)
|
||||
@solr_config = solr_config
|
||||
@connection = Solr::Connection.new(@solr_config[:solr_url])
|
||||
|
||||
clear
|
||||
@facet_queries = {} # name => {:queries => [], :filters => []}
|
||||
|
||||
@index_info = @connection.send(Solr::Request::IndexInfo.new)
|
||||
|
||||
excluded = @solr_config[:facets_exclude] ? @solr_config[:facets_exclude].collect {|e| e.to_s} : []
|
||||
@facet_fields = @index_info.field_names.find_all {|v| v =~ /_facet$/} - excluded
|
||||
|
||||
@text_fields = @index_info.field_names.find_all {|v| v =~ /_text$/}
|
||||
end
|
||||
|
||||
def clear
|
||||
@queries = []
|
||||
@filters = []
|
||||
@applied_facet_queries = []
|
||||
|
||||
# this is cleared for development purposes - allowing flare to stay running but different Solr datasets swapping
|
||||
@index_info = @connection.send(Solr::Request::IndexInfo.new)
|
||||
excluded = @solr_config[:facets_exclude] ? @solr_config[:facets_exclude].collect {|e| e.to_s} : []
|
||||
@facet_fields = @index_info.field_names.find_all {|v| v =~ /_facet$/} - excluded
|
||||
@text_fields = @index_info.field_names.find_all {|v| v =~ /_text$/}
|
||||
|
||||
# facet_queries not cleared as their lifetime is different than constraints
|
||||
end
|
||||
|
||||
def empty_constraints?
|
||||
@queries.empty? && @filters.empty? && @applied_facet_queries.empty?
|
||||
end
|
||||
|
||||
def search(start, max)
|
||||
facet_queries = @facet_queries.collect do |k,v|
|
||||
clauses = filter_queries(v[:filters])
|
||||
clauses << build_boolean_query(v[:queries])
|
||||
query = clauses.join(" AND ")
|
||||
@facet_queries[k][:real_query] = query
|
||||
query
|
||||
end
|
||||
|
||||
qa = applied_facet_queries.collect {|map| q = @facet_queries[map[:name]][:real_query]; map[:negative] ? "-(#{q})" : q}
|
||||
qa << build_boolean_query(@queries)
|
||||
request = Solr::Request::Standard.new(:query => qa.join(" AND "),
|
||||
:filter_queries => filter_queries(@filters),
|
||||
:start => start,
|
||||
:rows => max,
|
||||
:facets => {
|
||||
:fields => @facet_fields, :limit => 20 , :mincount => 1, :sort => :count,
|
||||
:queries => facet_queries
|
||||
},
|
||||
:highlighting => {:field_list => @text_fields})
|
||||
|
||||
#TODO: call response.field_facets(??) - maybe field_facets should be return a higher level?
|
||||
# logger.info({:query => query, :filter_queries => filters}.inspect)
|
||||
@connection.send(request)
|
||||
end
|
||||
|
||||
def retrieve_field_facets(field, limit=-1, prefix=nil)
|
||||
req = Solr::Request::Standard.new(:query => build_boolean_query(@queries),
|
||||
:filter_queries => filter_queries(@filters),
|
||||
:facets => {:fields => [field],
|
||||
:mincount => 1, :limit => limit, :prefix => prefix, :missing => true, :sort => :count
|
||||
},
|
||||
:rows => 0
|
||||
)
|
||||
|
||||
results = @connection.send(req)
|
||||
|
||||
results.field_facets(field)
|
||||
end
|
||||
|
||||
def to_s
|
||||
<<-TO_S
|
||||
------
|
||||
Applied facet queries: #{applied_facet_queries.inspect}
|
||||
Queries: #{queries.inspect}
|
||||
Filters: #{filters.inspect}
|
||||
Facet queries: #{facet_queries.inspect}
|
||||
------
|
||||
TO_S
|
||||
end
|
||||
|
||||
private
|
||||
def build_boolean_query(queries)
|
||||
if queries.nil? || queries.empty?
|
||||
query = "*:*"
|
||||
else
|
||||
query = queries.collect{|q| "#{q[:negative] ? '-' : ''}(#{q[:query]})"}.join(' AND ')
|
||||
end
|
||||
|
||||
query
|
||||
end
|
||||
|
||||
def filter_queries(filters)
|
||||
filters.collect do |filter|
|
||||
value = filter[:value]
|
||||
if value != "[* TO *]"
|
||||
value = "\"#{value}\""
|
||||
end
|
||||
"#{filter[:negative] ? '-' : ''}#{filter[:field]}:#{value}"
|
||||
end
|
||||
end
|
||||
end
|
153
client/ruby/flare/vendor/plugins/flare/lib/flare/controller_extensions.rb
vendored
Executable file
153
client/ruby/flare/vendor/plugins/flare/lib/flare/controller_extensions.rb
vendored
Executable file
|
@ -0,0 +1,153 @@
|
|||
# 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.
|
||||
|
||||
module Flare
|
||||
module ActionControllerExtensions
|
||||
|
||||
def self.included(base)
|
||||
base.extend(ClassMethods)
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def flare(options={})
|
||||
include Flare::ActionControllerExtensions::InstanceMethods
|
||||
end
|
||||
end
|
||||
|
||||
module InstanceMethods
|
||||
|
||||
# Assumes @flare is set by a before_filter
|
||||
|
||||
def index
|
||||
session[:page] = params[:page].to_i if params[:page]
|
||||
session[:page] = 1 if session[:page] <= 0
|
||||
|
||||
@results_per_page = 25
|
||||
|
||||
@start = (session[:page] - 1) * @results_per_page
|
||||
|
||||
@response = @flare.search(@start, @results_per_page)
|
||||
end
|
||||
|
||||
def facet
|
||||
puts "---- facet: #{params[:field]}"
|
||||
@facets = @flare.retrieve_field_facets(params[:field])
|
||||
end
|
||||
|
||||
def auto_complete_for_search_query
|
||||
# TODO instead of "text", default to the default search field configured in schema.xml
|
||||
@values = @flare.retrieve_field_facets("text", 5, params['search']['query'].downcase)
|
||||
|
||||
render :partial => 'suggest'
|
||||
end
|
||||
|
||||
|
||||
def add_query
|
||||
@flare.queries << {:query => params[:search][:query]}
|
||||
session[:page] = 1
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
def update_query
|
||||
logger.debug "update_query: #{params.inspect}"
|
||||
@flare.queries[params[:index].to_i][:query] = params[:value]
|
||||
session[:page] = 1
|
||||
render :update do |page|
|
||||
page.redirect_to '/browse'
|
||||
end
|
||||
end
|
||||
|
||||
def invert_query
|
||||
q = @flare.queries[params[:index].to_i]
|
||||
q[:negative] = !q[:negative]
|
||||
session[:page] = 1
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
def remove_query
|
||||
@flare.queries.delete_at(params[:index].to_i)
|
||||
session[:page] = 1
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
def invert_filter
|
||||
f = @flare.filters[params[:index].to_i]
|
||||
f[:negative] = !f[:negative]
|
||||
session[:page] = 1
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
def remove_filter
|
||||
@flare.filters.delete_at(params[:index].to_i)
|
||||
session[:page] = 1
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
def add_filter
|
||||
@flare.filters << {:field => params[:field], :value => params[:value], :negative => (params[:negative] ? true : false)}
|
||||
session[:page] = 1
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
def add_saved_search
|
||||
@flare.applied_facet_queries << {:name => params[:name], :negative => (params[:negative] ? true : false)}
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
def remove_saved_constraint
|
||||
@flare.applied_facet_queries.delete_at(params[:index].to_i)
|
||||
session[:page] = 1
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
def clear
|
||||
@flare.clear
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
def show_saved
|
||||
query = @flare.facet_queries[params[:name]]
|
||||
@flare.applied_facet_queries << {:name => params[:name], :negative => (params[:negative] ? true : false)}
|
||||
index
|
||||
render :action => 'index'
|
||||
end
|
||||
|
||||
def save
|
||||
@flare.facet_queries[params[:name]] = {:filters => @flare.filters.clone, :queries => @flare.queries.clone}
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
def remove_saved_search
|
||||
puts "---- BEFORE", @flare.to_s
|
||||
@flare.facet_queries.delete(params[:name])
|
||||
@flare.applied_facet_queries.delete_if {|f| params[:name] == f[:name]}
|
||||
puts "---- AFTER", @flare.to_s
|
||||
session[:page] = 1
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
def invert_saved_constraint
|
||||
f = @flare.applied_facet_queries[params[:index].to_i]
|
||||
f[:negative] = !f[:negative]
|
||||
session[:page] = 1
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
module ActionController
|
||||
class Base
|
||||
include Flare::ActionControllerExtensions
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue