CloudSesame 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b7aad854d12632f7a254e4d4130381ecf2c1e468
4
- data.tar.gz: d150f9b6a91d47da8fd83df34b967c78507221bf
3
+ metadata.gz: d640359762a517c60a26d82969d821678bb14871
4
+ data.tar.gz: 7d9e1082e91951cd4d61061de81cba3416f8c93b
5
5
  SHA512:
6
- metadata.gz: 1a2374d616b59d412dcc228f51343ce56e0d9686ffc322f272a7ded656976ffeaab5492cd83547feec36619279bea6a97d094f66b8377692f3e509f89122ce2b
7
- data.tar.gz: 816abf070d875a9d1d2df1e54bd0b1aa23618d09c1bcbf0d4e067c6abb6170667c8889b649066bd5fbe3d1aa4be712ce5251bfc73562fdd9a0f5c4ccac1f2ceb
6
+ metadata.gz: 392b5a7c410506f2a4c0547853c31e1ce282063191251eb3fa0f30b64cf3aa503d41bdb13e52ebaec879fa9de7f8dce00a34f846d667d6e0ea334d9b8dc4b55c
7
+ data.tar.gz: 064717d64e27d0ae3f172b7ab0d0bd870dd40240b93d17b5e4ff6fb6f75b7dd9cd6c4b5e0d1352dc9934997ef1c460a0ffab50c5f4b65a85736f34a7493ea1a6
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- CloudSesame (0.1.4)
4
+ CloudSesame (0.1.6)
5
5
  aws-sdk (~> 2)
6
6
 
7
7
  GEM
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ #CloudSesame
2
+ Light and Flexible CloudSearch Query Interface
3
+
4
+ #Install
5
+ * In terminal
6
+ ```gem install CloudSesame```
7
+ * In Gemfile
8
+ ```gem 'CloudSesame```
9
+
10
+ #Setup
11
+
12
+ 2. Initalize the gem
13
+ * Inside the Rails `config/initializers` folder, create a file called `cloud_sesame.rb`
14
+ * In the file, enter in your AWS credentials
15
+
16
+ ```
17
+ require 'cloud_sesame'
18
+ CloudSesame::Domain::Client.configure do |config|
19
+ config.access_key = ENV['AWS_ACCESS_KEY_ID']
20
+ config.secret_key = ENV['AWS_SECRET_ACCESS_KEY']
21
+ end
22
+ ```
23
+
24
+ 3. Setup your searchable model
25
+
26
+ * `include CloudSesame`
27
+ * call `define_cloudsearch` to setup your CloudSearch config, default size (optional), fields, and scopes (optional).
28
+
29
+ ```
30
+ class Product
31
+ include CloudSesame
32
+
33
+ define_cloudsearch do
34
+ config.endpoint = ENV[AWS_ENDPOINT]
35
+ config.region = END[AWS_REGION]
36
+
37
+ default_size 100 #will default to 10 if not defined
38
+
39
+ field :description, query: true
40
+ field :name, query: { weight: 2 }
41
+ field :currency, facet: true
42
+ field :manufacturer, facet: { size: 50 }
43
+ field :price, facet: { buckets: %w([0, 25], [25, 50], [50, 100]), method: 'interval'}
44
+
45
+ scope :puma_shoes, -> { query("shoes").and { manufacturer "Puma" } }
46
+ scope :puma_shoes do
47
+ query("shoes").and { manufacturer "Puma" }
48
+ end
49
+
50
+ end
51
+ end
52
+ ```
53
+
54
+ 4. How to define search fields
55
+ * to add a field to query_options, set `query: true`
56
+ * to add a field to query_options with a weight, set `query: { weight: <any integer> }`
57
+ * to add a field to filter_query, set `facet : true`
data/cloud_sesame.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'CloudSesame'
3
- s.version = '0.1.5'
3
+ s.version = '0.1.6'
4
4
  s.date = '2016-01-14'
5
5
  s.summary = "AWS CloudSearch Query Interface"
6
6
  s.description = "AWS CloudSearch Query Interface"
data/lib/cloud_sesame.rb CHANGED
@@ -21,26 +21,29 @@ require 'cloud_sesame/query/dsl/page'
21
21
  require 'cloud_sesame/query/dsl/sort'
22
22
  require 'cloud_sesame/query/dsl/and'
23
23
  require 'cloud_sesame/query/dsl/or'
24
- require 'cloud_sesame/query/dsl/range'
25
24
  require 'cloud_sesame/query/dsl/literal'
