grn_mini 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8b9f025b3d3dfc38fd85b82b8552b9df10244dd8
4
- data.tar.gz: 2294e3e7af33ffd32d15253d01572bbeff84bbb3
3
+ metadata.gz: 954b7ebeb13d40913ed6022a6b96d972193b73ea
4
+ data.tar.gz: c64cf4de87e4cf59b172fb1b4d5c64d7f8f17e12
5
5
  SHA512:
6
- metadata.gz: 44faf36a48ca1245ddd3621955b998295a7e608e1f6ddb98229374391374cb18919c4883c0a3c0517fa4cee9eb9034a213e3a87ba271f3f4c2611f3454015c9b
7
- data.tar.gz: 68bd08647aa71e471072aec681a547821f06c111fcac909309545986f0898b9046d365fee677bc4334047772f844a286a673a39b738ff0317a2e8001160a619b
6
+ metadata.gz: 0406c079b5f1fac34c4f35de6e0ca59b1236df413b285ec28d529c054e1e08f1558f03712b24c37d2dba53f843e219db3ecc37e3d3ea33143faf4121c50b6fb1
7
+ data.tar.gz: 747fe7c71d88f786229ad7461639b9ff4de8cee0bc73e27aff73ce3301c98659311173517434b98b857b91bbbace9aabb084ee3900c968fd828bad8531d43af3
data/README.md CHANGED
@@ -52,6 +52,25 @@ end
52
52
  # Delete temporary database
53
53
  ```
54
54
 
55
+ ## Create Hash
56
+
57
+ ```ruby
58
+ require 'grn_mini'
59
+
60
+ hash = GrnMini::Hash.new("test.db")
61
+
62
+ # Add
63
+ hash["a"] = {text:"aaa", number:1}
64
+ hash["b"] = {text:"bbb", number:2}
65
+ hash["c"] = {text:"ccc", number:3}
66
+
67
+ # Read
68
+ hash["b"].text #=> "bbb"
69
+
70
+ # Write
71
+ hash["b"].text = "BBB"
72
+ ```
73
+
55
74
  ## Data Type
56
75
 
57
76
  ```ruby
data/lib/grn_mini.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "grn_mini/version"
2
2
  require "grn_mini/array"
3
+ require "grn_mini/hash"
3
4
  require "grn_mini/util"
4
5
 
5
6
  module GrnMini
@@ -0,0 +1,95 @@
1
+ require 'grn_mini/util'
2
+ require 'groonga'
3
+ require 'tmpdir'
4
+
5
+ module GrnMini
6
+ class Hash
7
+ attr_accessor :grn
8
+ include Enumerable
9
+
10
+ def self.tmpdb
11
+ Dir.mktmpdir do |dir|
12
+ # p dir
13
+ yield self.new(File.join(dir, "tmp.db"))
14
+ end
15
+ end
16
+
17
+ def initialize(path)
18
+ unless File.exist?(path)
19
+ Groonga::Database.create(path: path)
20
+ else
21
+ Groonga::Database.open(path)
22
+ end
23
+
24
+ @grn = Groonga["Hash"] || Groonga::Hash.create(name: "Hash", persistent: true)
25
+ @terms = Groonga["Terms"] || Groonga::PatriciaTrie.create(name: "Terms", key_normalize: true, default_tokenizer: "TokenBigramSplitSymbolAlphaDigit")
26
+ end
27
+
28
+ def add(key, values)
29
+ if @grn.empty?
30
+ values.each do |key, value|
31
+ column = key.to_s
32
+
33
+ # @todo Need define_index_column ?
34
+ if value.is_a?(Time)
35
+ @grn.define_column(column, "Time")
36
+ elsif value.is_a?(Float)
37
+ @grn.define_column(column, "Float")
38
+ elsif value.is_a?(Numeric)
39
+ @grn.define_column(column, "Int32")
40
+ else
41
+ @grn.define_column(column, "ShortText")
42
+ @terms.define_index_column("array_#{column}", @grn, source: "Hash.#{column}", with_position: true)
43
+ end
44
+ end
45
+ end
46
+
47
+ @grn.add(key, values)
48
+ end
49
+
50
+ def [](key)
51
+ @grn[key]
52
+ end
53
+
54
+ def []=(key, value)
55
+ add(key, value)
56
+ end
57
+
58
+ def select(query, options = {default_column: "text"})
59
+ @grn.select(query, options)
60
+ end
61
+
62
+ def size
63
+ @grn.size
64
+ end
65
+
66
+ alias length size
67
+
68
+ def empty?
69
+ size == 0
70
+ end
71
+
72
+ def each
73
+ @grn.each do |record|
74
+ yield record
75
+ end
76
+ end
77
+
78
+ def delete(id = nil, &block)
79
+ if block_given?
80
+ @grn.delete(&block)
81
+ else
82
+ raise IdIsGreaterThanZero if id == 0
83
+ @grn.delete(id)
84
+ end
85
+ end
86
+
87
+ def sort(keys, options = {})
88
+ @grn.sort(keys, options)
89
+ end
90
+
91
+ def group(key, options = {})
92
+ @grn.group(key, options)
93
+ end
94
+ end
95
+ end
@@ -1,3 +1,3 @@
1
1
  module GrnMini
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -15,7 +15,7 @@ module Input
15
15
 
