qiita-elasticsearch 0.2.1 → 0.2.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8560c892e6ef0e111e0a382d6d194b93eed3fb82
4
- data.tar.gz: c7fde536c988141b2550462cac74a38419b8933c
3
+ metadata.gz: aaa3120e317dceee23661a755b4a9eb2f38f2694
4
+ data.tar.gz: db119b903847b6287106d7205a945aa6218c7816
5
5
  SHA512:
6
- metadata.gz: 4835e6a0299c1dc4e930b347e26854763a1e5e968488a91db46e40b773acc6ebb0472d21103c8c9e9cec460ee9f6f31e8553149068dc98a2e09aa3896ccc0b90
7
- data.tar.gz: 074d7ecd0a00f12fea0513bae0a875aa6b554c46c2a3d8d0cabe6c691ba92d0ace07e43ef41d5f846d56ca01194746014305ddbdf44922aaa30c616e40edf271
6
+ metadata.gz: 5f3454a506c3c3fae11b682c23acd2a4d0b197cd8409f67b98078e6cead69c8e92a9949119d556675c6333439204a0dc25bae5c819cc843968267c593083de9e
7
+ data.tar.gz: 54baba6c1bd52bba643b8961c5038ce86f8d3de46afd6682f706b0a139995c16dc0685667e9af16f0bfb9bdcfbd7fb12643ed90fba344367ccde0b639672b8ad
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## 0.2.2
2
+ - Support range fields
3
+
1
4
  ## 0.2.1
2
5
  - Fix _cache property on filtered queries
3
6
 
data/README.md CHANGED
@@ -6,7 +6,7 @@ Elasticsearch client helper for Qiita.
6
6
 
7
7
  ```rb
8
8
  query_builder = Qiita::Elasticsearch::QueryBuilder.new
9
- #=> #<Qiita::Elasticsearch::QueryBuilder:0x007ff81e67c4d8 @filterable_fields=nil, @matchable_fields=nil>
9
+ #=> #<Qiita::Elasticsearch::QueryBuilder:0x007ff81e67c4d8 @filterable_fields=nil, @hierarchal_fields=nil, @matchable_fields=nil>
10
10
 
11
11
  query_builder.build("a")
12
12
  #=> {"match"=>{"_all"=>"a"}}
@@ -15,7 +15,7 @@ query_builder.build("a b")
15
15
  #=> {"bool"=>{"should"=>[{"match"=>{"_all"=>"a"}}, {"match"=>{"_all"=>"b"}}]}}
16
16
 
17
17
  query_builder.build("a -b")
18
- #=> {"bool"=>{"must_not"=>[{"match"=>{"_all"=>"b"}}], "should"=>[{"match"=>{"_all"=>"a"}}]}}
18
+ #=> {"filtered"=> {"filter"=>{"bool"=>{"_cache"=>true, "must_not"=>[{"match"=>{"_all"=>"b"}}]}}, "query"=>{"match"=>{"_all"=>"a"}}}}
19
19
 
20
20
  query_builder.build('"a b"')
21
21
  #=> {"match_phrase"=>{"_all"=>"a b"}}
@@ -29,7 +29,7 @@ Pass `:matchable_fields` option to tell matchable field names (default: `_all`).
29
29
 
30
30
  ```rb
31
31
  query_builder = Qiita::Elasticsearch::QueryBuilder.new(matchable_fields: ["body", "title"])
32
- #=> #<Qiita::Elasticsearch::QueryBuilder:0x007ff81fa59168 @filterable_fields=nil, @matchable_fields=["body", "title"]>
32
+ #=> #<Qiita::Elasticsearch::QueryBuilder:0x007ff81fa59168 @filterable_fields=nil, @hierarchal_fields=nil, @matchable_fields=["body", "title"], @range_fields=nil>
33
33
 
34
34
  query_builder.build("a")
35
35
  #=> {"multi_match"=>{"fields"=>["body", "title"], "query"=>"a"}}
@@ -40,13 +40,13 @@ Pass `:filterable_fields` option to enable filtered queries like `tag:Ruby`.
40
40
 
