solr_query 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README +46 -0
  3. data/Rakefile +79 -0
  4. data/lib/blank.rb +58 -0
  5. data/lib/solr_query.rb +108 -0
  6. metadata +78 -0
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 [Matthew Rudy Jacobs]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,46 @@
1
+ SolrQuery
2
+ =========
3
+
4
+ SolrQuery is a ruby library designed to make building nested Solr queries simple and standardized.
5
+
6
+ It does everything for you,
7
+ it deals with escaping characters,
8
+ matching ActiveRecord objects by id.
9
+
10
+ It'll take an array of strings,
11
+ an array of ActiveRecords.
12
+
13
+ Give it a Hash or a Range, and it'll sort out lucene range queries for you!
14
+
15
+ Example
16
+ =======
17
+
18
+ build a query for solr;
19
+
20
+ SolrQuery.build(:keyword => "Feather duster")
21
+ #=> "feather duster"
22
+
23
+ SolrQuery.build(:keyword => "clean", :organisation => [organisation1, organisation2])
24
+ #=> "clean AND organisation:(275 OR 6534)"
25
+
26
+ SolrQuery.build(:colour => ["red", "pink"], :item_type => ["Toy", "Train"])
27
+ #=> "colour:(red OR pink) AND item_type:(Toy OR Train)"
28
+
29
+ or you can specify a different magical key for keyword;
30
+
31
+ SolrQuery.build({:keyword => "old one", :new_keyword => "new one"}, :new_keyword)
32
+ #=> "new one AND keyword:(old one)"
33
+
34
+ if you need to do range queries;
35
+
36
+ SolrQuery.build(:salary => {:min => "010000", :max => "050000"})
37
+ #=> "salary:([010000 TO 050000])"
38
+
39
+ SolrQuery.build(:salary => "010000".."050000")
40
+ #=> "salary:([010000 TO 050000])"
41
+
42
+ SolrQuery.build(:surname => {:min => "jacobs")
43
+ #=> "surname:([jacobs TO *])"
44
+
45
+
46
+ Copyright (c) 2008 [Matthew Rudy Jacobs], released under the MIT license
@@ -0,0 +1,79 @@
1
+ require 'rake'
2
+ require 'spec'
3
+ require 'spec/rake/spectask'
4
+ require 'rake/rdoctask'
5
+
6
+ desc 'Default: run the specs.'
7
+ task :default => :spec
8
+
9
+ desc 'Run specs for SolrQuery'
10
+ Spec::Rake::SpecTask.new(:spec) do |t|
11
+ t.spec_opts = ['--options', "\"spec/spec.opts\""]
12
+ t.spec_files = FileList['spec/**/*_spec.rb']
13
+ end
14
+
15
+ desc 'Generate documentation for the solr_query plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'SolrQuery'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
23
+
24
+
25
+ require "rubygems"
26
+ require "rake/gempackagetask"
27
+
28
+ Spec::Rake::SpecTask.new do |t|
29
+ t.spec_opts = %w(--format specdoc --colour)
30
+ t.libs = ["spec"]
31
+ end
32
+
33
+ # This builds the actual gem. For details of what all these options
34
+ # mean, and other ones you can add, check the documentation here:
35
+ #
36
+ # http://rubygems.org/read/chapter/20
37
+ #
38
+ spec = Gem::Specification.new do |s|
39
+
40
+ # Change these as appropriate
41
+ s.name = "solr_query"
42
+ s.version = "1.0.0"
43
+ s.description = "Build SOLR queries, properly escaped, with a nice API"
44
+ s.summary = "a ruby library designed to make building nested Solr queries simple and standardized. "
45
+ s.author = "Matthew Rudy"
46
+ s.email = "matthewrudyjacobs@gmail.com"
47
+ s.homepage = "http://github.com/matthewrudy/solr_query"
48
+
49
+ s.has_rdoc = true
50
+ s.extra_rdoc_files = %w(README)
51
+ s.rdoc_options = %w(--main README)
52
+
53
+ # Add any extra files to include in the gem
54
+ s.files = %w(MIT-LICENSE Rakefile README) + Dir.glob("{spec,lib/**/*}")
55
+ s.require_paths = ["lib"]
56
+
57
+ # If you want to depend on other gems, add them here, along with any
58
+ # relevant versions
59
+ # s.add_dependency("some_other_gem", "~> 0.1.0")
60
+
61
+ # If your tests use any gems, include them here
62
+ s.add_development_dependency("rspec")
63
+ end
64
+
65
+ # This task actually builds the gem. We also regenerate a static
66
+ # .gemspec file, which is useful if something (i.e. GitHub) will
67
+ # be automatically building a gem for this project. If you're not
68
+ # using GitHub, edit as appropriate.
69
+ #
70
+ # To publish your gem online, install the 'gemcutter' gem; Read more
71
+ # about that here: http://gemcutter.org/pages/gem_docs
72
+ Rake::GemPackageTask.new(spec) do |pkg|
73
+ pkg.gem_spec = spec
74
+
75
+ # Generate the gemspec file for github.
76
+ file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
77
+ File.open(file, "w") {|f| f << spec.to_ruby }
78
+ end
79
+
@@ -0,0 +1,58 @@
1
+ class Object
2
+ # An object is blank if it's false, empty, or a whitespace string.
3
+ # For example, "", " ", +nil+, [], and {} are blank.
4
+ #
5
+ # This simplifies
6
+ #
7
+ # if !address.nil? && !address.empty?
8
+ #
9
+ # to
10
+ #
11
+ # if !address.blank?
12
+ def blank?
13
+ respond_to?(:empty?) ? empty? : !self
14
+ end
15
+
16
+ # An object is present if it's not blank.
17
+ def present?
18
+ !blank?
19
+ end
20
+ end
21
+
22
+ class NilClass #:nodoc:
23
+ def blank?
24
+ true
25
+ end
26
+ end
27
+
28
+ class FalseClass #:nodoc:
29
+ def blank?
30
+ true
31
+ end
32
+ end
33
+
34
+ class TrueClass #:nodoc:
35
+ def blank?
36
+ false
37
+ end
38
+ end
39
+
40
+ class Array #:nodoc:
41
+ alias_method :blank?, :empty?
42
+ end
43
+
44
+ class Hash #:nodoc:
45
+ alias_method :blank?, :empty?
46
+ end
47
+
48
+ class String #:nodoc:
49
+ def blank?
50
+ self !~ /\S/
51
+ end
52
+ end
53
+
54
+ class Numeric #:nodoc:
55
+ def blank?
56
+ false
57
+ end
58
+ end
@@ -0,0 +1,108 @@
1
+ unless nil.respond_to?(:blank?)
2
+ require File.join(File.dirname(__FILE__), "blank")
3
+ end
4
+
5
+ module SolrQuery
6
+ class << self
7
+ # build a query for solr
8
+ #
9
+ # SolrQuery.build(:keyword => "Feather duster")
10
+ # => "feather duster"
11
+ #
12
+ # SolrQuery.build(:keyword => "clean", :organisation => [organisation1, organisation2])
13
+ # => "clean AND organisation:(275 OR 6534)"
14
+ #
15
+ # SolrQuery.build(:colour => ["red", "pink"], :item_type => ["Toy", "Train"])
16
+ # => "colour:(red OR pink) AND item_type:(Toy OR Train)"
17
+ #
18
+ # or you can specify a different magical key for keyword;
19
+ #
20
+ # SolrQuery.build({:keyword => "old one", :new_keyword => "new one"}, :new_keyword)
21
+ # => "new one AND keyword:(old one)"
22
+ # if you need to do range queries;
23
+ #
24
+ # SolrQuery.build(:salary => {:min => "010000", :max => "050000"})
25
+ # => "salary:([010000 TO 050000])"
26
+ #
27
+ # SolrQuery.build(:salary => "010000".."050000")
28
+ # => "salary:([010000 TO 050000])"
29
+ #
30
+ # SolrQuery.build(:surname => {:min => "jacobs")
31
+ # => "surname:([jacobs TO *])"
32
+ def build(conditions = {}, keyword_key=:keyword)
33
+ conditions = conditions.dup # let's not accidentally kill our original params
34
+ query_parts = []
35
+ keyword = conditions.delete(keyword_key) # keyword is magical
36
+ unless keyword.blank?
37
+ query_parts << "#{solr_value(keyword, true)}"
38
+ end
39
+
40
+ conditions.each do |field, value|
41
+ unless value.nil?
42
+ query_parts << "#{field}:(#{solr_value(value)})"
43
+ end
44
+ end
45
+
46
+ if query_parts.empty?
47
+ return ""
48
+ else
49
+ return query_parts.join(" AND ")
50
+ end
51
+ end
52
+
53
+ def solr_value(object, downcase=false)
54
+ if object.is_a?(Array) # case when Array will break for has_manys
55
+ if object.empty?
56
+ string = "NIL" # an empty array should be equivalent to "don't match anything"
57
+ else
58
+ string = object.map do |element|
59
+ solr_value(element, downcase)
60
+ end.join(" OR ")
61
+ downcase = false # don't downcase the ORs
62
+ end
63
+ elsif object.is_a?(Hash) || object.is_a?(Range)
64
+ return solr_range(object) # avoid escaping the *
65
+ elsif defined?(ActiveRecord) && object.is_a?(ActiveRecord::Base)
66
+ string = object.id.to_s
67
+ elsif object.is_a?(String)
68
+ if downcase && (bits = object.split(" OR ")) && bits.length > 1
69
+ return "(#{solr_value(bits, downcase)})"
70
+ else
71
+ string = object
72
+ end
73
+ else
74
+ string = object.to_s
75
+ end
76
+ string.downcase! if downcase
77
+ return escape_solr_string(string)
78
+ end
79
+ protected :solr_value
80
+
81
+ def solr_range(object)
82
+ min = max = nil
83
+ if object.is_a?(Hash)
84
+ min = object[:min]
85
+ max = object[:max]
86
+ else
87
+ min = object.first
88
+ max = object.last
89
+ end
90
+ min = solr_value(min) if min
91
+ max = solr_value(max) if max
92
+
93
+ min ||= "*"
94
+ max ||= "*"
95
+
96
+ return "[#{min} TO #{max}]"
97
+ end
98
+ protected :solr_range
99
+
100
+ def escape_solr_string(string)
101
+ string.gsub(SOLR_ESCAPE_REGEXP, "\\\\\\0").strip
102
+ end
103
+ protected :escape_solr_string
104
+ end
105
+
106
+ SOLR_ESCAPE_CHARACTERS = %w" \ + - ! ( ) : ; ^ [ ] { } ~ * ? "
107
+ SOLR_ESCAPE_REGEXP = Regexp.new(SOLR_ESCAPE_CHARACTERS.map{|char| Regexp.escape(char)}.join("|"))
108
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: solr_query
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Matthew Rudy
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-02-26 00:00:00 +08:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ version_requirements: *id001
32
+ description: Build SOLR queries, properly escaped, with a nice API
33
+ email: matthewrudyjacobs@gmail.com
34
+ executables: []
35
+
36
+ extensions: []
37
+
38
+ extra_rdoc_files:
39
+ - README
40
+ files:
41
+ - MIT-LICENSE
42
+ - Rakefile
43
+ - README
44
+ - lib/blank.rb
45
+ - lib/solr_query.rb
46
+ has_rdoc: true
47
+ homepage: http://github.com/matthewrudy/solr_query
48
+ licenses: []
49
+
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --main
53
+ - README
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.3.6
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: a ruby library designed to make building nested Solr queries simple and standardized.
77
+ test_files: []
78
+