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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +57 -0
- data/cloud_sesame.gemspec +1 -1
- data/lib/cloud_sesame.rb +9 -5
- data/lib/cloud_sesame/domain/base.rb +4 -12
- data/lib/cloud_sesame/query/ast/compound_array.rb +30 -35
- data/lib/cloud_sesame/query/ast/date_value.rb +1 -9
- data/lib/cloud_sesame/query/ast/literal.rb +20 -20
- data/lib/cloud_sesame/query/ast/multi_branch.rb +1 -1
- data/lib/cloud_sesame/query/ast/multi_expression_operator.rb +2 -4
- data/lib/cloud_sesame/query/ast/near.rb +11 -2
- data/lib/cloud_sesame/query/ast/phrase.rb +14 -0
- data/lib/cloud_sesame/query/ast/prefix.rb +1 -2
- data/lib/cloud_sesame/query/ast/range_value.rb +16 -41
- data/lib/cloud_sesame/query/ast/root.rb +3 -13
- data/lib/cloud_sesame/query/ast/single_branch.rb +5 -2
- data/lib/cloud_sesame/query/ast/single_expression_operator.rb +2 -4
- data/lib/cloud_sesame/query/ast/term.rb +14 -0
- data/lib/cloud_sesame/query/ast/value.rb +10 -2
- data/lib/cloud_sesame/query/builder.rb +30 -5
- data/lib/cloud_sesame/query/dsl/boost.rb +20 -0
- data/lib/cloud_sesame/query/dsl/filter_query.rb +11 -20
- data/lib/cloud_sesame/query/dsl/literal.rb +48 -8
- data/lib/cloud_sesame/query/dsl/page.rb +4 -0
- data/lib/cloud_sesame/query/dsl/return.rb +21 -0
- data/lib/cloud_sesame/query/dsl/value.rb +28 -0
- data/lib/cloud_sesame/query/node/request.rb +6 -1
- data/lib/cloud_sesame/query/node/return.rb +21 -0
- data/spec/cloud_sesame/query/ast/multi_branch_spec.rb +1 -1
- data/spec/cloud_sesame/query/ast/multi_expression_operator_spec.rb +0 -4
- data/spec/cloud_sesame/query/dsl/filter_query_spec.rb +6 -56
- data/spec/cloud_sesame/query/node/request_spec.rb +2 -2
- data/spec/cloud_sesame_spec.rb +22 -7
- metadata +8 -3
- data/lib/cloud_sesame/query/dsl/literal_helper.rb +0 -17
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d640359762a517c60a26d82969d821678bb14871
|
4
|
+
data.tar.gz: 7d9e1082e91951cd4d61061de81cba3416f8c93b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 392b5a7c410506f2a4c0547853c31e1ce282063191251eb3fa0f30b64cf3aa503d41bdb13e52ebaec879fa9de7f8dce00a34f846d667d6e0ea334d9b8dc4b55c
|
7
|
+
data.tar.gz: 064717d64e27d0ae3f172b7ab0d0bd870dd40240b93d17b5e4ff6fb6f75b7dd9cd6c4b5e0d1352dc9934997ef1c460a0ffab50c5f4b65a85736f34a7493ea1a6
|
data/Gemfile.lock
CHANGED
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
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/
|
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::
|
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
|
25
|
-
@
|
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
|
-
|
8
|
-
attr_reader :field
|
6
|
+
attr_reader :scope, :field
|
9
7
|
|
10
|
-
def
|
11
|
-
|
8
|
+
def for_field(field)
|
9
|
+
parents.clear
|
12
10
|
@field = field
|
13
11
|
end
|
14
12
|
|
15
|
-
def
|
16
|
-
|
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
|
-
#
|
25
|
+
# NEAR
|
24
26
|
# =======================================
|
25
|
-
def
|
26
|
-
|
27
|
-
insert_and_return_children
|
27
|
+
def near(*values)
|
28
|
+
parents[1] = AST::Near
|
29
|
+
insert_and_return_children values
|
28
30
|
end
|
29
31
|
|
30
|
-
alias_method :
|
32
|
+
alias_method :sloppy, :near
|
31
33
|
|
32
|
-
#
|
34
|
+
# NOT
|
33
35
|
# =======================================
|
34
|
-
def
|
35
|
-
|
36
|
-
insert_and_return_children
|
36
|
+
def not(*values)
|
37
|
+
parents[0] = AST::Not
|
38
|
+
insert_and_return_children values
|
37
39
|
end
|
38
40
|
|
39
|
-
alias_method :
|
41
|
+
alias_method :is_not, :not
|
40
42
|
|
41
|
-
# PREFIX
|
43
|
+
# PREFIX
|
42
44
|
# =======================================
|
43
45
|
def prefix(*values)
|
44
|
-
|
45
|
-
insert_and_return_children
|
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
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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
|
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 :
|
7
|
+
attr_reader :options, :value
|
8
8
|
|
9
|
-
def initialize(field, value, options = {})
|
10
|
-
|
11
|
-
|
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
|
23
|
-
|
15
|
+
def as_field
|
16
|
+
options[:as] || field
|
24
17
|
end
|
25
18
|
|
26
19
|
def compile
|
27
|
-
options[:detailed] ?
|
20
|
+
options[:detailed] ? detailed_format : standard_format
|
28
21
|
end
|
29
22
|
|
30
|
-
def
|
31
|
-
options[:
|
23
|
+
def detailed
|
24
|
+
options[:detailed] = true
|
25
|
+
return self
|
32
26
|
end
|
33
27
|
|
34
28
|
private
|
35
29
|
|
36
|
-
def
|
37
|
-
|
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
|
41
|
+
def detailed_format
|
42
42
|
"field=#{ escape as_field } #{ value.compile }"
|
43
43
|
end
|
44
44
|
|
@@ -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
|
-
|
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
|
-
|
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
|
@@ -3,73 +3,48 @@ module CloudSesame
|
|
3
3
|
module AST
|
4
4
|
class RangeValue < Value
|
5
5
|
|
6
|
-
|
7
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
62
|
-
|
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
|
66
|
-
|
42
|
+
def lb
|
43
|
+
data[1] && data[0] ? '[' : '{'
|
67
44
|
end
|
68
45
|
|
69
|
-
|
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
|