CloudSesame 0.3.6 → 0.4.0
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/cloud_sesame.gemspec +1 -1
- data/lib/cloud_sesame/query/ast/literal.rb +7 -15
- data/lib/cloud_sesame/query/ast/near.rb +2 -2
- data/lib/cloud_sesame/query/ast/not.rb +2 -2
- data/lib/cloud_sesame/query/ast/operator.rb +0 -1
- data/lib/cloud_sesame/query/ast/range_value.rb +20 -12
- data/lib/cloud_sesame/query/ast/single_expression_operator.rb +3 -3
- data/lib/cloud_sesame/query/ast/value.rb +3 -4
- data/lib/cloud_sesame/query/builder.rb +1 -1
- data/lib/cloud_sesame/query/dsl/base.rb +4 -0
- data/lib/cloud_sesame/query/dsl/block_methods.rb +17 -3
- data/lib/cloud_sesame/query/dsl/filter_query_methods.rb +29 -14
- data/spec/cloud_sesame/query/ast/operator_spec.rb +0 -9
- data/spec/cloud_sesame_spec.rb +38 -21
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a97ed18065996a1ded5cc2b8719d43e668383f4f
|
4
|
+
data.tar.gz: 94b4b851f28cbe7b50cd7f3b7d0ce45373e07e87
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f62458643e0f3e95e404b326317016c07b94657a7f17ce471601d9f603667077affd7cf4319d7dd34553818f1e85f9a6e099973f701e5cc2c4e599e0893c08d
|
7
|
+
data.tar.gz: 756f7b2e14460b142b8ed59d5ac63dbd3f66deff02f4af71f57b4e9213e5b8ac3c5655e42796d2a20a399c0e9eedf26c88fe00d4bf295e6ddc4a1978eb242652
|
data/Gemfile.lock
CHANGED
data/cloud_sesame.gemspec
CHANGED
@@ -11,12 +11,10 @@ module CloudSesame
|
|
11
11
|
|
12
12
|
def initialize(field = nil, value = nil, options = {}, &block)
|
13
13
|
@field = field
|
14
|
-
|
15
14
|
@value = Value.parse value if value
|
16
15
|
@value = Value.parse ValueEvaluator.new.instance_exec &block if block_given?
|
17
|
-
|
18
16
|
@options = options || {}
|
19
|
-
|
17
|
+
applied[@value] = true
|
20
18
|
end
|
21
19
|
|
22
20
|
def is_for(field, options)
|
@@ -25,27 +23,21 @@ module CloudSesame
|
|
25
23
|
end
|
26
24
|
|
27
25
|
def is_excluded
|
28
|
-
|
29
|
-
(options[:excluded] ||= []) << value
|
26
|
+
applied[value] = applied[value] == false ? true : false
|
30
27
|
end
|
31
28
|
|
32
29
|
def as_field
|
33
|
-
|
30
|
+
options[:as] || field
|
34
31
|
end
|
35
32
|
|
36
33
|
def compile(detailed = false)
|
37
|
-
|
34
|
+
detailed ? detailed_format : standard_format
|
38
35
|
end
|
39
36
|
|
40
37
|
private
|
41
38
|
|
42
|
-
def
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
def recompile(detailed)
|
47
|
-
@compiled_value = value
|
48
|
-
@compiled = detailed ? detailed_format : standard_format
|
39
|
+
def applied
|
40
|
+
options[:applied] ||= {}
|
49
41
|
end
|
50
42
|
|
51
43
|
def standard_format
|
@@ -53,7 +45,7 @@ module CloudSesame
|
|
53
45
|
end
|
54
46
|
|
55
47
|
def detailed_format
|
56
|
-
"field=#{ escape as_field } #{ value.compile }"
|
48
|
+
"field=#{ escape as_field.to_s } #{ value.compile }"
|
57
49
|
end
|
58
50
|
|
59
51
|
def escape(data)
|
@@ -5,8 +5,8 @@ module CloudSesame
|
|
5
5
|
DETAILED = true
|
6
6
|
SYMBOL = :near
|
7
7
|
|
8
|
-
def compile
|
9
|
-
"(#{ symbol }#{ boost }#{ distance } #{ child.compile
|
8
|
+
def compile(detailed = nil)
|
9
|
+
"(#{ symbol }#{ boost }#{ distance } #{ child.compile operator_detailed })" if child
|
10
10
|
end
|
11
11
|
|
12
12
|
def distance
|
@@ -3,22 +3,18 @@ module CloudSesame
|
|
3
3
|
module AST
|
4
4
|
class RangeValue < Value
|
5
5
|
|
6
|
-
|
6
|
+
RANGE_FORMAT = /\A(\[|{)(.*),(.*)(\}|\])\z/
|
7
7
|
|
8
8
|
def initialize(value = nil)
|
9
9
|
@data = if value.kind_of?(Range)
|
10
10
|
range_to_array(value)
|
11
|
-
elsif value.is_a?(String) && (match =
|
11
|
+
elsif value.is_a?(String) && (match = string_format?(value))
|
12
12
|
@data = match.captures
|
13
13
|
else
|
14
14
|
default_range
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
def compile
|
19
|
-
"#{ lb }#{ l.to_s },#{ u.to_s }#{ ub }"
|
20
|
-
end
|
21
|
-
|
22
18
|
def gt(value = nil)
|
23
19
|
data[0], data[1] = '{', Value.parse(value) if value
|
24
20
|
return self
|
@@ -39,18 +35,22 @@ module CloudSesame
|
|
39
35
|
return self
|
40
36
|
end
|
41
37
|
|
42
|
-
def
|
43
|
-
|
38
|
+
def compile
|
39
|
+
"#{ lb }#{ l.to_s },#{ u.to_s }#{ ub }"
|
44
40
|
end
|
45
41
|
|
46
|
-
def
|
47
|
-
data
|
42
|
+
def ==(object)
|
43
|
+
data == Value.parse(object).data
|
48
44
|
end
|
49
45
|
|
50
46
|
private
|
51
47
|
|
52
|
-
def
|
53
|
-
|
48
|
+
def string_format?(string)
|
49
|
+
RANGE_FORMAT.match string.tr(' ', '')
|
50
|
+
end
|
51
|
+
|
52
|
+
def range_to_array(range)
|
53
|
+
['[', range.begin, range.end, end_symbol(range)]
|
54
54
|
end
|
55
55
|
|
56
56
|
def end_symbol(value)
|
@@ -61,6 +61,14 @@ module CloudSesame
|
|
61
61
|
['{', nil, nil, '}']
|
62
62
|
end
|
63
63
|
|
64
|
+
def l
|
65
|
+
data[1]
|
66
|
+
end
|
67
|
+
|
68
|
+
def u
|
69
|
+
data[2]
|
70
|
+
end
|
71
|
+
|
64
72
|
def lb
|
65
73
|
data[1] ? data[0] : '{'
|
66
74
|
end
|
@@ -21,11 +21,11 @@ module CloudSesame
|
|
21
21
|
self.child = object
|
22
22
|
end
|
23
23
|
|
24
|
-
def compile
|
25
|
-
"(#{ symbol }#{ boost } #{ child.compile
|
24
|
+
def compile(detailed = nil)
|
25
|
+
"(#{ symbol }#{ boost } #{ child.compile operator_detailed })" if child
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
28
|
+
def operator_detailed
|
29
29
|
self.class::DETAILED
|
30
30
|
end
|
31
31
|
|
@@ -3,7 +3,7 @@ module CloudSesame
|
|
3
3
|
module AST
|
4
4
|
class Value
|
5
5
|
|
6
|
-
RANGE_FORMAT = /\A
|
6
|
+
RANGE_FORMAT = /\A(\[|{)(.*),(.*)(\}|\])\z/
|
7
7
|
DIGIT_FORMAT = /\A\d+(.\d+)?\z/
|
8
8
|
SINGLE_QUATE = /\'/
|
9
9
|
ESCAPE_QUATE = "\\'"
|
@@ -12,15 +12,14 @@ module CloudSesame
|
|
12
12
|
|
13
13
|
def self.parse(value)
|
14
14
|
return value if value.kind_of? AST::Value
|
15
|
+
return AST::NumericValue.new(value) if value.is_a?(Numeric) || (value.is_a?(String) && DIGIT_FORMAT =~ value)
|
15
16
|
return AST::DateValue.new(value) if value.kind_of?(Date) || value.kind_of?(Time)
|
16
17
|
return AST::RangeValue.new(value) if value.kind_of?(Range) || (value.is_a?(String) && RANGE_FORMAT =~ value)
|
17
|
-
return AST::NumericValue.new(value) if value.is_a?(Numeric) || (value.is_a?(String) && DIGIT_FORMAT =~ value)
|
18
18
|
AST::Value.new(value)
|
19
19
|
end
|
20
20
|
|
21
21
|
def initialize(data)
|
22
22
|
@data = data
|
23
|
-
@compiled = compile
|
24
23
|
end
|
25
24
|
|
26
25
|
def compile
|
@@ -46,7 +45,7 @@ module CloudSesame
|
|
46
45
|
@compiled = escape @compiled_data
|
47
46
|
end
|
48
47
|
|
49
|
-
def escape(data
|
48
|
+
def escape(data)
|
50
49
|
"'#{ data.gsub(SINGLE_QUATE) { ESCAPE_QUATE } }'"
|
51
50
|
end
|
52
51
|
|
@@ -58,7 +58,7 @@ module CloudSesame
|
|
58
58
|
def search
|
59
59
|
compiled = request.compile
|
60
60
|
raise Error::MissingQuery.new("Query or FilterQuery can not be empty!") if !compiled[:query] || compiled[:query].empty?
|
61
|
-
@response = client.search compiled
|
61
|
+
@response = searchable.cloudsearch.client.search compiled
|
62
62
|
end
|
63
63
|
|
64
64
|
private
|
@@ -26,19 +26,33 @@ module CloudSesame
|
|
26
26
|
private
|
27
27
|
|
28
28
|
def block_style_dsl(klass, options, &block)
|
29
|
-
node = klass.new dsl_context, options
|
29
|
+
node = klass.new dsl_context, options
|
30
30
|
if block_given?
|
31
|
+
extract_caller_from block if on_root_level?
|
32
|
+
node.instance_eval &block
|
31
33
|
dsl_scope << node
|
32
34
|
dsl_return node
|
33
35
|
else
|
34
|
-
|
36
|
+
chaining_relation_for(node)
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
|
-
def
|
40
|
+
def chaining_relation_for(node)
|
39
41
|
AST::BlockChainingRelation.new(dsl_scope, dsl_return, node)
|
40
42
|
end
|
41
43
|
|
44
|
+
def on_root_level?
|
45
|
+
dsl_scope.is_a?(AST::Root)
|
46
|
+
end
|
47
|
+
|
48
|
+
def extract_caller_from(block)
|
49
|
+
dsl_context[:caller] = block.binding.eval "self"
|
50
|
+
end
|
51
|
+
|
52
|
+
def method_missing(name, *args, &block)
|
53
|
+
dsl_caller ? dsl_caller.send(name, *args, &block) : super
|
54
|
+
end
|
55
|
+
|
42
56
|
end
|
43
57
|
end
|
44
58
|
end
|
@@ -4,27 +4,42 @@ module CloudSesame
|
|
4
4
|
module FilterQueryMethods
|
5
5
|
|
6
6
|
def included?(field, value = nil)
|
7
|
-
(
|
8
|
-
(
|
9
|
-
(
|
7
|
+
!!(
|
8
|
+
(field_options = dsl_context[:fields][field]) &&
|
9
|
+
(applied = field_options[:applied]) &&
|
10
|
+
(
|
11
|
+
(!value && applied.values.any?) ||
|
12
|
+
(
|
13
|
+
value && (index = applied.keys.index(value)) &&
|
14
|
+
(field_options[:applied].values[index] != false)
|
15
|
+
)
|
16
|
+
)
|
10
17
|
)
|
11
18
|
end
|
12
19
|
|
13
20
|
def excluded?(field, value = nil)
|
14
|
-
(
|
15
|
-
(
|
16
|
-
(
|
21
|
+
!!(
|
22
|
+
(field_options = dsl_context[:fields][field]) &&
|
23
|
+
(applied = field_options[:applied]) &&
|
24
|
+
(
|
25
|
+
(!value && !applied.values.all?) ||
|
26
|
+
(
|
27
|
+
value && (index = applied.keys.index(value)) &&
|
28
|
+
field_options[:applied].values[index] == false
|
29
|
+
)
|
30
|
+
)
|
17
31
|
)
|
18
32
|
end
|
19
33
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
34
|
+
def applied_filters
|
35
|
+
applied = {}
|
36
|
+
dsl_context[:fields].each do |field, options|
|
37
|
+
if options && options[:applied] &&
|
38
|
+
!(values = options[:applied].select { |k, v| v }.keys).empty?
|
39
|
+
applied[field] = values
|
40
|
+
end
|
41
|
+
end
|
42
|
+
applied
|
28
43
|
end
|
29
44
|
|
30
45
|
end
|
@@ -9,15 +9,6 @@ module CloudSesame
|
|
9
9
|
let(:block) { Proc.new {} }
|
10
10
|
subject { Operator.new(context, options, &block) }
|
11
11
|
|
12
|
-
describe '#initialize' do
|
13
|
-
context 'given a block' do
|
14
|
-
let(:block) { Proc.new { context[:name] = :test } }
|
15
|
-
it 'should evalute the block' do
|
16
|
-
expect(subject.context[:name]).to eq :test
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
12
|
describe '#boost' do
|
22
13
|
context 'given boost option' do
|
23
14
|
let(:options) {{ boost: 2 }}
|
data/spec/cloud_sesame_spec.rb
CHANGED
@@ -62,22 +62,23 @@
|
|
62
62
|
# end
|
63
63
|
|
64
64
|
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
65
|
+
# n = 10_000
|
66
|
+
# q = nil
|
67
|
+
# result = RubyProf.profile do
|
68
|
+
# n.times do
|
68
69
|
# q = Product.cloudsearch.query("black jacket").sort(price: :asc).page(1).size(1000).and {
|
69
70
|
# or! {
|
70
|
-
# tags "
|
71
|
+
# tags "1", "2"
|
71
72
|
# and! {
|
72
|
-
# tags.not "
|
73
|
+
# tags.not "3", "4"
|
73
74
|
# }
|
74
75
|
# and!.not {
|
75
|
-
# tags.start_with "
|
76
|
-
# tags.not.start_with "
|
77
|
-
# tags.not.near "
|
78
|
-
# tags start_with("
|
79
|
-
# tags term "
|
80
|
-
# tags phrase "
|
76
|
+
# tags.start_with "5", "6"
|
77
|
+
# tags.not.start_with "7"
|
78
|
+
# tags.not.near "8"
|
79
|
+
# tags start_with("9"), near("10")
|
80
|
+
# tags term "11"
|
81
|
+
# tags phrase "12"
|
81
82
|
# }
|
82
83
|
# or!.not {
|
83
84
|
# price 25..100
|
@@ -91,15 +92,31 @@
|
|
91
92
|
# created_at gte(Date.today).lt(Date.today + 3)
|
92
93
|
# }
|
93
94
|
# }
|
94
|
-
# }
|
95
|
-
|
96
|
-
# # end
|
97
|
-
# # end
|
98
|
-
# # printer = RubyProf::FlatPrinter.new(result)
|
99
|
-
# # printer.print(STDOUT, {})
|
100
|
-
|
101
|
-
# # q = Product.cloudsearch.and {
|
102
|
-
# binding.pry
|
103
|
-
# # }
|
95
|
+
# }
|
96
|
+
# a = q.applied_filters
|
104
97
|
|
98
|
+
# end
|
99
|
+
# end
|
100
|
+
# printer = RubyProf::FlatPrinter.new(result)
|
101
|
+
# printer.print(STDOUT, {})
|
102
|
+
|
103
|
+
# binding.pry
|
104
|
+
|
105
|
+
# # class TestClass
|
106
|
+
# # def initialize
|
107
|
+
# # @name = "scott"
|
108
|
+
# # end
|
109
|
+
# # def greeting
|
110
|
+
# # "hello world!"
|
111
|
+
# # end
|
112
|
+
# # def test_method
|
113
|
+
# # local = :test
|
114
|
+
# # q = Product.cloudsearch.and {
|
115
|
+
# # binding.pry
|
116
|
+
# # }
|
117
|
+
# # end
|
118
|
+
# # end
|
119
|
+
|
120
|
+
# # test = TestClass.new
|
121
|
+
# # test.test_method
|
105
122
|
# end
|