41
41
  ```rb
42
42
  query_builder = Qiita::Elasticsearch::QueryBuilder.new(filterable_fields: ["tag", "title"])
43
- #=> #<Qiita::Elasticsearch::QueryBuilder:0x007ff81e2de1f0 @filterable_fields=["tag", "title"], @matchable_fields=nil>
43
+ #=> #<Qiita::Elasticsearch::QueryBuilder:0x007ff81e2de1f0 @filterable_fields=["tag", "title"], @hierarchal_fields=nil, @matchable_fields=nil, @range_fields=nil>
44
44
 
45
45
  query_builder.build("tag:a")
46
46
  #=> {"filtered"=>{"filter"=>{"term"=>{"tag"=>"a"}}}}
47
47
 
48
48
  query_builder.build("tag:a b")
49
- #=> {"bool"=>{"must"=>[{"filtered"=>{"filter"=>{"term"=>{"tag"=>"a"}}}}], "should"=>[{"match"=>{"_all"=>"b"}}]}}
49
+ #=> {"filtered"=>{"filter"=>{"term"=>{"tag"=>"a"}}, "query"=>{"match"=>{"_all"=>"b"}}}}
50
50
 
51
51
  query_builder.build("user:a b")
52
52
  #=> {"bool"=>{"should"=>[{"match"=>{"_all"=>"user:a"}}, {"match"=>{"_all"=>"b"}}]}}
@@ -58,8 +58,20 @@ With this option, `tag:foo` will hit documents tagged with `foo`, or `foo/...`.
58
58
 
59
59
  ```rb
60
60
  query_builder = Qiita::Elasticsearch::QueryBuilder.new(filterable_fields: ["tag"], hierarchal_fields: ["tag"])
61
- #=> #<Qiita::Elasticsearch::QueryBuilder:0x007fe96d6d5ed0 @filterable_fields=["tag"], @hierarchal_fields=["tag"], @matchable_fields=nil>
61
+ #=> #<Qiita::Elasticsearch::QueryBuilder:0x007fe96d6d5ed0 @filterable_fields=["tag"], @hierarchal_fields=["tag"], @matchable_fields=nil, @range_fields=nil>
62
62
 
63
63
  query_builder.build("tag:ruby")
64
64
  #=> {"filtered"=>{"filter"=>{"bool"=>{"should"=>[{"prefix"=>{"tag"=>"ruby/"}}, {"term"=>{"tag"=>"ruby"}}]}}}}
