qiita-elasticsearch 0.2.2 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aaa3120e317dceee23661a755b4a9eb2f38f2694
4
- data.tar.gz: db119b903847b6287106d7205a945aa6218c7816
3
+ metadata.gz: cc0094615455695aa7148b67052af7b154c5e31e
4
+ data.tar.gz: 64562e5f4139f14eb727062d7caf39cf706f92eb
5
5
  SHA512:
6
- metadata.gz: 5f3454a506c3c3fae11b682c23acd2a4d0b197cd8409f67b98078e6cead69c8e92a9949119d556675c6333439204a0dc25bae5c819cc843968267c593083de9e
7
- data.tar.gz: 54baba6c1bd52bba643b8961c5038ce86f8d3de46afd6682f706b0a139995c16dc0685667e9af16f0bfb9bdcfbd7fb12643ed90fba344367ccde0b639672b8ad
6
+ metadata.gz: 183fabc234d8480455a5804eb80a8ccca40cc0b0e39fc5f6ee2f75800958875170203063f76303c88ea68e45388f347aa000f14c13d204eb6f2f8317c213b5d7
7
+ data.tar.gz: 857a39fb54f660ed9a3edf6c74b45212589ba558586bd0966f2b388454099ce5aad322a7b77949d1a4129b10ae6e755eacf377b8c2eecf3e6a0f43a042637ba6
@@ -11,11 +11,14 @@ Metrics/CyclomaticComplexity:
11
11
  Enabled: false
12
12
 
13
13
  Metrics/LineLength:
14
- Max: 120
14
+ Enabled: false
15
15
 
16
16
  Metrics/MethodLength:
17
17
  Enabled: false
18
18
 
19
+ Metrics/ParameterLists:
20
+ Enabled: false
21
+
19
22
  Metrics/PerceivedComplexity:
20
23
  Enabled: false
21
24
 
@@ -1,3 +1,6 @@
1
+ ## 0.3.0
2
+ - Add downcased_fields options and update case rule
3
+
1
4
  ## 0.2.2
2
5
  - Support range fields
3
6
 
data/README.md CHANGED
@@ -6,7 +6,6 @@ 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, @hierarchal_fields=nil, @matchable_fields=nil>
10
9
 
11
10
  query_builder.build("a")
12
11
  #=> {"match"=>{"_all"=>"a"}}
@@ -29,7 +28,6 @@ Pass `:matchable_fields` option to tell matchable field names (default: `_all`).
29
28
 
30
29
  ```rb
31
30
  query_builder = Qiita::Elasticsearch::QueryBuilder.new(matchable_fields: ["body", "title"])
32
- #=> #<Qiita::Elasticsearch::QueryBuilder:0x007ff81fa59168 @filterable_fields=nil, @hierarchal_fields=nil, @matchable_fields=["body", "title"], @range_fields=nil>
33
31
 
34
32
  query_builder.build("a")
35
33
  #=> {"multi_match"=>{"fields"=>["body", "title"], "query"=>"a"}}
@@ -40,7 +38,6 @@ Pass `:filterable_fields` option to enable filtered queries like `tag:Ruby`.
40
38
 
41
39
  ```rb
42
40
  query_builder = Qiita::Elasticsearch::QueryBuilder.new(filterable_fields: ["tag", "title"])
43
- #=> #<Qiita::Elasticsearch::QueryBuilder:0x007ff81e2de1f0 @filterable_fields=["tag", "title"], @hierarchal_fields=nil, @matchable_fields=nil, @range_fields=nil>
44
41
 
45
42
  query_builder.build("tag:a")
46
43
  #=> {"filtered"=>{"filter"=>{"term"=>{"tag"=>"a"}}}}
@@ -53,25 +50,34 @@ query_builder.build("user:a b")
53
50
  ```
54
51
 
55
52
  ### hierarchal_fields
56
- Pass `:hierarchal_fields` options with `:filterable_fields` to enable prefixed filtered queries.
53
+ Pass `:hierarchal_fields` option with `:filterable_fields` to enable prefixed filtered queries.
57
54
  With this option, `tag:foo` will hit documents tagged with `foo`, or `foo/...`.
58
55
 
59
56
  ```rb
