CloudSesame 0.1.5 → 0.1.6

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +57 -0
  4. data/cloud_sesame.gemspec +1 -1
  5. data/lib/cloud_sesame.rb +9 -5
  6. data/lib/cloud_sesame/domain/base.rb +4 -12
  7. data/lib/cloud_sesame/query/ast/compound_array.rb +30 -35
  8. data/lib/cloud_sesame/query/ast/date_value.rb +1 -9
  9. data/lib/cloud_sesame/query/ast/literal.rb +20 -20
  10. data/lib/cloud_sesame/query/ast/multi_branch.rb +1 -1
  11. data/lib/cloud_sesame/query/ast/multi_expression_operator.rb +2 -4
  12. data/lib/cloud_sesame/query/ast/near.rb +11 -2
  13. data/lib/cloud_sesame/query/ast/phrase.rb +14 -0
  14. data/lib/cloud_sesame/query/ast/prefix.rb +1 -2
  15. data/lib/cloud_sesame/query/ast/range_value.rb +16 -41
  16. data/lib/cloud_sesame/query/ast/root.rb +3 -13
  17. data/lib/cloud_sesame/query/ast/single_branch.rb +5 -2
  18. data/lib/cloud_sesame/query/ast/single_expression_operator.rb +2 -4
  19. data/lib/cloud_sesame/query/ast/term.rb +14 -0
  20. data/lib/cloud_sesame/query/ast/value.rb +10 -2
  21. data/lib/cloud_sesame/query/builder.rb +30 -5
  22. data/lib/cloud_sesame/query/dsl/boost.rb +20 -0
  23. data/lib/cloud_sesame/query/dsl/filter_query.rb +11 -20
  24. data/lib/cloud_sesame/query/dsl/literal.rb +48 -8
  25. data/lib/cloud_sesame/query/dsl/page.rb +4 -0
  26. data/lib/cloud_sesame/query/dsl/return.rb +21 -0
  27. data/lib/cloud_sesame/query/dsl/value.rb +28 -0
  28. data/lib/cloud_sesame/query/node/request.rb +6 -1
  29. data/lib/cloud_sesame/query/node/return.rb +21 -0
  30. data/spec/cloud_sesame/query/ast/multi_branch_spec.rb +1 -1
  31. data/spec/cloud_sesame/query/ast/multi_expression_operator_spec.rb +0 -4
  32. data/spec/cloud_sesame/query/dsl/filter_query_spec.rb +6 -56
  33. data/spec/cloud_sesame/query/node/request_spec.rb +2 -2
  34. data/spec/cloud_sesame_spec.rb +22 -7
  35. metadata +8 -3
  36. data/lib/cloud_sesame/query/dsl/literal_helper.rb +0 -17
  37. data/lib/cloud_sesame/query/dsl/range.rb +0 -41
@@ -1,21 +1,11 @@
1
1
  module CloudSesame
2
2
  module Query
3
3
  module AST
4
- class Root < MultiBranch
4
+ class Root < And
5
+ self.symbol = :and
5
6
 
6
7
  def compile
7
- if children.size > 1
8
- join_by_default_operator.compile
9
- else
10
- compile_children
11
- end
12
- end
13
-
14
- private
15
-
16
- def join_by_default_operator
17
- (default = And.new context).children.concat children
18
- default
8
+ children.size > 1 ? super : compile_children
19
9
  end
20
10
 
21
11
  end
@@ -2,7 +2,6 @@ module CloudSesame
2
2
  module Query
3
3
  module AST
4
4
  class SingleBranch
5
-
6
5
  attr_accessor :child
7
6
  attr_reader :context
8
7
 
@@ -13,11 +12,15 @@ module CloudSesame
13
12
 
14
13
  def child=(object)
15
14
  if object.kind_of? Literal
16
- (object.options[:excluded] ||= []) << object.options[:included].delete(object.value.data)
15
+ (object.options[:excluded] ||= []) << object.options[:included].delete(object.value)
17
16
  end
18
17
  @child = object
19
18
  end
20
19
 
20
+ def <<(object)
21
+ self.child= object
22
+ end
23
+
21
24
  end
22
25
  end
23
26
  end
@@ -2,20 +2,18 @@ module CloudSesame
2
2
  module Query
3
3
  module AST
4
4
  class SingleExpressionOperator < SingleBranch
5
+ include DSL::Boost
5
6
 
6
- # Operator Symbol Writer
7
7
  def self.symbol=(symbol)
8
8
  @symbol = symbol
9
9
  end
10
10
 
11
- # Operator Symbol Getter
12
11
  def self.symbol
13
12
  @symbol
14
13
  end
15
14
 
16
15
  def compile
17
- raise Error::MissingOperatorSymbol if self.class.symbol.nil?
18
- "(#{ self.class.symbol } #{ child.compile })" if child
16
+ "(#{ self.class.symbol }#{ compile_boost } #{ child.compile })" if child
19
17
  end
20
18
 
21
19
  end
