ansr 0.0.1 → 0.0.3
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.
- checksums.yaml +15 -0
- data/README.md +35 -0
- data/ansr.gemspec +2 -1
- data/ansr_blacklight/Gemfile +3 -0
- data/ansr_blacklight/README.md +37 -0
- data/ansr_blacklight/ansr_blacklight.gemspec +28 -0
- data/ansr_blacklight/lib/ansr_blacklight.rb +57 -0
- data/ansr_blacklight/lib/ansr_blacklight/arel.rb +6 -0
- data/ansr_blacklight/lib/ansr_blacklight/arel/big_table.rb +57 -0
- data/ansr_blacklight/lib/ansr_blacklight/arel/visitors.rb +6 -0
- data/ansr_blacklight/lib/ansr_blacklight/arel/visitors/query_builder.rb +217 -0
- data/ansr_blacklight/lib/ansr_blacklight/arel/visitors/to_no_sql.rb +14 -0
- data/ansr_blacklight/lib/ansr_blacklight/base.rb +21 -0
- data/ansr_blacklight/lib/ansr_blacklight/connection_adapters/no_sql_adapter.rb +38 -0
- data/ansr_blacklight/lib/ansr_blacklight/model/querying.rb +29 -0
- data/ansr_blacklight/lib/ansr_blacklight/relation.rb +50 -0
- data/ansr_blacklight/lib/ansr_blacklight/relation/solr_projection_methods.rb +55 -0
- data/ansr_blacklight/lib/ansr_blacklight/request_builders.rb +141 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr.rb +4 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/request.rb +46 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/response.rb +94 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/response/group.rb +32 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/response/group_response.rb +50 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/response/more_like_this.rb +14 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/response/pagination_methods.rb +35 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/response/spelling.rb +92 -0
- data/ansr_blacklight/spec/fixtures/config.yml +0 -0
- data/ansr_blacklight/spec/lib/loaded_relation_spec.rb +223 -0
- data/ansr_blacklight/spec/lib/queryable_relation_spec.rb +133 -0
- data/ansr_blacklight/spec/lib/relation/faceting_spec.rb +475 -0
- data/ansr_blacklight/spec/lib/relation/grouping_spec.rb +159 -0
- data/ansr_blacklight/spec/spec_helper.rb +72 -0
- data/ansr_dpla/Gemfile +3 -0
- data/ansr_dpla/Gemfile.lock +138 -0
- data/ansr_dpla/README.md +2 -2
- data/ansr_dpla/ansr_dpla.gemspec +2 -2
- data/ansr_dpla/lib/ansr_dpla.rb +3 -0
- data/ansr_dpla/lib/ansr_dpla/api.rb +3 -3
- data/ansr_dpla/lib/ansr_dpla/arel.rb +1 -2
- data/ansr_dpla/lib/ansr_dpla/arel/big_table.rb +4 -0
- data/ansr_dpla/lib/ansr_dpla/arel/visitors.rb +6 -0
- data/ansr_dpla/lib/ansr_dpla/arel/visitors/query_builder.rb +188 -0
- data/ansr_dpla/lib/ansr_dpla/arel/visitors/to_no_sql.rb +9 -0
- data/ansr_dpla/lib/ansr_dpla/connection_adapters/no_sql_adapter.rb +58 -0
- data/ansr_dpla/lib/ansr_dpla/model/base.rb +7 -0
- data/ansr_dpla/lib/ansr_dpla/model/querying.rb +6 -10
- data/ansr_dpla/lib/ansr_dpla/relation.rb +61 -0
- data/ansr_dpla/lib/ansr_dpla/request.rb +5 -0
- data/ansr_dpla/spec/lib/api_spec.rb +8 -5
- data/ansr_dpla/spec/lib/item_spec.rb +2 -2
- data/ansr_dpla/spec/lib/relation/facet_spec.rb +27 -19
- data/ansr_dpla/spec/lib/relation/select_spec.rb +10 -8
- data/ansr_dpla/spec/lib/relation/where_spec.rb +1 -1
- data/ansr_dpla/spec/lib/relation_spec.rb +31 -29
- data/ansr_dpla/test/system.rb +4 -2
- data/lib/ansr.rb +7 -0
- data/lib/ansr/arel.rb +3 -0
- data/lib/ansr/arel/big_table.rb +43 -3
- data/lib/ansr/arel/configured_field.rb +19 -0
- data/lib/ansr/arel/nodes.rb +41 -0
- data/lib/ansr/arel/visitors.rb +7 -0
- data/lib/ansr/arel/visitors/context.rb +13 -0
- data/lib/ansr/arel/visitors/query_builder.rb +47 -0
- data/lib/ansr/arel/visitors/to_no_sql.rb +41 -0
- data/lib/ansr/base.rb +29 -1
- data/lib/ansr/configurable.rb +6 -12
- data/lib/ansr/connection_adapters.rb +5 -0
- data/lib/ansr/connection_adapters/no_sql_adapter.rb +80 -0
- data/lib/ansr/dummy_associations.rb +105 -0
- data/lib/ansr/facets.rb +103 -0
- data/lib/ansr/model.rb +17 -107
- data/lib/ansr/model/connection_handler.rb +6 -0
- data/lib/ansr/relation.rb +40 -23
- data/lib/ansr/relation/group.rb +31 -0
- data/lib/ansr/relation/predicate_builder.rb +106 -0
- data/lib/ansr/relation/query_methods.rb +192 -45
- data/lib/ansr/sanitization.rb +5 -18
- data/lib/ansr/utils.rb +89 -0
- data/lib/ansr/version.rb +1 -1
- metadata +73 -25
- data/ansr_dpla/lib/ansr_dpla/arel/connection.rb +0 -81
- data/ansr_dpla/lib/ansr_dpla/arel/query_builder.rb +0 -131
- data/lib/ansr/model/connection.rb +0 -103
checksums.yaml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
!binary "U0hBMQ==":
|
|
3
|
+
metadata.gz: !binary |-
|
|
4
|
+
YjdhOTQ4ZmY2ZTY3OTFkM2YwZjQwNDI3MWI4NmEzYTYwMTc3YzkwZg==
|
|
5
|
+
data.tar.gz: !binary |-
|
|
6
|
+
ZDI1ODllMmMxOGMxMjg5MDI3MWEyYjIwZjQ5ODdkYWNhOGZjZTZhOA==
|
|
7
|
+
SHA512:
|
|
8
|
+
metadata.gz: !binary |-
|
|
9
|
+
MzhhMjYwMTA5YjljZjFhZmU3M2RmOWViNjZkMzg3YzA2ODIxOTRlYzc2M2Yy
|
|
10
|
+
NWUyNDI2NzY1ZTY5YzQ1ZTJhMTNmNzlmOWJjYWM1MzJlYjUyY2RiZjNkNzIx
|
|
11
|
+
ZjVlNzMyZjBlNzBjM2ZjOTNkMmI5NmRkOTZhZGQxNjJiYmI5YzE=
|
|
12
|
+
data.tar.gz: !binary |-
|
|
13
|
+
ZTlhMjE0NjczMjk0NDk1ZThmMzlkMGY0NWYwYzQ1OTU5NWVhMDA2NDY0N2Ux
|
|
14
|
+
YjE1ZGI5NTdiYTRmNGRjZmMyMmNjMzQ2ZWVlYjU4OTllN2FhNTlhYzNhMjk4
|
|
15
|
+
NDc1NjJmYTZhMGM0YTEzOTNkMjRmYmJmZDQzZTcxODQxMmI2Mjg=
|
data/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
ansr
|
|
2
|
+
====
|
|
3
|
+
|
|
4
|
+
ActiveRecord(No-SQL)::Relation + Blacklight
|
|
5
|
+
|
|
6
|
+
Ansr is a library for building ActiveRecord-style models and Relation implementations that query no-SQL data sources.
|
|
7
|
+
Ansr is motivated by a proposed refactoring of Blacklight at Code4Lib 2014.
|
|
8
|
+
|
|
9
|
+
[Blacklight](https://github.com/projectblacklight/blacklight) (BL) defines itself as “an open source Solr user interface discovery platform.” The coupling to Solr is evident in the structure: Solr querying facilities are sprinkled throughout several mixins that are included in BL controllers. This results in a codebase that cannot, as is regularly asked on the mailing lists, be used in front of another document store (eg ElasticSeach). But this is not necessarily the case.
|
|
10
|
+
|
|
11
|
+
BL might be refactored to locate the actual Solr querying machinery behind the core model of BL apps (currently called SolrDocument). Refactoring the codebase this way would realize several benefits:
|
|
12
|
+
|
|
13
|
+
1. Adherence to the Principle of Least Surprise: The BL document model would behave more like a Rails model backed by RDBMS. When bringing new developers into a BL project, familiarity with the standard patterns of Rails would translate more immediately to the BL context.
|
|
14
|
+
|
|
15
|
+
2. Flexible abstraction of the document store: Moving the specifics of querying the document store would make the introduction of models interacting with other stores possible. For example, the DPLA REST API exposes some Solr-like concepts, and a proof-of-concept model for an ActiveRecord-like approach to searching them can be seen at (https://github.com/barmintor/ansr/tree/master/ansr_dpla)
|
|
16
|
+
|
|
17
|
+
3. Clearer testing strategies and ease of console debugging
|
|
18
|
+
|
|
19
|
+
4. Clarification of BL’s relationship to RSolr as the provider to an analog for ActiveRecord::Relation
|
|
20
|
+
|
|
21
|
+
What would such a refactor require?
|
|
22
|
+
|
|
23
|
+
1. A definition of the backend requirements of BL beyond a reference to Solr per se: indexed documents with fields, a concept of facets corresponding to the Solr/Lucene definitions, the ability to expose Hash-like representations of results.
|
|
24
|
+
|
|
25
|
+
2. A relocation of the searching methods from Blacklight::Catalog and Blacklight::SolrHelper into a model generated to include Solr code
|
|
26
|
+
|
|
27
|
+
3. An accommodation of controller-specific Solr configuration, possibly resolved by having the BL config register Solr parms with the model a la SolrDocument extensions in BL 4
|
|
28
|
+
|
|
29
|
+
4. An abstraction of the fielded/faceted search parameters to mimic ActiveRecord limits
|
|
30
|
+
|
|
31
|
+
5. A partner institution capable of producing integration and system testing support for, at minimum, another Lucene-backed document store (ElasticSearch)
|
|
32
|
+
|
|
33
|
+
Since these changes are incompatible with current BL, they are proposed as a principal feature of BL 6.0.
|
|
34
|
+
|
|
35
|
+
An example of the kinds of models to be implemented can be seen in a [DPLA proof of concept](https://github.com/barmintor/ansr/tree/master/ansr_dpla).
|
data/ansr.gemspec
CHANGED
|
@@ -14,7 +14,8 @@ Gem::Specification.new do |spec|
|
|
|
14
14
|
spec.require_paths = ["lib"]
|
|
15
15
|
|
|
16
16
|
spec.add_dependency 'loggable'
|
|
17
|
-
spec.add_dependency '
|
|
17
|
+
spec.add_dependency 'arel'
|
|
18
|
+
spec.add_dependency 'activerecord'
|
|
18
19
|
|
|
19
20
|
spec.add_development_dependency("rake")
|
|
20
21
|
spec.add_development_dependency("bundler", ">= 1.0.14")
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Ansr::Blacklight
|
|
2
|
+
=================
|
|
3
|
+
|
|
4
|
+
A re-implementation of Blacklight's Solr model with find/search functionality moved behind ActiveRecord::Relation subclasses.
|
|
5
|
+
|
|
6
|
+
QUESTIONS
|
|
7
|
+
|
|
8
|
+
Is a closer conformation to the expectations from ActiveRecord valuable enough to forego use of Sunspot (https://github.com/sunspot/sunspot)?
|
|
9
|
+
|
|
10
|
+
REQUEST REQUIREMENTS
|
|
11
|
+
|
|
12
|
+
Considering the following block from the BL Solr request code:
|
|
13
|
+
SINGULAR_KEYS = %W{ facet fl q qt rows start spellcheck spellcheck.q sort
|
|
14
|
+
per_page wt hl group defType}
|
|
15
|
+
ARRAY_KEYS = %W{facet.field facet.query facet.pivot fq hl.fl }
|
|
16
|
+
|
|
17
|
+
facet : a boolean field indicating the requested presence of facet info in response
|
|
18
|
+
fl : the selected fields
|
|
19
|
+
q : the query (fielding?)
|
|
20
|
+
qt : query type; indicates queryHandler in Solr
|
|
21
|
+
rows : corresponds to limit
|
|
22
|
+
start : corresponds to offset
|
|
23
|
+
spellcheck : boolean?
|
|
24
|
+
spellcheck.q : ?
|
|
25
|
+
sort : ?
|
|
26
|
+
facet.field : the fields for which facet info is requested
|
|
27
|
+
facet.query : ?
|
|
28
|
+
facet.pivot : ?
|
|
29
|
+
fq : ?
|
|
30
|
+
hl.fl : field to highlight
|
|
31
|
+
How is facet query different from filter query (fq)?
|
|
32
|
+
|
|
33
|
+
Relations must be configurable with default parameters; this is fairly easy to do with a template Relation to spawn the default scope from.
|
|
34
|
+
|
|
35
|
+
RESPONSE REQUIREMENTS
|
|
36
|
+
|
|
37
|
+
tbd
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../lib/ansr/version')
|
|
2
|
+
version = Ansr.version
|
|
3
|
+
Gem::Specification.new do |spec|
|
|
4
|
+
spec.name = 'ansr_blacklight'
|
|
5
|
+
spec.version = version
|
|
6
|
+
spec.platform = Gem::Platform::RUBY
|
|
7
|
+
spec.authors = ["Benjamin Armintor"]
|
|
8
|
+
spec.email = ["armintor@gmail.com"]
|
|
9
|
+
spec.summary = 'ActiveRecord-style models and relations for Blacklight'
|
|
10
|
+
spec.description = 'Wrapping the Blacklight/RSolr in Rails-like models and relations'
|
|
11
|
+
spec.homepage = 'https://github.com/barmintor/ansr/tree/master/ansr_blacklight'
|
|
12
|
+
spec.files = `git ls-files`.split("\n")
|
|
13
|
+
spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
14
|
+
spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
15
|
+
spec.require_paths = ["lib"]
|
|
16
|
+
|
|
17
|
+
spec.add_dependency 'ansr', version
|
|
18
|
+
spec.add_dependency 'json-ld'
|
|
19
|
+
spec.add_dependency 'rest-client'
|
|
20
|
+
spec.add_dependency 'loggable'
|
|
21
|
+
spec.add_dependency "rails", ">= 3.2.6", "< 5"
|
|
22
|
+
# spec.add_dependency 'blacklight', '>=5.1.0'
|
|
23
|
+
spec.add_dependency 'sass-rails'
|
|
24
|
+
spec.add_development_dependency("rake")
|
|
25
|
+
spec.add_development_dependency("bundler", ">= 1.0.14")
|
|
26
|
+
spec.add_development_dependency "rspec-rails"
|
|
27
|
+
spec.add_development_dependency("yard")
|
|
28
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'ansr'
|
|
2
|
+
require 'rsolr'
|
|
3
|
+
module Ansr::Blacklight
|
|
4
|
+
extend ActiveSupport::Autoload
|
|
5
|
+
autoload :SolrProjectionMethods, 'ansr_blacklight/relation/solr_projection_methods'
|
|
6
|
+
require 'ansr_blacklight/solr'
|
|
7
|
+
require 'ansr_blacklight/request_builders'
|
|
8
|
+
require 'ansr_blacklight/arel'
|
|
9
|
+
require 'ansr_blacklight/connection_adapters/no_sql_adapter'
|
|
10
|
+
require 'ansr_blacklight/relation'
|
|
11
|
+
require 'ansr_blacklight/model/querying'
|
|
12
|
+
require 'ansr_blacklight/base'
|
|
13
|
+
|
|
14
|
+
def self.solr_file
|
|
15
|
+
"#{::Rails.root.to_s}/config/solr.yml"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.solr
|
|
19
|
+
@solr ||= RSolr.connect(Ansr::Blacklight.solr_config)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.solr_config
|
|
23
|
+
@solr_config ||= begin
|
|
24
|
+
raise "The #{::Rails.env} environment settings were not found in the solr.yml config" unless solr_yml[::Rails.env]
|
|
25
|
+
solr_yml[::Rails.env].symbolize_keys
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.solr_yml
|
|
30
|
+
require 'erb'
|
|
31
|
+
require 'yaml'
|
|
32
|
+
|
|
33
|
+
return @solr_yml if @solr_yml
|
|
34
|
+
unless File.exists?(solr_file)
|
|
35
|
+
raise "You are missing a solr configuration file: #{solr_file}. Have you run \"rails generate blacklight:install\"?"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
begin
|
|
39
|
+
@solr_erb = ERB.new(IO.read(solr_file)).result(binding)
|
|
40
|
+
rescue Exception => e
|
|
41
|
+
raise("solr.yml was found, but could not be parsed with ERB. \n#{$!.inspect}")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
begin
|
|
45
|
+
@solr_yml = YAML::load(@solr_erb)
|
|
46
|
+
rescue StandardError => e
|
|
47
|
+
raise("solr.yml was found, but could not be parsed.\n")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if @solr_yml.nil? || !@solr_yml.is_a?(Hash)
|
|
51
|
+
raise("solr.yml was found, but was blank or malformed.\n")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
return @solr_yml
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Ansr::Blacklight::Arel
|
|
2
|
+
class BigTable < Ansr::Arel::BigTable
|
|
3
|
+
attr_accessor :name
|
|
4
|
+
|
|
5
|
+
def initialize(klass, engine=nil, config=nil)
|
|
6
|
+
super(klass, engine)
|
|
7
|
+
@name = 'select'
|
|
8
|
+
self.config(config)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
delegate :index_fields, to: :config
|
|
12
|
+
delegate :show_fields, to: :config
|
|
13
|
+
delegate :sort_fields, to: :config
|
|
14
|
+
|
|
15
|
+
def filterable
|
|
16
|
+
config.facet_fields.keys
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
alias_method :facets, :filterable
|
|
20
|
+
|
|
21
|
+
def filterable?(field)
|
|
22
|
+
filterable.include? field
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def constrainable
|
|
26
|
+
index_fields.keys
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def constrainable?(field)
|
|
30
|
+
index_fields.include?(field)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def selectable
|
|
34
|
+
show_fields.keys + index_fields.keys
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def selectable?(field)
|
|
38
|
+
show_fields.include? field
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def fields
|
|
42
|
+
(constrainable + selectable + filterable).uniq
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def sortable
|
|
46
|
+
sort_fields.keys
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def sortable?(field)
|
|
50
|
+
sort_fields.include? field
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def primary_key
|
|
54
|
+
@primary_key ||= ::Arel::Attribute.new(self, config.document_unique_id_param.to_s)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
module Ansr::Blacklight::Arel::Visitors
|
|
2
|
+
class QueryBuilder < Ansr::Arel::Visitors::QueryBuilder
|
|
3
|
+
include Ansr::Blacklight::RequestBuilders
|
|
4
|
+
attr_reader :solr_request
|
|
5
|
+
|
|
6
|
+
def initialize(table)
|
|
7
|
+
super(table)
|
|
8
|
+
@solr_request = Ansr::Blacklight::Solr::Request.new
|
|
9
|
+
table.configure_fields.each do |k,v|
|
|
10
|
+
unless v[:select].blank?
|
|
11
|
+
v[:select].each do |sk, sv|
|
|
12
|
+
key = "f.#{k}.#{sk}".to_sym
|
|
13
|
+
@solr_request[key] = sv
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
public
|
|
20
|
+
def query_opts
|
|
21
|
+
solr_request
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# determines whether multiple values should accumulate or overwrite in merges
|
|
25
|
+
def multiple?(field_key)
|
|
26
|
+
true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def visit_String o, a
|
|
30
|
+
case a
|
|
31
|
+
when Ansr::Arel::Visitors::From
|
|
32
|
+
query_opts.path = o
|
|
33
|
+
when Ansr::Arel::Visitors::Filter
|
|
34
|
+
filter_field(o.to_sym)
|
|
35
|
+
when Ansr::Arel::Visitors::Order
|
|
36
|
+
order(o)
|
|
37
|
+
else
|
|
38
|
+
raise "visited String \"#{o}\" with #{a.to_s}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def visit_Arel_Nodes_TableAlias(object, attribute)
|
|
44
|
+
solr_request[:qt] = object.name.to_s
|
|
45
|
+
opts = {qt: object.name.to_s}
|
|
46
|
+
if (cf = table[object.name]).is_a? Ansr::Arel::ConfiguredField
|
|
47
|
+
opts.merge!(cf.config.fetch(:query,{}))
|
|
48
|
+
end
|
|
49
|
+
solr_request.merge!(opts)
|
|
50
|
+
visit object.relation, attribute
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def visit_Ansr_Arel_Nodes_ProjectionTraits(object, attribute)
|
|
54
|
+
solr_request[:wt] = object.wt if object.wt
|
|
55
|
+
solr_request[:defType] = object.defType if object.defType
|
|
56
|
+
visit(object.expr, attribute)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def visit_Arel_SqlLiteral(n, attribute)
|
|
60
|
+
select_val = n.to_s.split(" AS ")
|
|
61
|
+
if Ansr::Arel::Visitors::Filter === attribute
|
|
62
|
+
solr_request.append_facet_fields(select_val[0].to_sym)
|
|
63
|
+
else
|
|
64
|
+
field(select_val[0].to_sym)
|
|
65
|
+
if select_val[1]
|
|
66
|
+
query_opts.aliases ||= {}
|
|
67
|
+
query_opts.aliases[select_val[0]] = select_val[1]
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def from(value)
|
|
73
|
+
if value.respond_to? :name
|
|
74
|
+
solr_request.path = value.name
|
|
75
|
+
else
|
|
76
|
+
solr_request.path = value.to_s
|
|
77
|
+
end
|
|
78
|
+
self.table=value if (value.is_a? Ansr::Arel::BigTable)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def field(field_name)
|
|
82
|
+
return unless field_name
|
|
83
|
+
old = query_opts[:fields] ? Array(query_opts[:fields]) : []
|
|
84
|
+
field_names = (old + Array(field_name)).uniq
|
|
85
|
+
if field_names[0]
|
|
86
|
+
query_opts[:fields] = field_names[1] ? field_names : field_names[0]
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def filter_field(field_name)
|
|
91
|
+
return unless field_name
|
|
92
|
+
old = solr_request[:"facet.field"] ? Array(solr_request[:"facet.field"]) : []
|
|
93
|
+
fields = Array(field_name).delete_if {|x| old.include? x}
|
|
94
|
+
solr_request.append_facet_fields(fields)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def visit_Arel_Nodes_Equality(object, attribute)
|
|
98
|
+
field_key = (object.left.respond_to? :expr) ? field_key_from_node(object.left.expr) : field_key_from_node(object.left)
|
|
99
|
+
opts = {}
|
|
100
|
+
opts.merge!(local_field_params(field_key))
|
|
101
|
+
opts.merge!(object.left.config.fetch(:local,{})) if object.left.respond_to? :config
|
|
102
|
+
if Ansr::Arel::Visitors::Filter === attribute or Ansr::Arel::Nodes::Filter === object.left
|
|
103
|
+
add_filter_fq_to_solr(solr_request, f: {field_key => object.right}, opts: opts)
|
|
104
|
+
else
|
|
105
|
+
# check the table for configured fields
|
|
106
|
+
add_query_to_solr(field_key, object.right, opts)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def visit_Arel_Nodes_NotEqual(object, attribute)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def visit_Arel_Nodes_Or(object, attribute)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def visit_Arel_Nodes_Grouping(object, attribute)
|
|
117
|
+
visit object.expr, attribute
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def visit_Arel_Nodes_Group(object, attribute)
|
|
121
|
+
solr_request[:group] = object.expr.to_s
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def visit_Ansr_Arel_Nodes_Facet(object, attribute)
|
|
125
|
+
name = object.expr
|
|
126
|
+
name = name.name if name.respond_to? :name
|
|
127
|
+
default = false
|
|
128
|
+
if name == ::Arel.star
|
|
129
|
+
prefix = "facet."
|
|
130
|
+
default = true
|
|
131
|
+
else
|
|
132
|
+
filter_field(name.to_sym) unless default
|
|
133
|
+
solr_request.append_facet_fields(name.to_sym) unless default
|
|
134
|
+
prefix = "f.#{name}.facet."
|
|
135
|
+
end
|
|
136
|
+
# there's got to be a helper for this
|
|
137
|
+
if object.pivot
|
|
138
|
+
solr_request.append_facet_pivot with_ex_local_param(object.ex, object.pivot.join(","))
|
|
139
|
+
elsif object.query
|
|
140
|
+
solr_request.append_facet_query object.query.map { |k, x| with_ex_local_param(object.ex, x[:fq]) }
|
|
141
|
+
else
|
|
142
|
+
object.opts.each do |att, value|
|
|
143
|
+
solr_request["#{prefix}#{att.to_s}".to_sym] = value.to_s unless att == :ex
|
|
144
|
+
end
|
|
145
|
+
solr_request.append_facet_fields with_ex_local_param(object.ex, name.to_sym) unless default
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def visit_Ansr_Arel_Nodes_Spellcheck(object, attribute)
|
|
150
|
+
unless object.expr == false
|
|
151
|
+
solr_request[:spellcheck] = object.expr.to_s
|
|
152
|
+
end
|
|
153
|
+
object.opts.each do |att, val|
|
|
154
|
+
solr_request["spellcheck.#{att.to_s}".to_sym] = val if att != :select
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def visit_Ansr_Arel_Nodes_Highlight(object, attribute)
|
|
159
|
+
unless object.expr == false or object.expr == true
|
|
160
|
+
solr_request[:hl] = object.expr.to_s
|
|
161
|
+
end
|
|
162
|
+
object.opts.each do |att, val|
|
|
163
|
+
solr_request["hl.#{att.to_s}".to_sym] = val if att != :select
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def order(*arel_nodes)
|
|
168
|
+
direction = nil
|
|
169
|
+
nodes = []
|
|
170
|
+
arel_nodes.inject(nodes) do |c, n|
|
|
171
|
+
if ::Arel::Nodes::Ordering === n
|
|
172
|
+
c << n
|
|
173
|
+
elsif n.is_a? String
|
|
174
|
+
_ns = n.split(',')
|
|
175
|
+
_ns.each do |_n|
|
|
176
|
+
_p = _n.split(/\s+/)
|
|
177
|
+
if (_p[1])
|
|
178
|
+
_p[1] = _p[1].downcase.to_sym
|
|
179
|
+
else
|
|
180
|
+
_p[1] = :asc
|
|
181
|
+
end
|
|
182
|
+
c << table[_p[0].to_sym].send(_p[1])
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
c
|
|
186
|
+
end
|
|
187
|
+
nodes.each do |node|
|
|
188
|
+
if ::Arel::Nodes::Ordering === node
|
|
189
|
+
if solr_request[:sort_by]
|
|
190
|
+
solr_request[:sort_by] = Array[solr_request[:sort_by]] << node.expr.name
|
|
191
|
+
else
|
|
192
|
+
solr_request[:sort_by] = node.expr.name
|
|
193
|
+
end
|
|
194
|
+
direction = :asc if (::Arel::Nodes::Ascending === node and direction)
|
|
195
|
+
direction = :desc if (::Arel::Nodes::Descending === node)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
solr_request[:sort_order] = direction if direction
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def visit_Arel_Nodes_Limit(object, attribute)
|
|
202
|
+
value = object.expr
|
|
203
|
+
if value and (value = value.to_i)
|
|
204
|
+
raise "Page size cannot be > 500 (#{value}" if value > 500
|
|
205
|
+
solr_request[:rows] = value.to_s
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def visit_Arel_Nodes_Offset(object, attribute)
|
|
210
|
+
value = object.expr
|
|
211
|
+
if value
|
|
212
|
+
solr_request[:start] = value.to_s
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
end
|
|
217
|
+
end
|