16
16
  if File.file? filename
17
17
  next if ignore_file?(filename)
18
- array << {filename: filename, text: read_file(filename), timestamp: File.stat(filename).mtime, suffix: File.extname(filename).sub('.', ""), index: index } # index is dirty
18
+ array << {filename: filename, text: read_file(filename), timestamp: File.stat(filename).mtime, suffix: File.extname(filename).sub('.', "")}
19
19
  index += 1
20
20
  end
21
21
  end
@@ -61,7 +61,7 @@ class Search
61
61
  elements = []
62
62
 
63
63
  page_entries.each do |record|
64
- element = "<hr>\n<a href=\"/#{record.index}\">#{record.filename}</a>\n"
64
+ element = "<hr>\n<a href=\"/#{record.value.key.id}\">#{record.filename}</a>\n"
65
65
 
66
66
  snippet.execute(record.text).each do |segment|
67
67
  element += "<pre style=\"border:1px solid #bbb;\">#{segment}</pre>\n"
@@ -41,6 +41,7 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
41
41
  results = array.select("bb number:<10")
42
42
 
43
43
  assert_equal 1, results.size
44
+ assert_equal 2, results.first.key.id
44
45
  assert_equal "bbb", results.first.text
45
46
  assert_equal 2, results.first.number
46
47
  end
@@ -325,8 +326,8 @@ EOF
325
326
  record = results.first
326
327
  segments = snippet.execute(record.text)
327
328
  assert_equal 2, segments.size
328
- assert_match /\[1\] <<This>> is a <<pen>> pep pea pek pet./, segments[0]
329
- assert_match /\[2\] <<This>> is a <<pen>> pep pea pek pet./, segments[1]
329
+ assert_match /\[1\]<< This>> is a<< pen>> pep pea pek pet./, segments[0]
330
+ assert_match /\[2\]<< This>> is a<< pen>> pep pea pek pet./, segments[1]
330
331
  end
331
332
  end
332
333
 
@@ -344,7 +345,7 @@ EOF
344
345
  record = results.first
345
346
  segments = snippet.execute(record.text)
346
347
  assert_equal 1, segments.size
347
- assert_equal "&lt;html&gt;\n &lt;div&gt;<strong>This</strong> is a <strong>pen</strong> pep pea pek pet.&lt;/div&gt;\n&lt;/html&gt;\n", segments.first
348
+ assert_equal "&lt;html&gt;\n &lt;div&gt;<strong>This</strong> is a<strong> pen</strong> pep pea pek pet.&lt;/div&gt;\n&lt;/html&gt;\n", segments.first
348
349
  end
349
350
  end
350
351
 