@@ -0,0 +1,14 @@
1
+ module CloudSesame
2
+ module Query
3
+ module AST
4
+ class Term < SingleExpressionOperator
5
+ self.symbol = :term
6
+
7
+ def compile
8
+ child.detailed if child.kind_of?(Literal)
9
+ super
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -3,14 +3,22 @@ module CloudSesame
3
3
  module AST
4
4
  class Value < Leaf
5
5
 
6
- attr_accessor :data
6
+ attr_reader :data
7
7
 
8
8
  def initialize(data)
9
9
  @data = data
10
10
  end
11
11
 
12
12
  def compile
13
- format(data)
13
+ format data
14
+ end
15
+
16
+ def ==(value)
17
+ data == value || compile == value
18
+ end
19
+
20
+ def to_s
21
+ compile
14
22
  end
15
23
 
16
24
  private
@@ -1,13 +1,14 @@
1
1
  module CloudSesame
2
2
  module Query
3
- class Builder
3
+ module Builder
4
4
  include DSL::Base
5
5
  include DSL::FilterQuery
6
6
  include DSL::Page
7
7
  include DSL::Query
8
8
  include DSL::Sort
9
+ include DSL::Return
9
10
 
10
- attr_reader :context, :searchable, :result
11
+ attr_reader :result
11
12
 
12
13
  def initialize(default_context, searchable)
13
14
  @context = default_context
@@ -18,26 +19,50 @@ module CloudSesame
18
19
  @request ||= (clear_result; Node::Request.new context.dup)
19
20
  end
20
21
 
22
+ def response
23
+ @response ||= search
24
+ end
25
+
21
26
  def clear_request
22
27
  @request = nil
23
28
  end
24
29
 
25
30
  def clear_result
26
- @result = nil
31
+ @response = nil
32
+ end
33
+
34
+ def compile
35
+ request.compile
27
36
  end
28
37
 
29
38
  def inspect
30
- "#<CloudSesame::Query::Builder:#{ object_id } #{ request.compile }>"
39
+ "#<#{ self.class }:#{ object_id } #{ compile }>"
31
40
  end
32
41
 
33
42
  # ENDING METHODS
34
43
  # =========================================
35
44
 
45
+ def found
46
+ response.hits.found
47
+ end
48
+
49
+ def results
50
+ response.hits.hit
51
+ end
52
+
53
+ def each(&block)
54
+ results.each &block
55
+ end
56
+
57
+ def map(&block)
58
+ results.map &block
59
+ end
60
+
36
61
  def search
37
62
  compiled = request.compile
38
63
  raise Error::MissingQuery.new("Query or FilterQuery can not be empty!") if !compiled[:query] || compiled[:query].empty?
39
64
  clear_request
40
- @result = searchable.cloudsearch.client.search compiled
65
+ @response = client.search compiled
41
66
  end
42
67
 
43
68
  private
@@ -0,0 +1,20 @@
1
+ module CloudSesame
2
+ module Query
3
+ module DSL
4
+ module Boost
5
+
6
+ def compile_boost
7
+ " boost=#{ @boost }" if @boost
8
+ end
9
+
10
+ def boost(value)
11
+ @boost = value.to_i
12
+ return self
13
+ end
14
+
15
+ alias_method :weight, :boost
16
+
17
+ end
18
+ end
19
+ end
20
+ end
@@ -2,43 +2,34 @@ module CloudSesame
2
2
  module Query
3
3
  module DSL
4
4
  module FilterQuery
5
- include Scope
6
5
  include And
7
- include Or
8
6
  include Literal
9
- include LiteralHelper
7
+ include Or
8
+ include Scope
9
+ include Value
10
10
 
11
- # { fields: { tags: { excluded: [100] } } }
12
11
  def included?(field, value = nil)
13
12
  (field_options = method_scope.context[:fields][field]) && (
14
- (value && field_includes?(field_options, value)) ||
15
- (!value && field_included_is_not_empty?(field_options))
13
+ (value && field_options_is(:included, field_options, value)) ||
14
+ (!value && field_options_not_empty_in(:included, field_options))
16
15
  )
17
16
  end
18
17
 
19
18
  def excluded?(field, value = nil)
20
19
  (field_options = method_scope.context[:fields][field]) && (
21
- (value && field_excludes?(field_options, value)) ||
22
- (!value && field_excluded_is_not_empty?(field_options))
20
+ (value && field_options_is(:excluded, field_options, value)) ||
21
+ (!value && field_options_not_empty_in(:excluded, field_options))
23
22
  )
24
23
  end
25
24
 
26
25
  private
27
26
 
28
- def field_includes?(field_options, value)
29
- field_options[:included] && field_options[:included].include?(value)
30
- end
31
-
32
- def field_included_is_not_empty?(field_options)
33
- field_options[:included] && !field_options[:included].empty?
34
- end
35
-
36
- def field_excludes?(field_options, value)
37
- field_options[:excluded] && field_options[:excluded].include?(value)
27
+ def field_options_is(type, field_options, value)
28
+ (values = field_options[type]) && values.include?(value)
38
29
  end
39
30
 