26
- require 'cloud_sesame/query/dsl/literal_helper'
25
+ require 'cloud_sesame/query/dsl/value'
27
26
  require 'cloud_sesame/query/dsl/scope'
28
27
  require 'cloud_sesame/query/dsl/filter_query'
28
+ require 'cloud_sesame/query/dsl/boost'
29
+ require 'cloud_sesame/query/dsl/return'
29
30
 
30
31
  # Query Query Filter Query AST Tree
31
32
  # ===============================================
32
33
  require 'cloud_sesame/query/ast/multi_branch'
33
34
  require 'cloud_sesame/query/ast/single_branch'
34
- require 'cloud_sesame/query/ast/root'
35
- require 'cloud_sesame/query/ast/leaf'
36
35
  require 'cloud_sesame/query/ast/multi_expression_operator'
36
+ require 'cloud_sesame/query/ast/single_expression_operator'
37
37
  require 'cloud_sesame/query/ast/and'
38
38
  require 'cloud_sesame/query/ast/or'
39
- require 'cloud_sesame/query/ast/single_expression_operator'
40
39
  require 'cloud_sesame/query/ast/not'
41
40
  require 'cloud_sesame/query/ast/near'
41
+ require 'cloud_sesame/query/ast/phrase'
42
42
  require 'cloud_sesame/query/ast/prefix'
43
+ require 'cloud_sesame/query/ast/term'
43
44
  require 'cloud_sesame/query/ast/compound_array'
45
+ require 'cloud_sesame/query/ast/root'
46
+ require 'cloud_sesame/query/ast/leaf'
44
47
  require 'cloud_sesame/query/ast/literal'
45
48
  require 'cloud_sesame/query/ast/value'
46
49
  require 'cloud_sesame/query/ast/date_value'
@@ -58,6 +61,7 @@ require 'cloud_sesame/query/node/filter_query'
58
61
  require 'cloud_sesame/query/node/facet'
59
62
  require 'cloud_sesame/query/node/page'
60
63
  require 'cloud_sesame/query/node/sort'
64
+ require 'cloud_sesame/query/node/return'
61
65
 
62
66
  # Query Builder Interface
63
67
  # ===============================================
@@ -2,17 +2,13 @@ module CloudSesame
2
2
  module Domain
3
3
  class Base
4
4
  extend Forwardable
5
- include Query::DSL::Scope
5
+ include Query::Builder
6
6
 
7
7
  attr_accessor :definition
8
- attr_reader :searchable
8
+ attr_reader :searchable, :result
9
9
 
10
10
  def_delegator :client, :config
11
11
 
12
- def_delegators :builder, :query, :page, :size, :sort,
13
- :and, :or, :included?, :excluded?,
14
- :method_context, :method_return, :method_scope
15
-
16
12
  def initialize(searchable)
17
13
  @searchable = searchable
18
14
  end
@@ -21,17 +17,13 @@ module CloudSesame
21
17
  @client ||= Client.new
22
18
  end
23
19
 
24
- def builder
25
- @builder ||= CloudSesame::Query::Builder.new context, searchable
20
+ def context
21
+ @context ||= Context.new
26
22
  end
27
23
 
28
24
  # DEFAULT CONTEXT METHODS
29
25
  # =========================================
30
26
 
31
- def context
32
- @context ||= Context.new
33
- end
34
-
35
27
  def default_size(value)
36
28
  context[:page, true][:size] = value
37
29
  end
@@ -2,70 +2,65 @@ module CloudSesame
2
2
  module Query
3
3
  module AST
4
4
  class CompoundArray < Array
5
- # include Range
6
5
 
7
- attr_accessor :scope, :parent, :literal
8
- attr_reader :field
6
+ attr_reader :scope, :field
9
7
 
10
- def field=(field)
11
- self.parent = nil
8
+ def for_field(field)
9
+ parents.clear
12
10
  @field = field
13
11
  end
14
12
 
15
- def set_scope(scope)
16
- self.scope = scope
13
+ def parents
14
+ @parents ||= []
15
+ end
16
+
17
+ def scope_to(scope)
18
+ @scope = scope
17
19
  return self
18
20
  end
19
21
 
20
22
  # SINGLE BRANCH OPERATOR
21
23
  # =======================================
22
24
 
23
- # NOT
25
+ # NEAR
24
26
  # =======================================
25
- def not(*values)
26
- self.parent = AST::Not
27
- insert_and_return_children(values)
27
+ def near(*values)
28
+ parents[1] = AST::Near
29
+ insert_and_return_children values
28
30
  end
