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 +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +18 -6
- data/lib/qiita/elasticsearch/nodes/filter_node.rb +6 -1
- data/lib/qiita/elasticsearch/nodes/filterable_node.rb +4 -1
- data/lib/qiita/elasticsearch/nodes/or_separatable_node.rb +5 -1
- data/lib/qiita/elasticsearch/nodes/term_node.rb +22 -2
- data/lib/qiita/elasticsearch/query_builder.rb +8 -5
- data/lib/qiita/elasticsearch/token.rb +31 -0
- data/lib/qiita/elasticsearch/version.rb +1 -1
- metadata +3 -5
- data/lib/qiita/elasticsearch/parser.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aaa3120e317dceee23661a755b4a9eb2f38f2694
|
4
|
+
data.tar.gz: db119b903847b6287106d7205a945aa6218c7816
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f3454a506c3c3fae11b682c23acd2a4d0b197cd8409f67b98078e6cead69c8e92a9949119d556675c6333439204a0dc25bae5c819cc843968267c593083de9e
|
7
|
+
data.tar.gz: 54baba6c1bd52bba643b8961c5038ce86f8d3de46afd6682f706b0a139995c16dc0685667e9af16f0bfb9bdcfbd7fb12643ed90fba344367ccde0b639672b8ad
|
data/CHANGELOG.md
CHANGED
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"}}], "
|
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
|
-
#=> {"
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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/
|
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
|
-
|
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 =
|
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
|
35
|
-
@
|
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
|
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.
|
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-
|
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.
|
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
|