65
65
  ```
66
+
67
+ ### range_fields
68
+ Pass `:range_fields` options with `:filterable_fields` to enable range filtered queries.
69
+ With this option, `created_at:<2015-04-16` will hit documents created before 2015-04-16.
70
+
71
+ ```rb
72
+ query_builder = Qiita::Elasticsearch::QueryBuilder.new(filterable_fields: ["created_at"], range_fields: ["created_at"])
73
+ #=> #<Qiita::Elasticsearch::QueryBuilder:0x007fe96d6d5ed0 @filterable_fields=["created_at"], @hierarchal_fields=nil, @matchable_fields=nil, @range_fields=["created_at"]>
74
+
75
+ query_builder.build("created_at:<2015-04-16")
76
+ #=> {"filtered"=>{"filter"=>{"range"=>{"created_at"=>{"lt"=>"2015-04-16"}}}}}
77
+ ```
@@ -8,9 +8,11 @@ module Qiita
8
8
  # @param [Array<Qiita::Elasticsearch::Tokens>] tokens
9
9
  # @param [Array<String>, nil] hierarchal_fields
10
10
  # @param [Array<String>, nil] matchable_fields
11
- def initialize(tokens, hierarchal_fields: nil, matchable_fields: nil)
11
+ # @param [Array<String>, nil] range_fields
12
+ def initialize(tokens, hierarchal_fields: nil, matchable_fields: nil, range_fields: nil)
12
13
  @hierarchal_fields = hierarchal_fields
13
14
  @matchable_fields = matchable_fields
15
+ @range_fields = range_fields
14
16
  @tokens = tokens
15
17
  end
16
18
 
@@ -19,6 +21,7 @@ module Qiita
19
21
  TermNode.new(
20
22
  must_tokens.first,
21
23
  hierarchal_fields: @hierarchal_fields,
24
+ range_fields: @range_fields,
22
25
  ).to_hash
23
26
  else
24
27
  {
@@ -46,6 +49,7 @@ module Qiita
46
49
  TermNode.new(
47
50
  token,
48
51
  hierarchal_fields: @hierarchal_fields,
52
+ range_fields: @range_fields,
49
53
  )
50
54
  end.to_hash
51
55
  end
@@ -60,6 +64,7 @@ module Qiita
60
64
  TermNode.new(
61
65
  token,
62
66
  hierarchal_fields: @hierarchal_fields,
67
+ range_fields: @range_fields,
63
68
  ).to_hash
64
69
  end
65
70
  end
@@ -8,9 +8,11 @@ module Qiita
8
8
  # @param [Array<Qiita::Elasticsearch::Tokens>] tokens
9
9
  # @param [Array<String>, nil] hierarchal_fields
10
10
  # @param [Array<String>, nil] matchable_fields
11
- def initialize(tokens, hierarchal_fields: nil, matchable_fields: nil)
11
+ # @param [Array<String>, nil] range_fields
12
+ def initialize(tokens, hierarchal_fields: nil, matchable_fields: nil, range_fields: nil)
12
13
  @hierarchal_fields = hierarchal_fields
13
14
  @matchable_fields = matchable_fields
15
+ @range_fields = range_fields
14
16
  @tokens = tokens
15
17
  end
16
18
 
@@ -27,6 +29,7 @@ module Qiita
27
29
  filter_tokens,
28
30
  hierarchal_fields: @hierarchal_fields,
29
31
  matchable_fields: @matchable_fields,
32
+ range_fields: @range_fields,
30
33
  ).to_hash,
31
34
  "query" => QueryNode.new(
32
35
  not_filter_tokens,
@@ -8,9 +8,11 @@ module Qiita
8
8
  # @param [Array<Qiita::Elasticsearch::Tokens>] tokens
9
9
  # @param [Array<String>, nil] hierarchal_fields
10
10
  # @param [Array<String>, nil] matchable_fields
11
- def initialize(tokens, hierarchal_fields: nil, matchable_fields: nil)
11
+ # @param [Array<String>, nil] range_fields
12
+ def initialize(tokens, hierarchal_fields: nil, matchable_fields: nil, range_fields: nil)
12
13
  @hierarchal_fields = hierarchal_fields
13
14
  @matchable_fields = matchable_fields
15
+ @range_fields = range_fields
14
16
  @tokens = tokens
15
17
  end
16
18
 
@@ -23,6 +25,7 @@ module Qiita
23
25
  tokens_grouped_by_or_token.first,
24
26
  hierarchal_fields: @hierarchal_fields,
25
27
  matchable_fields: @matchable_fields,
28
+ range_fields: @range_fields,
26
29
  ).to_hash
27
30
  else
28
31
  {
@@ -32,6 +35,7 @@ module Qiita
32
35
  tokens,
33
36
  hierarchal_fields: @hierarchal_fields,
34
37
  matchable_fields: @matchable_fields,
38
+ range_fields: @range_fields,
35
39
  ).to_hash
36
40
  end,
37
41
  },
@@ -3,17 +3,21 @@ module Qiita
3
3
  module Nodes
4
4
  class TermNode
5
5
  DEFAULT_HIERARCHAL_FIELDS = []
6
+ DEFAULT_RANGE_FIELDS = []
6
7
 
7
8
  # @param [Qiita::Elasticsearch::Token] token
8
9
  # @param [Array<String>, nil] hierarchal_fields
9
- def initialize(token, hierarchal_fields: nil)
10
+ # @param [Array<String>, nil] range_fields
11
+ def initialize(token, hierarchal_fields: nil, range_fields: nil)
10
12
  @hierarchal_fields = hierarchal_fields
13
+ @range_fields = range_fields
11
14
  @token = token
12
15
  end
13
16
 
14
17
  # @return [Hash]
15
18
  def to_hash
16
- if has_hierarchal_token?
19
+ case
20
+ when has_hierarchal_token?
17
21
  {
18
22
  "bool" => {
19
23
  "should" => [
@@ -30,6 +34,14 @@ module Qiita
30
34
  ],
31
35
  },
32
36
  }
37
+ when has_range_token?
38
+ {
39
+ "range" => {
40
+ @token.field_name => {
41
+ @token.range_parameter => @token.range_query,
42
+ },
43
+ },
44
+ }
33
45
  else
34
46
  {
35
47
  "term" => {
@@ -48,6 +60,14 @@ module Qiita
48
60
  def hierarchal_fields
49
61
  @hierarchal_fields || DEFAULT_HIERARCHAL_FIELDS
50
62
  end
63
+
64
+ def has_range_token?
65
+ range_fields.include?(@token.field_name) && @token.range_parameter
66
+ end
67
+
68
+ def range_fields
69
+ @range_fields || DEFAULT_RANGE_FIELDS
70
+ end
51
71
  end
52
72
  end
53
73
  end
@@ -1,6 +1,6 @@
1
1
  require "qiita/elasticsearch/nodes/null_node"
2
2
  require "qiita/elasticsearch/nodes/or_separatable_node"
3
- require "qiita/elasticsearch/parser"
3
+ require "qiita/elasticsearch/tokenizer"
4
4
 
5
5
  module Qiita
6
6
  module Elasticsearch
@@ -8,16 +8,18 @@ module Qiita
8
8
  # @param [Array<String>, nil] filterable_fields
9
9
  # @param [Array<String>, nil] hierarchal_fields
10
10
  # @param [Array<String>, nil] matchable_fields
11
- def initialize(hierarchal_fields: nil, filterable_fields: nil, matchable_fields: nil)
11
+ # @param [Array<String>, nil] range_fields
12
+ def initialize(hierarchal_fields: nil, filterable_fields: nil, matchable_fields: nil, range_fields: nil)
12
13
  @hierarchal_fields = hierarchal_fields
13
14
  @filterable_fields = filterable_fields
14
15
  @matchable_fields = matchable_fields
16
+ @range_fields = range_fields
15
17
  end
16
18
 
17
19
  # @param [String] query_string Raw query string
18
20
  # @return [Hash]
19
21
  def build(query_string)
20
- tokens = parser.parse(query_string)
22
+ tokens = tokenizer.tokenize(query_string)
21
23
  if tokens.size.zero?
22
24
  Nodes::NullNode.new.to_hash
23
25
  else
@@ -25,14 +27,15 @@ module Qiita
25
27
  tokens,
26
28
  hierarchal_fields: @hierarchal_fields,
27
29
  matchable_fields: @matchable_fields,
30
+ range_fields: @range_fields,
28
31
  ).to_hash
29
32
  end
30
33
  end
31
34
 
32
35
  private
33
36
 
34
- def parser
35
- @parser ||= Parser.new(filterable_fields: @filterable_fields)
37
+ def tokenizer
38
+ @tokenizer ||= Tokenizer.new(filterable_fields: @filterable_fields)
36
39
  end
37
40
  end
38
41
  end
@@ -1,6 +1,8 @@
1
1
  module Qiita
2
2
  module Elasticsearch
3
3
  class Token
4
+ RANGE_TERM_REGEXP = /\A(?<operand>\<|\<=|\>|\>=)(?<query>.*)\z/
5
+
4
6
  attr_reader :field_name, :term
5
7
 
6
8
  def initialize(field_name: nil, minus: nil, quoted: nil, term: nil, token_string: nil)
@@ -55,6 +57,35 @@ module Qiita
55
57
  def quoted?
56
58
  !!@quoted
57
59
  end
60
+
61
+ # @return [String, nil]
62
+ # @example Suppose @term is "created_at:>=2015-04-16"
63
+ # range_parameter #=> "gte"
64
+ def range_parameter
65
+ range_match[:operand] ? operand_map[range_match[:operand]] : nil
66
+ end
67
+
68
+ # @return [String, nil]
69
+ # @example Suppose @term is "created_at:>=2015-04-16"
70
+ # range_query #=> "2015-04-16"
71
+ def range_query
72
+ range_match[:query]
73
+ end
74
+
75
+ private
76
+
77
+ def range_match
78
+ @range_match ||= RANGE_TERM_REGEXP.match(@term) || {}
79
+ end
80
+
81
+ def operand_map
82
+ {
83
+ ">" => "gt",
84
+ ">=" => "gte",
85
+ "<" => "lt",
86
+ "<=" => "lte",
87
+ }
88
+ end
58
89
  end
59
90
  end
60
91
  end
@@ -1,5 +1,5 @@
1
1
  module Qiita
2
2
  module Elasticsearch
3
- VERSION = "0.2.1"
3
+ VERSION = "0.2.2"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qiita-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryo Nakamura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-18 00:00:00.000000000 Z
11
+ date: 2015-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -105,7 +105,6 @@ files:
105
105
  - lib/qiita/elasticsearch/nodes/or_separatable_node.rb
106
106
  - lib/qiita/elasticsearch/nodes/query_node.rb
107
107
  - lib/qiita/elasticsearch/nodes/term_node.rb
108
- - lib/qiita/elasticsearch/parser.rb
109
108
  - lib/qiita/elasticsearch/query_builder.rb
110
109
  - lib/qiita/elasticsearch/token.rb
111
110
  - lib/qiita/elasticsearch/tokenizer.rb
@@ -131,9 +130,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
130
  version: '0'
132
131
  requirements: []
133
132
  rubyforge_project:
134
- rubygems_version: 2.4.5
133
+ rubygems_version: 2.2.2
135
134
  signing_key:
136
135
  specification_version: 4
137
136
  summary: Elasticsearch client helper for Qiita.
138
137
  test_files: []
139
- has_rdoc:
@@ -1,24 +0,0 @@
1
- require "qiita/elasticsearch/tokenizer"
2
-
3
- module Qiita
4
- module Elasticsearch
5
- class Parser
6
- # @param [Array<String>, nil] filterable_fields
7
- def initialize(filterable_fields: nil)
8
- @filterable_fields = filterable_fields
9
- end
10
-
11
- # @param [String] query_string Raw query string
12
- # @return [Array<Qiita::Elasticsearch::Token>]
13
- def parse(query_string)
14
- tokenizer.tokenize(query_string)
15
- end
16
-
17
- private
18
-
19
- def tokenizer
20
- @tokenizer ||= Tokenizer.new(filterable_fields: @filterable_fields)
21
- end
22
- end
23
- end
24
- end