29
31
 
30
- alias_method :is_not, :not
32
+ alias_method :sloppy, :near
31
33
 
32
- # NEAR
34
+ # NOT
33
35
  # =======================================
34
- def near(*values)
35
- self.parent = AST::Near
36
- insert_and_return_children(values)
36
+ def not(*values)
37
+ parents[0] = AST::Not
38
+ insert_and_return_children values
37
39
  end
38
40
 
39
- alias_method :sloppy, :near
41
+ alias_method :is_not, :not
40
42
 
41
- # PREFIX LITERAL
43
+ # PREFIX
42
44
  # =======================================
43
45
  def prefix(*values)
44
- self.parent = AST::Prefix
45
- insert_and_return_children(values)
46
+ parents[1] = AST::Prefix
47
+ insert_and_return_children values
46
48
  end
47
49
 
48
50
  alias_method :start_with, :prefix
49
51
  alias_method :begin_with, :prefix
50
52
 
51
- # RANGE LITERAL
52
- # =======================================
53
- # def range
54
- # self.literal = AST::PrefixLiteral
55
- # insert_and_return_children(values)
56
- # return self
57
- # end
58
-
59
- # alias_method :start_with, :prefix
60
-
61
53
  def insert_and_return_children(values = [])
62
54
  values.each do |value|
63
- if parent
64
- self << (node = parent.new scope.context)
65
- node.child = AST::Literal.new(field, value, options)
66
- else
67
- self << AST::Literal.new(field, value, options)
55
+ value.child.field = field if value.kind_of?(AST::SingleExpressionOperator)
56
+ child = value.kind_of?(AST::SingleExpressionOperator) || value.kind_of?(AST::Literal) ? value : AST::Literal.new(field, value, options)
57
+
58
+ current_scope = self
59
+ parents.compact.each do |parent|
60
+ current_scope << (node = parent.new scope.context)
61
+ current_scope = node
68
62
  end
63
+ current_scope << child
69
64
  end
70
65
  return self
71
66
  end
@@ -3,16 +3,8 @@ module CloudSesame
3
3
  module AST
4
4
  class DateValue < Value
5
5
 
6
- def initialize(data)
7
- @data = data
8
- end
9
-
10
6
  def compile
11
- strip escape @data.strftime('%FT%TZ')
12
- end
13
-
14
- def to_s
15
- compile
7
+ strip escape data.strftime '%FT%TZ'
16
8
  end
17
9
 
18
10
  end
@@ -4,41 +4,41 @@ module CloudSesame
4
4
  class Literal < SingleBranch
5
5
 
6
6
  attr_accessor :field
7
- attr_reader :value, :options
7
+ attr_reader :options, :value
8
8
 
9
- def initialize(field, value, options = {})
10
- self.field = field
11
- self.value = value
12
-
13
- @options = options
14
- (options[:included] ||= []) << value
15
- end
16
-
17
- def detailed
18
- options[:detailed] = true
19
- return self
9
+ def initialize(field = nil, value = nil, options = {})
10
+ @field = field
11
+ @value = to_value value
12
+ ((@options = options || {})[:included] ||= []) << @value
20
13
  end
21
14
 
22
- def value=(value)
23
- @value = value.kind_of?(Value) ? value : Value.new(value)
15
+ def as_field
16
+ options[:as] || field
24
17
  end
25
18
 
26
19
  def compile
27
- options[:detailed] ? long_format : short_format
20
+ options[:detailed] ? detailed_format : standard_format
28
21
  end
29
22
 
30
- def as_field
31
- options[:as] || field
23
+ def detailed
24
+ options[:detailed] = true
25
+ return self
32
26
  end
33
27
 
34
28
  private
35
29
 
36
- def short_format
37
- "#{ as_field }:#{ value.compile }"
30
+ def to_value(value)
31
+ return value if value.kind_of? Value
32
+ return RangeValue.new value if value.kind_of? Range
33
+ return DateValue.new(value) if value.kind_of?(Date) || value.kind_of?(Time)
34
+ Value.new value
38
35
  end
39
36
 
37
+ def standard_format
38
+ "#{ as_field }:#{ value.compile }"
39
+ end
40
40
 
41
- def long_format
41
+ def detailed_format
42
42
  "field=#{ escape as_field } #{ value.compile }"
43
43
  end
44
44
 
@@ -14,7 +14,7 @@ module CloudSesame
14
14
  end
15
15
 
16
16
  def children