40
- def field_excluded_is_not_empty?(field_options)
41
- field_options[:excluded] && !field_options[:excluded].empty?
31
+ def field_options_not_empty_in(type, field_options)
32
+ field_options[type] && !field_options[type].empty?
42
33
  end
43
34
 
44
35
 
@@ -3,12 +3,45 @@ module CloudSesame
3
3
  module DSL
4
4
  module Literal
5
5
 
6
- # CLAUSE: LITERAL
7
- # =========================================
8
- def literal(field, value, options = {})
9
- node = AST::Literal.new(field, value, options)
10
- method_scope.children << node
11
- node
6
+ # LITERAL: creates a single LITERAL node
7
+ # =======================================
8
+ def literal(value)
9
+ field = method_scope.children.field
10
+ AST::Literal.new field, value, fields[field]
11
+ end
12
+
13
+ alias_method :l, :literal
14
+ alias_method :field, :literal
15
+
16
+ # NEAR: creates a single NEAR node
17
+ # =======================================
18
+ def near(value)
19
+ create_literal_with_operator AST::Near, value
20
+ end
21
+
22
+ alias_method :n, :near
23
+ alias_method :sloppy, :near
24
+
25
+ # PREFIX: creates a single PREFIX node
26
+ # =======================================
27
+ def prefix(value)
28
+ create_literal_with_operator AST::Prefix, value
29
+ end
30
+
31
+ alias_method :p, :prefix
32
+ alias_method :start_with, :prefix
33
+ alias_method :begin_with, :prefix
34
+
35
+ # PHRASE: creates a single PHRASE node
36
+ # =======================================
37
+ def phrase(value)
38
+ create_literal_with_operator AST::Phrase, value
39
+ end
40
+
41
+ # TERM: creates a single TERM node
42
+ # =======================================
43
+ def term(value)
44
+ create_literal_with_operator AST::Term, value
12
45
  end
13
46
 
14
47
  private
@@ -17,10 +50,17 @@ module CloudSesame
17
50
  method_context[:fields]
18
51
  end
19
52
 
53
+ def create_literal_with_operator(klass, value)
54
+ field = method_scope.children.field
55
+ literal = AST::Literal.new field, value, fields[field]
56
+ (node = klass.new method_context) << literal
57
+ node
58
+ end
59
+
20
60
  def method_missing(field, *values, &block)
21
61
  if fields && (options = fields[field])
22
- method_scope.children.field = field
23
- method_scope.children.insert_and_return_children(values)
62
+ method_scope.children.for_field field
63
+ method_scope.children.insert_and_return_children values
24
64
  else
25
65
  super
26
66
  end
@@ -3,6 +3,8 @@ module CloudSesame
3
3
  module DSL
4
4
  module Page
5
5
 
6
+ # CLAUSE: PAGE and SIZE
7
+ # =========================================
6
8
  def page(input = nil)
7
9
  if input
8
10
  request.page.page = input.to_i
@@ -21,6 +23,8 @@ module CloudSesame
21
23
  end
22
24
  end
23
25
 
26
+ alias_method :limit, :size
27
+
24
28
  end
25
29
  end
26
30
  end
@@ -0,0 +1,21 @@
1
+ module CloudSesame
2
+ module Query
3
+ module DSL
4
+ module Return
5
+
6
+ def all_fields
7
+ request.return_field.value = :all_fields
8
+ end
9
+
10
+ def no_fields
11
+ request.return_field.value = :no_fields
12
+ end
13
+
14
+ def score
15
+ request.return_field.value = :score
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ module CloudSesame
2
+ module Query
3
+ module DSL
4
+ module Value
5
+
6
+ # VALUE DSL
7
+ # =======================================
8
+
9
+ # DATE
10
+ # =======================================
11
+ def date(date)
12
+ AST::DateValue.new date
13
+ end
14
+
15
+ alias_method :d, :date
16
+
17
+ # RANGE
18
+ # =======================================
19
+ def range(range = nil)
20
+ AST::RangeValue.new range
21
+ end
22
+
23
+ alias_method :r, :range
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -34,6 +34,10 @@ module CloudSesame
34
34
  @sort ||= Sort.new(context[:sort, true])
35
35
  end
36
36
 
37
+ def return_field
38
+ @return ||= Return.new(context[:return, true])
39
+ end
40
+
37
41
  # EVALUATION
38
42
  # =========================================
39
43
 
@@ -44,7 +48,8 @@ module CloudSesame
44
48
  query_parser,
45
49
  filter_query,
46
50
  page,
47
- sort
51
+ sort,
52
+ return_field
48
53
  ].each_with_object({}) do |node, compiled|
49
54
  compiled.merge!(node.compile || {})
50
55
  end
@@ -0,0 +1,21 @@
1
+ module CloudSesame
2
+ module Query
3
+ module Node
4
+ class Return < Abstract
5
+
6
+ attr_accessor :value
7
+
8
+ def compile
9
+ { return: format(value) } if value
10
+ end
11
+
12
+ private
13
+
14
+ def format(value)
15
+ value.to_s.gsub(/^_?/, '_')
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end