60
57
  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, @range_fields=nil>
62
58
 
63
59
  query_builder.build("tag:ruby")
64
60
  #=> {"filtered"=>{"filter"=>{"bool"=>{"should"=>[{"prefix"=>{"tag"=>"ruby/"}}, {"term"=>{"tag"=>"ruby"}}]}}}}
65
61
  ```
66
62
 
67
63
  ### range_fields
68
- Pass `:range_fields` options with `:filterable_fields` to enable range filtered queries.
64
+ Pass `:range_fields` option with `:filterable_fields` to enable range filtered queries.
69
65
  With this option, `created_at:<2015-04-16` will hit documents created before 2015-04-16.
70
66
 
71
67
  ```rb
72
68
  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
69
 
75
70
  query_builder.build("created_at:<2015-04-16")
76
71
  #=> {"filtered"=>{"filter"=>{"range"=>{"created_at"=>{"lt"=>"2015-04-16"}}}}}
77
72
  ```
73
+
74
+ ### downcased_fields
75
+ Pass `:downcased_fields` option with `:filterable_fields` to downcase any terms in the fields.
76
+ This option is useful when some fields are stored within downcased format on Elasticsearch.
77
+
78
+ ```rb
79
+ query_builder = Qiita::Elasticsearch::QueryBuilder.new(downcased_fields: ["tag"], filterable_fields: ["tag"])
80
+
81
+ query_builder.build("tag:Ruby")
82
+ #=> {"filtered"=>{"filter"=>{"term"=>{"tag"=>"ruby"}}}}
83
+ ```
@@ -0,0 +1,16 @@
1
+ require "qiita/elasticsearch/token"
2
+
3
+ module Qiita
4
+ module Elasticsearch
5
+ class FilterableToken < Token
6
+ # @return [Hash]
7
+ def to_hash
8
+ {
9
+ "term" => {
10
+ @field_name => proper_cased_term,
11
+ },
12
+ }
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ require "qiita/elasticsearch/token"
2
+
3
+ module Qiita
4
+ module Elasticsearch
5
+ class HierarchalToken < Token
6
+ # @return [Hash]
7
+ def to_hash
8
+ {
9
+ "bool" => {
10
+ "should" => [
11
+ {
12
+ "prefix" => {
13
+ @field_name => proper_cased_term + "/",
14
+ },
15
+ },
16
+ {
17
+ "term" => {
18
+ @field_name => proper_cased_term,
19
+ },
20
+ },
21
+ ],
22
+ },
23
+ }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,29 @@
1
+ require "qiita/elasticsearch/token"
2
+
3
+ module Qiita
4
+ module Elasticsearch
5
+ class MatchableToken < Token
6
+ attr_writer :matchable_fields
7
+
8
+ # @return [Hash]
9
+ def to_hash
10
+ if @matchable_fields.nil?
11
+ {
12
+ quoted? ? "match_phrase" : "match" => {
13
+ "_all" => @term,
14
+ }
15
+ }
16
+ else
17
+ hash = {
18
+ "multi_match" => {
19
+ "fields" => @matchable_fields,
20
+ "query" => @term,
21
+ },
22
+ }
23
+ hash["multi_match"]["type"] = "phrase" if quoted?
24
+ hash
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -6,23 +6,13 @@ module Qiita
6
6
  module Nodes
7
7
  class FilterNode
8
8
  # @param [Array<Qiita::Elasticsearch::Tokens>] tokens
9
- # @param [Array<String>, nil] hierarchal_fields
10
- # @param [Array<String>, nil] matchable_fields
11
- # @param [Array<String>, nil] range_fields
12
- def initialize(tokens, hierarchal_fields: nil, matchable_fields: nil, range_fields: nil)
13
- @hierarchal_fields = hierarchal_fields
14
- @matchable_fields = matchable_fields
15
- @range_fields = range_fields
9
+ def initialize(tokens)
16
10
  @tokens = tokens
17
11
  end
18
12
 
19
13
  def to_hash
20
14
  if must_not_tokens.empty? && must_tokens.length == 1
21
- TermNode.new(
22
- must_tokens.first,
23
- hierarchal_fields: @hierarchal_fields,
24
- range_fields: @range_fields,
25
- ).to_hash
15
+ TermNode.new(must_tokens.first).to_hash
26
16
  else
27
17
  {
28
18
  "bool" => {
@@ -41,17 +31,10 @@ module Qiita
41
31
  def must_not_queries
42
32
  must_not_tokens.map do |token|
43
33
  if token.field_name.nil?
44
- MatchNode.new(
45
- token,
46
- matchable_fields: @matchable_fields,
47
- )
34
+ MatchNode.new(token).to_hash
48
35
  else
49
- TermNode.new(
50
- token,
51
- hierarchal_fields: @hierarchal_fields,
52
- range_fields: @range_fields,
53
- )
54
- end.to_hash
36
+ TermNode.new(token).to_hash
37
+ end
55
38
  end
56
39
  end
57
40
 
@@ -61,11 +44,7 @@ module Qiita
61
44
 
62
45
  def must_queries
63
46
  must_tokens.map do |token|
64
- TermNode.new(
65
- token,
66
- hierarchal_fields: @hierarchal_fields,
67
- range_fields: @range_fields,
68
- ).to_hash
47
+ TermNode.new(token).to_hash
69
48
  end
70
49
  end
71
50
 
@@ -6,35 +6,18 @@ module Qiita
6
6
  module Nodes
7
7
  class FilterableNode
8
8
  # @param [Array<Qiita::Elasticsearch::Tokens>] tokens
9
- # @param [Array<String>, nil] hierarchal_fields
10
- # @param [Array<String>, nil] matchable_fields
11
- # @param [Array<String>, nil] range_fields
12
- def initialize(tokens, hierarchal_fields: nil, matchable_fields: nil, range_fields: nil)
13
- @hierarchal_fields = hierarchal_fields
14
- @matchable_fields = matchable_fields
15
- @range_fields = range_fields
9
+ def initialize(tokens)
16
10
  @tokens = tokens
17
11
  end
18
12
 
19
13
  def to_hash
20
14
  if filter_tokens.empty?
21
- QueryNode.new(
22
- not_filter_tokens,
23
- matchable_fields: @matchable_fields,
24
- ).to_hash
15
+ QueryNode.new(not_filter_tokens).to_hash
25
16
  else
26
17
  {
27
18
  "filtered" => {
28
- "filter" => FilterNode.new(
29
- filter_tokens,
30
- hierarchal_fields: @hierarchal_fields,
31
- matchable_fields: @matchable_fields,
32
- range_fields: @range_fields,
33
- ).to_hash,
34
- "query" => QueryNode.new(
35
- not_filter_tokens,
36
- matchable_fields: @matchable_fields,
37
- ).to_hash,
19
+ "filter" => FilterNode.new(filter_tokens).to_hash,
20
+ "query" => QueryNode.new(not_filter_tokens).to_hash,
38
21
  }.reject do |key, value|
39
22
  value.empty?
40
23
  end,
@@ -3,29 +3,13 @@ module Qiita
3
3
  module Nodes
4
4
  class MatchNode
5
5
  # @param [Qiita::Elasticsearch::Token] token
6
- # @param [Array<String>, nil] matchable_fields
7
- def initialize(token, matchable_fields: nil)
8
- @matchable_fields = matchable_fields
6
+ def initialize(token)
9
7
  @token = token
10
8
  end
11
9
 
10
+ # @return [Hash]
12
11
  def to_hash
13
- if @matchable_fields.nil?
14
- {
15
- @token.quoted? ? "match_phrase" : "match" => {
16
- "_all" => @token.term,
17
- }
18
- }
19
- else
20
- hash = {
21
- "multi_match" => {
22
- "fields" => @matchable_fields,
23
- "query" => @token.term,
24
- },
25
- }
26
- hash["multi_match"]["type"] = "phrase" if @token.quoted?
27
- hash
28
- end
12
+ @token.to_hash
29
13
  end
30
14
  end
31
15
  end
@@ -5,9 +5,7 @@ module Qiita
5
5
  module Nodes
6
6
  class MultiShouldNode
7
7
  # @param [Array<Qiita::Elasticsearch::Tokens>] tokens
8
- # @param [Array<String>, nil] matchable_fields
9
- def initialize(tokens, matchable_fields: nil)
10
- @matchable_fields = matchable_fields
8
+ def initialize(tokens)
11
9
  @tokens = tokens
12
10
  end
13
11
 
@@ -24,10 +22,7 @@ module Qiita
24
22
  # @return [Array<Hash>] Queries to be used as a value of `should` property of bool query.
25
23
  def should_queries
26
24
  @tokens.map do |token|
27
- MatchNode.new(
28
- token,
29
- matchable_fields: @matchable_fields,
30
- ).to_hash
25
+ MatchNode.new(token).to_hash
31
26
  end
32
27
  end
33
28
  end
@@ -6,13 +6,7 @@ module Qiita
6
6
  module Nodes
7
7
  class OrSeparatableNode
8
8
  # @param [Array<Qiita::Elasticsearch::Tokens>] tokens
9
- # @param [Array<String>, nil] hierarchal_fields
10
- # @param [Array<String>, nil] matchable_fields
11
- # @param [Array<String>, nil] range_fields
12
- def initialize(tokens, hierarchal_fields: nil, matchable_fields: nil, range_fields: nil)
13
- @hierarchal_fields = hierarchal_fields
14
- @matchable_fields = matchable_fields
15
- @range_fields = range_fields
9
+ def initialize(tokens)
16
10
  @tokens = tokens
17
11
  end
18
12
 
@@ -21,22 +15,12 @@ module Qiita
21
15
  when 0
22
16
  Nodes::NullNode.new.to_hash
23
17
  when 1
24
- Nodes::FilterableNode.new(
25
- tokens_grouped_by_or_token.first,
26
- hierarchal_fields: @hierarchal_fields,
27
- matchable_fields: @matchable_fields,
28
- range_fields: @range_fields,
29
- ).to_hash
18
+ Nodes::FilterableNode.new(tokens_grouped_by_or_token.first).to_hash
30
19
  else
31
20
  {
32
21
  "bool" => {
33
22
  "should" => tokens_grouped_by_or_token.map do |tokens|
34
- Nodes::FilterableNode.new(
35
- tokens,
36
- hierarchal_fields: @hierarchal_fields,
37
- matchable_fields: @matchable_fields,
38
- range_fields: @range_fields,
39
- ).to_hash
23
+ Nodes::FilterableNode.new(tokens).to_hash
40
24
  end,
41
25
  },
42
26
  }
@@ -6,10 +6,7 @@ module Qiita
6
6
  module Nodes
7
7
  class QueryNode
8
8
  # @param [Array<Qiita::Elasticsearch::Tokens>] tokens
9
- # @param [Array<String>, nil] matchable_fields
10
- def initialize(tokens, hierarchal_fields: nil, matchable_fields: nil)
11
- @hierarchal_fields = hierarchal_fields
12
- @matchable_fields = matchable_fields
9
+ def initialize(tokens)
13
10
  @tokens = tokens
14
11
  end
15
12
 
@@ -18,15 +15,9 @@ module Qiita
18
15
  when 0
19
16
  {}
20
17
  when 1
21
- MatchNode.new(
22
- @tokens.first,
23
- matchable_fields: @matchable_fields,
24
- ).to_hash
18
+ MatchNode.new(@tokens.first).to_hash
25
19
  else
26
- MultiShouldNode.new(
27
- @tokens,
28
- matchable_fields: @matchable_fields,
29
- ).to_hash
20
+ MultiShouldNode.new(@tokens).to_hash
30
21
  end
31
22
  end
32
23
  end
@@ -2,71 +2,14 @@ module Qiita
2
2
  module Elasticsearch
3
3
  module Nodes
4
4
  class TermNode
5
- DEFAULT_HIERARCHAL_FIELDS = []
6
- DEFAULT_RANGE_FIELDS = []
7
-
8
5
  # @param [Qiita::Elasticsearch::Token] token
9
- # @param [Array<String>, nil] hierarchal_fields
10
- # @param [Array<String>, nil] range_fields
11
- def initialize(token, hierarchal_fields: nil, range_fields: nil)
12
- @hierarchal_fields = hierarchal_fields
13
- @range_fields = range_fields
6
+ def initialize(token)
14
7
  @token = token
15
8
  end
16
9
 
17
10
  # @return [Hash]
18
11
  def to_hash
19
- case
20
- when has_hierarchal_token?
21
- {
22
- "bool" => {
23
- "should" => [
24
- {
25
- "prefix" => {
26
- @token.field_name => @token.downcased_term + "/",
27
- },
28
- },
29
- {
30
- "term" => {
31
- @token.field_name => @token.downcased_term,
32
- },
33
- },
34
- ],
35
- },
36
- }
37
- when has_range_token?
38
- {
39
- "range" => {
40
- @token.field_name => {
41
- @token.range_parameter => @token.range_query,
42
- },
43
- },
44
- }
45
- else
46
- {
47
- "term" => {
48
- @token.field_name => @token.downcased_term,
49
- },
50
- }
51
- end
52
- end
53
-
54
- private
55
-
56
- def has_hierarchal_token?
57
- hierarchal_fields.include?(@token.field_name)
58
- end
59
-
60
- def hierarchal_fields
61
- @hierarchal_fields || DEFAULT_HIERARCHAL_FIELDS
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
12
+ @token.to_hash
70
13
  end
71
14
  end
72
15
  end
@@ -5,11 +5,13 @@ require "qiita/elasticsearch/tokenizer"
5
5
  module Qiita
6
6
  module Elasticsearch
7
7
  class QueryBuilder
8
+ # @param [Array<String>, nil] downcased_fields
8
9
  # @param [Array<String>, nil] filterable_fields
9
10
  # @param [Array<String>, nil] hierarchal_fields
10
11
  # @param [Array<String>, nil] matchable_fields
11
12
  # @param [Array<String>, nil] range_fields
12
- def initialize(hierarchal_fields: nil, filterable_fields: nil, matchable_fields: nil, range_fields: nil)
13
+ def initialize(downcased_fields: nil, hierarchal_fields: nil, filterable_fields: nil, matchable_fields: nil, range_fields: nil)
14
+ @downcased_fields = downcased_fields
13
15
  @hierarchal_fields = hierarchal_fields
14
16
  @filterable_fields = filterable_fields
15
17
  @matchable_fields = matchable_fields
@@ -23,19 +25,20 @@ module Qiita
23
25
  if tokens.size.zero?
24
26
  Nodes::NullNode.new.to_hash
25
27
  else
26
- Nodes::OrSeparatableNode.new(
27
- tokens,
28
- hierarchal_fields: @hierarchal_fields,
29
- matchable_fields: @matchable_fields,
30
- range_fields: @range_fields,
31
- ).to_hash
28
+ Nodes::OrSeparatableNode.new(tokens).to_hash
32
29
  end
33
30
  end
34
31
 
35
32
  private
36
33
 
37
34
  def tokenizer
38
- @tokenizer ||= Tokenizer.new(filterable_fields: @filterable_fields)
35
+ @tokenizer ||= Tokenizer.new(
36
+ downcased_fields: @downcased_fields,
37
+ hierarchal_fields: @hierarchal_fields,
38
+ filterable_fields: @filterable_fields,
39
+ matchable_fields: @matchable_fields,
40
+ range_fields: @range_fields,
41
+ )
39
42
  end
40
43
  end
41
44
  end
@@ -0,0 +1,57 @@
1
+ require "qiita/elasticsearch/token"
2
+
3
+ module Qiita
4
+ module Elasticsearch
5
+ class RangeToken < Token
6
+ RANGE_TERM_REGEXP = /\A(?<operand>\<|\<=|\>|\>=)(?<query>.*)\z/
7
+
8
+ # @return [Hash]
9
+ def to_hash
10
+ if range_parameter
11
+ {
12
+ "range" => {
13
+ @field_name => {
14
+ range_parameter => range_query,
15
+ },
16
+ },
17
+ }
18
+ else
19
+ {
20
+ "term" => {
21
+ @field_name => proper_cased_term,
22
+ },
23
+ }
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ # @return [String, nil]
30
+ # @example Suppose @term is "created_at:>=2015-04-16"
31
+ # range_parameter #=> "gte"
32
+ def range_parameter
33
+ range_match[:operand] ? operand_map[range_match[:operand]] : nil
34
+ end
35
+
36
+ # @return [String, nil]
37
+ # @example Suppose @term is "created_at:>=2015-04-16"
38
+ # range_query #=> "2015-04-16"
39
+ def range_query
40
+ range_match[:query]
41
+ end
42
+
43
+ def range_match
44
+ @range_match ||= RANGE_TERM_REGEXP.match(@term) || {}
45
+ end
46
+
47
+ def operand_map
48
+ {
49
+ ">" => "gt",
50
+ ">=" => "gte",
51
+ "<" => "lt",
52
+ "<=" => "lte",
53
+ }
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,11 +1,11 @@
1
1
  module Qiita
2
2
  module Elasticsearch
3
3
  class Token
4
- RANGE_TERM_REGEXP = /\A(?<operand>\<|\<=|\>|\>=)(?<query>.*)\z/
5
-
6
4
  attr_reader :field_name, :term
7
5
 
8
- def initialize(field_name: nil, minus: nil, quoted: nil, term: nil, token_string: nil)
6
+ # @param [true, false] downcased
7
+ def initialize(downcased: nil, field_name: nil, minus: nil, quoted: nil, term: nil, token_string: nil)
8
+ @downcased = downcased
9
9
  @field_name = field_name
10
10
  @minus = minus
11
11
  @quoted = quoted
@@ -13,10 +13,19 @@ module Qiita
13
13
  @token_string = token_string
14
14
  end
15
15
 
16
+ # @return [true, false] True if its term must be treated with downcased
17
+ def downcased?
18
+ !!@downcased
19
+ end
20
+
16
21
  def downcased_term
17
22
  @downcased_term ||= term.downcase
18
23
  end
19
24
 
25
+ def to_hash
26
+ fail NotImplementedError
27
+ end
28
+
20
29
  def filter?
21
30
  !field_name.nil? || negative?
22
31
  end
@@ -50,6 +59,15 @@ module Qiita
50
59
  @minus.nil?
51
60
  end
52
61
 
62
+ # @return [String] Downcased or not-downcased term
63
+ def proper_cased_term
64
+ if downcased?
65
+ downcased_term
66
+ else
67
+ term
68
+ end
69
+ end
70
+
53
71
  # @return [true, false] True if this token is for phrase matching
54
72
  # @note `Express OR "Ruby on Rails"`
55
73
  # ^^^^^^^^^^^^^^^
@@ -57,35 +75,6 @@ module Qiita
57
75
  def quoted?
58
76
  !!@quoted
59
77
  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
89
78
  end
90
79
  end
91
80
  end
@@ -1,9 +1,15 @@
1
- require "qiita/elasticsearch/token"
1
+ require "qiita/elasticsearch/filterable_token"
2
+ require "qiita/elasticsearch/hierarchal_token"
3
+ require "qiita/elasticsearch/matchable_token"
4
+ require "qiita/elasticsearch/range_token"
2
5
 
3
6
  module Qiita
4
7
  module Elasticsearch
5
8
  class Tokenizer
9
+ DEFAULT_DOWNCASED_FIELDS = []
6
10
  DEFAULT_FILTERABLE_FIELDS = []
11
+ DEFAULT_HIERARCHAL_FIELDS = []
12
+ DEFAULT_RANGE_FIELDS = []
7
13
 
8
14
  TOKEN_PATTERN = /
9
15
  (?<token_string>
@@ -17,9 +23,17 @@ module Qiita
17
23
  )
18
24
  /x
19
25
 
26
+ # @param [Array<String>, nil] downcased_fields
20
27
  # @param [Array<String>, nil] filterable_fields
21
- def initialize(filterable_fields: nil)
28
+ # @param [Array<String>, nil] hierarchal_fields
29
+ # @param [Array<String>, nil] matchable_fields
30
+ # @param [Array<String>, nil] range_fields
31
+ def initialize(downcased_fields: nil, filterable_fields: nil, hierarchal_fields: nil, matchable_fields: nil, range_fields: nil)
32
+ @downcased_fields = downcased_fields
22
33
  @filterable_fields = filterable_fields
34
+ @hierarchal_fields = hierarchal_fields
35
+ @matchable_fields = matchable_fields
36
+ @range_fields = range_fields
23
37
  end
24
38
 
25
39
  # @param [String] query_string Raw query string
@@ -31,21 +45,49 @@ module Qiita
31
45
  term = "#{field_name}:#{term}"
32
46
  field_name = nil
33
47
  end
34
- Token.new(
48
+ token = token_class(field_name).new(
49
+ downcased: downcased_fields.include?(field_name),
35
50
  field_name: field_name,
36
51
  minus: minus,
37
52
  quoted: !quoted_term.nil?,
38
53
  term: term,
39
54
  token_string: token_string,
40
55
  )
56
+ token.matchable_fields = @matchable_fields if token.is_a?(MatchableToken)
57
+ token
41
58
  end
42
59
  end
43
60
 
44
61
  private
45
62
 
63
+ def downcased_fields
64
+ @downcased_fields || DEFAULT_DOWNCASED_FIELDS
65
+ end
66
+
46
67
  def filterable_fields
47
68
  @filterable_fields || DEFAULT_FILTERABLE_FIELDS
48
69
  end
70
+
71
+ def hierarchal_fields
72
+ @hierarchal_fields || DEFAULT_HIERARCHAL_FIELDS
73
+ end
74
+
75
+ def range_fields
76
+ @range_fields || DEFAULT_RANGE_FIELDS
77
+ end
78
+
79
+ def token_class(field_name)
80
+ case
81
+ when range_fields.include?(field_name)
82
+ RangeToken
83
+ when hierarchal_fields.include?(field_name)
84
+ HierarchalToken
85
+ when filterable_fields.include?(field_name)
86
+ FilterableToken
87
+ else
88
+ MatchableToken
89
+ end
90
+ end
49
91
  end
50
92
  end
51
93
  end
@@ -1,5 +1,5 @@
1
1
  module Qiita
2
2
  module Elasticsearch
3
- VERSION = "0.2.2"
3
+ VERSION = "0.3.0"
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.2
4
+ version: 0.3.0
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-04-16 00:00:00.000000000 Z
11
+ date: 2015-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -97,6 +97,9 @@ files:
97
97
  - README.md
98
98
  - Rakefile
99
99
  - lib/qiita/elasticsearch.rb
100
+ - lib/qiita/elasticsearch/filterable_token.rb
101
+ - lib/qiita/elasticsearch/hierarchal_token.rb
102
+ - lib/qiita/elasticsearch/matchable_token.rb
100
103
  - lib/qiita/elasticsearch/nodes/filter_node.rb
101
104
  - lib/qiita/elasticsearch/nodes/filterable_node.rb
102
105
  - lib/qiita/elasticsearch/nodes/match_node.rb
@@ -106,6 +109,7 @@ files:
106
109
  - lib/qiita/elasticsearch/nodes/query_node.rb
107
110
  - lib/qiita/elasticsearch/nodes/term_node.rb
108
111
  - lib/qiita/elasticsearch/query_builder.rb
112
+ - lib/qiita/elasticsearch/range_token.rb
109
113
  - lib/qiita/elasticsearch/token.rb
110
114
  - lib/qiita/elasticsearch/tokenizer.rb
111
115
  - lib/qiita/elasticsearch/version.rb
@@ -130,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
134
  version: '0'
131
135
  requirements: []
132
136
  rubyforge_project:
133
- rubygems_version: 2.2.2
137
+ rubygems_version: 2.4.5
134
138
  signing_key:
135
139
  specification_version: 4
136
140
  summary: Elasticsearch client helper for Qiita.