17
- @children ||= CompoundArray.new.set_scope self
17
+ @children ||= CompoundArray.new.scope_to self
18
18
  end
19
19
 
20
20
  def compile_children
@@ -2,20 +2,18 @@ module CloudSesame
2
2
  module Query
3
3
  module AST
4
4
  class MultiExpressionOperator < MultiBranch
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 } #{ compile_children })" unless children.empty?
16
+ "(#{ self.class.symbol }#{ compile_boost } #{ compile_children })" unless children.empty?
19
17
  end
20
18
 
21
19
  end
@@ -5,10 +5,19 @@ module CloudSesame
5
5
  self.symbol = :near
6
6
 
7
7
  def compile
8
- child.detailed
9
- super
8
+ child.detailed if child.kind_of?(Literal)
9
+ "(#{ self.class.symbol }#{ compile_boost }#{ compile_distance } #{ child.compile })" if child
10
10
  end
11
11
 
12
+ def distance(value)
13
+ @distance = value.to_i
14
+ return self
15
+ end
16
+
17
+ def compile_distance
18
+ " distance=#{ @distance }" if @distance
19
+ end
20
+
12
21
  end
13
22
  end
14
23
  end
@@ -0,0 +1,14 @@
1
+ module CloudSesame
2
+ module Query
3
+ module AST
4
+ class Phrase < SingleExpressionOperator
5
+ self.symbol = :phrase
6
+
7
+ def compile
8
+ child.detailed if child.kind_of?(Literal)
9
+ super
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -5,10 +5,9 @@ module CloudSesame
5
5
  self.symbol = :prefix
6
6
 
7
7
  def compile
8
- child.detailed
8
+ child.detailed if child.kind_of?(Literal)
9
9
  super
10
10
  end
11
-
12
11
  end
13
12
  end
14
13
  end
@@ -3,73 +3,48 @@ module CloudSesame
3
3
  module AST
4
4
  class RangeValue < Value
5
5
 
6
- attr_accessor :lower_bound_included,
7
- :upper_bound_included
8
-
9
- def initialize
10
- @data = [nil, nil]
6
+ def initialize(range = nil)
7
+ @data = range ? [true, to_value(range.begin), to_value(range.end), !range.exclude_end?] : [false, nil, nil, false]
11
8
  end
12
9
 
13
10
  def compile
14
- strip "#{ lower_bound }#{ lower.compile if lower },#{ upper.compile if upper }#{ upper_bound }"
15
- end
16
-
17
- def to_s
18
- compile
11
+ "#{ lb }#{ data[1].to_s },#{ data[2].to_s }#{ ub }"
19
12
  end
20
13
 
21
14
  def gt(value)
22
- self.lower = value
23
- self.lower_bound_included = false
15
+ data[0], data[1] = false, to_value(value)
24
16
  return self
25
17
  end
26
18
 
27
19
  def gte(value)
28
- self.lower = value
29
- self.lower_bound_included = true
20
+ data[0], data[1] = true, to_value(value)
30
21
  return self
31
22
  end
32
23
 
33
24
  def lt(value)
34
- self.upper = value
35
- self.upper_bound_included = false
25
+ data[2], data[3] = to_value(value), false
36
26
  return self
37
27
  end
38
28
 
39
29
  def lte(value)
40
- self.upper = value
41
- self.upper_bound_included = true
30
+ data[2], data[3] = to_value(value), true
42
31
  return self
43
32
  end
44
33
 
45
- def lower
46
- data[0]
47
- end
48
-
49
- def lower=(value)
50
- data[0] = to_value(value)
51
- end
52
-
53
- def upper
54
- data[1]
55
- end
56
-
57
- def upper=(value)
58
- data[1] = to_value(value)
59
- end
34
+ private
60
35
 
61
- def lower_bound
62
- lower && lower_bound_included ? '[' : '{'
36
+ def to_value(value)
37
+ return value if value.kind_of? Value
38
+ return DateValue.new(value) if value.kind_of?(Date) || value.kind_of?(Time)
39
+ Value.new value
63
40
  end
64
41
 
65
- def upper_bound
66
- upper && upper_bound_included ? ']' : '}'
42
+ def lb
43
+ data[1] && data[0] ? '[' : '{'
67
44
  end
68
45
 
69
- private
70
-
71
- def to_value(value)
72
- value.kind_of?(Value) ? value : Value.new(value)
46
+ def ub
47
+ data[2] && data[3] ? ']' : '}'
73
48
  end
74
49
 
75
50
  end