CloudSesame 0.8.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/cloud_sesame.rb CHANGED
@@ -37,6 +37,7 @@ require 'cloud_sesame/query/dsl/range_helper'
37
37
  require 'cloud_sesame/query/dsl/response_methods'
38
38
  require 'cloud_sesame/query/dsl/return_methods'
39
39
  require 'cloud_sesame/query/dsl/sort_methods'
40
+ require 'cloud_sesame/query/dsl/k_gram_phrase_methods'
40
41
 
41
42
  # Query Query Domain Objects
42
43
  # ===============================================
@@ -10,6 +10,10 @@ module CloudSesame
10
10
  new value.to_s if value
11
11
  end
12
12
 
13
+ def to_ary
14
+ compile.split(' ')
15
+ end
16
+
13
17
  private
14
18
 
15
19
  def recompile(value)
@@ -11,6 +11,7 @@ module CloudSesame
11
11
  include DSL::ReturnMethods
12
12
  include DSL::ScopeAccessors
13
13
  include DSL::SortMethods
14
+ include DSL::KGramPhraseMethods
14
15
 
15
16
  # ClassSpecific construct class callback
16
17
  #
@@ -9,6 +9,7 @@ module CloudSesame
9
9
  include DSL::RangeHelper
10
10
  include DSL::ScopeAccessors
11
11
  include DSL::BindCaller
12
+ include DSL::KGramPhraseMethods
12
13
 
13
14
  after_construct { |_, field_accessor| include field_accessor }
14
15
 
@@ -0,0 +1,50 @@
1
+ module CloudSesame
2
+ module Query
3
+ module DSL
4
+ module KGramPhraseMethods
5
+ DELIMITER = / |-/.freeze
6
+ MULTIPLIER = 5
7
+
8
+ def k_gram_phrase(field, value, options = {})
9
+ if value && !value.empty?
10
+ words = value.split(DELIMITER).compact
11
+
12
+ or!(options) do
13
+ literal field, phrase(value, boost: MULTIPLIER * words.size)
14
+
15
+ each_k_gram_combination(words, options[:min]) do |combination, original|
16
+ remaining_terms = (original - combination).join(' ')
17
+ unique_phrase = combination.join(' ')
18
+ k = MULTIPLIER * combination.size
19
+
20
+ and!(boost: k + 2) do
21
+ literal field, phrase(unique_phrase)
22
+ literal field, term(remaining_terms)
23
+ end
24
+
25
+ literal field, phrase(unique_phrase, boost: k)
26
+ end
27
+
28
+ literal field, term(value)
29
+ end
30
+ end
31
+
32
+ _return != _scope ? _return : self
33
+ end
34
+
35
+ private
36
+
37
+ def each_k_gram_combination(array, min)
38
+ min ||= 4
39
+ size = array.size
40
+ m = [size - min, 1].max
41
+ n = size - 1
42
+ while n > m
43
+ array.each_cons(n) { |con| yield(con, array) }
44
+ n -= 1
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -9,7 +9,7 @@ module CloudSesame
9
9
  end
10
10
 
11
11
  def self.query
12
- @query
12
+ @query ||= Query
13
13
  end
14
14
 
15
15
  # CHILDREN
@@ -94,10 +94,10 @@ module CloudSesame
94
94
  context 'when given no type' do
95
95
  let(:initial_value) { 10..20 }
96
96
 
97
- it 'should not parse the start and end value' do
98
- expect(type).to_not receive(:parse)
99
- subject
100
- end
97
+ # it 'should not parse the start and end value' do
98
+ # expect(type).to_not receive(:parse)
99
+ # subject
100
+ # end
101
101
  it 'should keep the original start and end value' do
102
102
  expect(subject.begin).to be_kind_of(Numeric)
103
103
  expect(subject.end).to be_kind_of(Numeric)
@@ -143,13 +143,13 @@ module CloudSesame
143
143
  subject.parse(parse_type)
144
144
  end
145
145
  end
146
- context 'given type is nil' do
147
- let(:parse_type) { nil }
148
- it 'should not try to parse the begin and end value' do
149
- expect(parse_type).to_not receive(:parse)
150
- subject.parse(parse_type)
151
- end
152
- end
146
+ # context 'given type is nil' do
147
+ # let(:parse_type) { nil }
148
+ # it 'should not try to parse the begin and end value' do
149
+ # expect(parse_type).to_not receive(:parse)
150
+ # subject.parse(parse_type)
151
+ # end
152
+ # end
153
153
  end
154
154
 
155
155
  describe '#begin' do
