CloudSesame 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|