@@ -0,0 +1,260 @@
1
+ require 'minitest_helper'
2
+
3
+ class TestGrnMiniHash < MiniTest::Unit::TestCase
4
+ def test_initialize
5
+ Dir.mktmpdir do |dir|
6
+ hash = GrnMini::Hash.new(File.join(dir, "test.db"))
7
+ end
8
+ end
9
+
10
+ def test_add
11
+ GrnMini::Hash.tmpdb do |hash|
12
+ hash.add("aaa", text:"aaa", number:1)
13
+ assert_equal 1, hash.size
14
+
15
+ # alias []=
16
+ hash["bbb"] = {text:"bbb", number:2}
17
+ assert_equal 2, hash.size
18
+ end
19
+ end
20
+
21
+ def test_select
22
+ GrnMini::Hash.tmpdb do |hash|
23
+ hash["a"] = {text:"aaa", number:1}
24
+ hash["b"] = {text:"bbb", number:2}
25
+ hash["c"] = {text:"ccc", number:3}
26
+
27
+ results = hash.select("bb")
28
+
29
+ assert_equal 1, results.size
30
+ assert_equal "b", results.first.key.key
31
+ assert_equal "bbb", results.first.text
32
+ end
33
+ end
34
+
35
+ def test_select2
36
+ GrnMini::Hash.tmpdb do |hash|
37
+ hash["a"] = {text:"aaa", number:1}
38
+ hash["b"] = {text:"bbb", number:2}
39
+ hash["c"] = {text:"bbb", number:20}
40
+ hash["d"] = {text:"ccc", number:3}
41
+
42
+ results = hash.select("bb number:<10")
43
+
44
+ assert_equal 1, results.size
45
+ assert_equal "b", results.first.key.key
46
+ assert_equal "bbb", results.first.text
47
+ assert_equal 2, results.first.number
48
+ end
49
+ end
50
+
51
+ def test_size
52
+ GrnMini::Hash.tmpdb do |hash|
53
+ assert_equal 0, hash.size
54
+ assert_equal 0, hash.length
55
+
56
+ hash["a"] = {text:"aaa", number:1}
57
+ hash["b"] = {text:"bbb", number:2}
58
+ assert_equal 2, hash.size
59
+ assert_equal 2, hash.length
60
+ end
61
+ end
62
+
63
+ def test_empty?
64
+ GrnMini::Hash.tmpdb do |hash|
65
+ assert_equal true, hash.empty?
66
+
67
+ hash["a"] = {text:"aaa", number:1}
68
+ assert_equal false, hash.empty?
69
+ end
70
+ end
71
+
72
+ def test_each
73
+ GrnMini::Hash.tmpdb do |hash|
74
+ hash["c"] = {text:"ccc", number:3}
75
+ hash["a"] = {text:"aaa", number:1}
76
+ hash["b"] = {text:"bbb", number:2}
77
+
78
+ total = 0
79
+
80
+ hash.each do |v|
81
+ total += v.number
82
+ end
83
+
84
+ assert_equal 6, total
85
+ end
86
+ end
87
+
88
+ def test_read_by_key
89
+ GrnMini::Hash.tmpdb do |hash|
90
+ hash["a"] = {text:"aaa", number:1}
91
+ hash["b"] = {text:"bbb", number:2}
92
+ hash["c"] = {text:"ccc", number:3}
93
+
94
+ assert_equal nil, hash["not found"]
95
+ assert_equal "aaa", hash["a"].text
96
+ assert_equal "bbb", hash["b"].text
97
+ assert_equal "ccc", hash["c"].text
98
+ end
99
+ end
100
+
101
+ def test_write_by_key
102
+ GrnMini::Hash.tmpdb do |hash|
103
+ hash["a"] = {text:"aaa", number:1}
104
+ hash["b"] = {text:"bbb", number:2}
105
+ hash["c"] = {text:"ccc", number:3}
106
+
107
+ assert_equal "bbb", hash["b"].text
108
+ assert_equal 2, hash["b"].number
109
+
110
+ hash["b"].text = "BBB"
111
+ hash["b"].number = 22
112
+
113
+ assert_equal "BBB", hash["b"].text
114
+ assert_equal 22, hash["b"].number
115
+ end
116
+ end
117
+
118
+ def test_delete_by_id
119
+ GrnMini::Hash.tmpdb do |hash|
120
+ hash["a"] = {text:"aaa", number:1}
121
+ hash["b"] = {text:"bbb", number:2}
122
+ hash["c"] = {text:"ccc", number:3}
123
+
124
+ # Delete from key
125
+ assert_equal 3, hash.size
126
+ assert_equal 2, hash["b"].number
127
+
128
+ hash.delete("b")
129
+
130
+ assert_equal 2, hash.size
131
+ assert_nil hash["b"]
132
+ end
133
+ end
134
+
135
+ def test_delete_by_block
136
+ GrnMini::Hash.tmpdb do |hash|
137
+ hash["a"] = {text:"aaa", number:1}
138
+ hash["b"] = {text:"bbb", number:2}
139
+ hash["c"] = {text:"ccc", number:3}
140
+
141
+ hash.delete do |record|
142
+ record.number >= 2
143
+ end
144
+
145
+ assert_equal 1, hash.size
146
+ assert_equal "aaa", hash.first.text
147
+ assert_equal 1, hash.first.number
148
+ end
149
+ end
150
+
151
+ def test_float_column
152
+ GrnMini::Hash.tmpdb do |hash|
153
+ hash["a"] = {text:"aaaa", float: 1.5}
154
+ hash["b"] = {text:"bbbb", float: 2.5}
155
+ hash["c"] = {text:"cccc", float: 3.5}
156
+
157
+ assert_equal 2.5, hash["b"].float
158
+
159
+ results = hash.select("float:>2.6")
160
+ assert_equal 3.5, results.first.float
161
+ end
162
+ end
163
+
164
+ def test_time_column
165
+ GrnMini::Hash.tmpdb do |hash|
166
+ hash["a"] = {text:"aaaa", timestamp: Time.new(2013)} # 2013-01-01
167
+ hash["b"] = {text:"bbbb", timestamp: Time.new(2014)} # 2014-01-01
168
+ hash["c"] = {text:"cccc", timestamp: Time.new(2015)} # 2015-01-01
169
+
170
+ assert_equal Time.new(2014), hash["b"].timestamp
171
+
172
+ results = hash.select("timestamp:<=#{Time.new(2013,12).to_i}")
173
+ assert_equal 1, results.size
174
+ assert_equal Time.new(2013), results.first.timestamp
175
+ end
176
+ end
177
+
178
+ def test_record_attributes
179
+ GrnMini::Hash.tmpdb do |hash|
180
+ hash["a"] = {text:"aaaa", int: 1}
181
+ hash["b"] = {text:"bbbb", int: 2}
182
+ hash["c"] = {text:"cccc", int: 3}
183
+
184
+ assert_equal({"_id"=>1, "_key"=>"a", "int"=>1, "text"=>"aaaa"}, hash["a"].attributes)
185
+ assert_equal({"_id"=>2, "_key"=>"b", "int"=>2, "text"=>"bbbb"}, hash["b"].attributes)
186
+ assert_equal({"_id"=>3, "_key"=>"c", "int"=>3, "text"=>"cccc"}, hash["c"].attributes)
187
+ end
188
+ end
189
+
190
+ def test_assign_long_text_to_short_text
191
+ GrnMini::Hash.tmpdb do |hash|
192
+ hash["a"] = {filename:"a.txt"}
193
+ hash["b"] = {filename:"a"*4095 + ".txt" } # Over 4095 byte (ShortText limit)
194
+
195
+ results = hash.select("txt", default_column: "filename")
196
+ assert_equal 2, results.size
197
+ end
198
+ end
199
+
200
+ def test_grn_object
201
+ GrnMini::Hash.tmpdb do |hash|
202
+ hash["a"] = {text: "aaaa", filename:"a.txt", int: 1, float: 1.5, time: Time.at(2001)}
203
+
204
+ raw = hash.grn
205
+
206
+ assert_equal true, raw.have_column?("filename")
207
+ assert_equal true, raw.have_column?("int")
208
+ assert_equal true, raw.have_column?("float")
209
+ assert_equal true, raw.have_column?("time")
210
+ assert_equal false, raw.have_column?("timeee")
211
+
212
+ assert_equal "ShortText", raw.column("text").range.name
213
+ assert_equal "ShortText", raw.column("filename").range.name
214
+ assert_equal "Int32" , raw.column("int").range.name
215
+ assert_equal "Float" , raw.column("float").range.name
216
+ assert_equal "Time" , raw.column("time").range.name
217
+
218
+ assert_equal true, raw.support_key? # GrnMini::Array is false
219
+ assert_equal false, raw.support_sub_records?
220
+ end
221
+ end
222
+
223
+ def test_sort
224
+ GrnMini::Hash.tmpdb do |hash|
225
+ hash["a"] = {name:"Tanaka", age: 11, height: 162.5}
226
+ hash["b"] = {name:"Suzuki", age: 31, height: 170.0}
227
+ hash["c"] = {name:"Hayashi", age: 21, height: 175.4}
228
+ hash["d"] = {name:"Suzuki", age: 5, height: 110.0}
229
+
230
+ sorted_by_age = hash.sort(["age"])
231
+ sorted_array = sorted_by_age.map {|r| {name: r.name, age: r.age}}
232
+ assert_equal [{:name=>"Suzuki", :age=>5},
233
+ {:name=>"Tanaka", :age=>11},
234
+ {:name=>"Hayashi", :age=>21},
235
+ {:name=>"Suzuki", :age=>31}], sorted_array
236
+
237
+ sorted_by_combination = hash.sort([{key: "name", order: :ascending},
238
+ {key: "age" , order: :descending}])
239
+ sorted_array = sorted_by_combination.map {|r| {name: r.name, age: r.age}}
240
+ assert_equal [{:name=>"Hayashi", :age=>21},
241
+ {:name=>"Suzuki", :age=>31},
242
+ {:name=>"Suzuki", :age=>5},
243
+ {:name=>"Tanaka", :age=>11}], sorted_array
244
+ end
245
+ end
246
+
247
+ def test_group_from_hash
248
+ GrnMini::Hash.tmpdb do |hash|
249
+ hash["a"] = {text:"aaaa.txt", suffix:"txt", type:1}
250
+ hash["b"] = {text:"aaaa.doc", suffix:"doc", type:2}
251
+ hash["c"] = {text:"aabb.txt", suffix:"txt", type:2}
252
+
253
+ groups = GrnMini::Util::group_with_sort(hash, "suffix")
254
+
255
+ assert_equal 2, groups.size
256
+ assert_equal ["txt", 2], [groups[0].key, groups[0].n_sub_records]
257
+ assert_equal ["doc", 1], [groups[1].key, groups[1].n_sub_records]
258
+ end
259
+ end
260
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grn_mini
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ongaeshi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-07 00:00:00.000000000 Z
11
+ date: 2014-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -85,12 +85,14 @@ files:
85
85
  - grn_mini.gemspec
86
86
  - lib/grn_mini.rb
87
87
  - lib/grn_mini/array.rb
88
+ - lib/grn_mini/hash.rb
88
89
  - lib/grn_mini/util.rb
89
90
  - lib/grn_mini/version.rb
90
91
  - sample/mini-directory-search.rb
91
92
  - test/minitest_helper.rb
92
93
  - test/test_grn_mini.rb
93
94
  - test/test_grn_mini_array.rb
95
+ - test/test_grn_mini_hash.rb
94
96
  homepage: ''
95
97
  licenses:
96
98
  - MIT
@@ -119,3 +121,4 @@ test_files:
119
121
  - test/minitest_helper.rb
120
122
  - test/test_grn_mini.rb
121
123
  - test/test_grn_mini_array.rb
124
+ - test/test_grn_mini_hash.rb