@@ -0,0 +1,99 @@
1
+ module CloudSesame
2
+ module Query
3
+ module DSL
4
+ describe KGramPhraseMethods do
5
+
6
+ class Product
7
+ include CloudSesame
8
+ define_cloudsearch do
9
+ field :name, query: { weight: 2 }, type: :string
10
+ field :description, query: { weight: 0.4 }, type: :string
11
+ end
12
+ end
13
+
14
+ subject(:cloudsearch) { Product.cloudsearch.builder }
15
+ let(:root) { cloudsearch.request.filter_query.root }
16
+
17
+ describe '#k_gram_phrase' do
18
+ let(:phrase) { 'listerine mouth wash' }
19
+
20
+ it 'inserts an OR node at its scope level' do
21
+ expect { cloudsearch.k_gram_phrase(:name, phrase) }.to change { root.children }.by([AST::Or])
22
+ end
23
+
24
+ describe 'in the OR node' do
25
+ let(:or_node) { root.children.first }
26
+
27
+ it 'builds a phrase node with original term' do
28
+ cloudsearch.k_gram_phrase(:name, phrase)
29
+
30
+ phrase_node = or_node.children.first
31
+ expect(phrase_node).to be_kind_of AST::Phrase
32
+ expect(phrase_node.child.value).to eq(phrase)
33
+ end
34
+
35
+ it 'builds a term node with original term' do
36
+ cloudsearch.k_gram_phrase(:name, phrase)
37
+
38
+ term_node = or_node.children.last
39
+ expect(term_node).to be_kind_of AST::Term
40
+ expect(term_node.child.value).to eq(phrase)
41
+ end
42
+
43
+ it 'builds bunch of phrase nodes with k grams' do
44
+ cloudsearch.k_gram_phrase(:name, phrase)
45
+ k_nodes = or_node.children[1..-1]
46
+
47
+ expect(k_nodes[0]).to be_kind_of AST::And
48
+
49
+ expect(k_nodes[1]).to be_kind_of AST::Phrase
50
+ expect(k_nodes[1].options[:boost]).to eq(10)
51
+ expect(k_nodes[1].child.value).to eq('listerine mouth')
52
+
53
+ expect(k_nodes[2]).to be_kind_of AST::And
54
+
55
+ expect(k_nodes[3]).to be_kind_of AST::Phrase
56
+ expect(k_nodes[3].options[:boost]).to eq(10)
57
+ expect(k_nodes[3].child.value).to eq('mouth wash')
58
+ end
59
+
60
+ it 'builds the correct first And node' do
61
+ cloudsearch.k_gram_phrase(:name, phrase)
62
+ and_node = or_node.children[1..-1][0]
63
+
64
+ expect(and_node.options[:boost]).to eq(12)
65
+
66
+ expect(and_node.children.first).to be_kind_of AST::Phrase
67
+ expect(and_node.children.first.child.value).to eq('listerine mouth')
68
+
69
+ expect(and_node.children.last).to be_kind_of AST::Term
70
+ expect(and_node.children.last.child.value).to eq('wash')
71
+ end
72
+
73
+ it 'builds the correct second And node' do
74
+ cloudsearch.k_gram_phrase(:name, phrase)
75
+ and_node = or_node.children[1..-1][2]
76
+
77
+ expect(and_node.options[:boost]).to eq(12)
78
+
79
+ expect(and_node.children.first).to be_kind_of AST::Phrase
80
+ expect(and_node.children.first.child.value).to eq('mouth wash')
81
+
82
+ expect(and_node.children.last).to be_kind_of AST::Term
83
+ expect(and_node.children.last.child.value).to eq('listerine')
84
+ end
85
+ end
86
+
87
+ context 'when phrase is empty' do
88
+ let(:phrase) { nil }
89
+
90
+ it 'does not build anything' do
91
+ expect { cloudsearch.k_gram_phrase(:name, phrase) }.to_not change { root.children }
92
+ end
93
+ end
94
+ end
95
+
96
+ end
97
+ end
98
+ end
99
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: CloudSesame
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.3
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Chu
@@ -16,7 +16,7 @@ authors:
16
16
  autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
- date: 2016-08-25 00:00:00.000000000 Z
19
+ date: 2016-09-07 00:00:00.000000000 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: aws-sdk
@@ -188,6 +188,7 @@ files:
188
188
  - lib/cloud_sesame/query/dsl/bind_caller.rb
189
189
  - lib/cloud_sesame/query/dsl/block_styled_operators.rb
190
190
  - lib/cloud_sesame/query/dsl/inspect_method.rb
191
+ - lib/cloud_sesame/query/dsl/k_gram_phrase_methods.rb
191
192
  - lib/cloud_sesame/query/dsl/literal_chaining_methods.rb
192
193
  - lib/cloud_sesame/query/dsl/literal_methods.rb
193
194
  - lib/cloud_sesame/query/dsl/operators.rb
@@ -246,6 +247,7 @@ files:
246
247
  - spec/cloud_sesame/query/domain/block_spec.rb
247
248
  - spec/cloud_sesame/query/dsl/applied_filter_query_spec.rb
248
249
  - spec/cloud_sesame/query/dsl/block_styled_operators_spec.rb
250
+ - spec/cloud_sesame/query/dsl/k_gram_phrase_methods_spec.rb
249
251
  - spec/cloud_sesame/query/dsl/literal_chaining_methods_spec.rb
250
252
  - spec/cloud_sesame/query/dsl/literal_methods_spec.rb
251
253
  - spec/cloud_sesame/query/node/abstract_spec.rb
@@ -318,6 +320,7 @@ test_files:
318
320
  - spec/cloud_sesame/query/domain/block_spec.rb
319
321
  - spec/cloud_sesame/query/dsl/applied_filter_query_spec.rb
320
322
  - spec/cloud_sesame/query/dsl/block_styled_operators_spec.rb
323
+ - spec/cloud_sesame/query/dsl/k_gram_phrase_methods_spec.rb
321
324
  - spec/cloud_sesame/query/dsl/literal_chaining_methods_spec.rb
322
325
  - spec/cloud_sesame/query/dsl/literal_methods_spec.rb
323
326
  - spec/cloud_sesame/query/node/abstract_spec.rb