grn_mini 0.3.0 → 0.4.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: 954b7ebeb13d40913ed6022a6b96d972193b73ea
4
- data.tar.gz: c64cf4de87e4cf59b172fb1b4d5c64d7f8f17e12
3
+ metadata.gz: a3573d54bbab536ecc6429349a5326bce7f07e6b
4
+ data.tar.gz: e8d6c8f86a4b732aea1d84f6aee06ab8521fda97
5
5
  SHA512:
6
- metadata.gz: 0406c079b5f1fac34c4f35de6e0ca59b1236df413b285ec28d529c054e1e08f1558f03712b24c37d2dba53f843e219db3ecc37e3d3ea33143faf4121c50b6fb1
7
- data.tar.gz: 747fe7c71d88f786229ad7461639b9ff4de8cee0bc73e27aff73ce3301c98659311173517434b98b857b91bbbace9aabb084ee3900c968fd828bad8531d43af3
6
+ metadata.gz: a7471f3cf1a8e784d1aad28d94d84f174aa19fb31a570d4a9b6e2dfd339a15e33341e39c43e0b14134db64deafb05fdc2cca51feded94a679df8179f01bc60bc
7
+ data.tar.gz: b0ecedae697ebc81e318c815488188db3744b87bac42fc91970b46b41c7158bf3cac1194784d058f8d8b3794eb1d9cf3bbd86d742535c33eaeaee3fea3eb26f7
data/HISTORY.md ADDED
@@ -0,0 +1,45 @@
1
+ # HISTORY - grn_mini
2
+
3
+ ## 0.4 - 2014/02/01
4
+
5
+ - GrnMini
6
+ - Add GrnMini::create_or_open(db_name)
7
+ - Add GrnMini::tmpdb
8
+
9
+ - GrnMini::Table
10
+ - Extract common function of Array and Hash
11
+ - Array < Table
12
+ - Hash < Table
13
+ - Add Table#setup_columns
14
+ - Specification of column types explicitly
15
+ - Support cross-reference between table
16
+ - Support new column type
17
+ - VECTOR_COLUMN
18
+ - GrnMini::Table, Groonga::Table (with define_index_column)
19
+ - "BOOL"
20
+ - GrnMini::Table#select
21
+ - Support block argument
22
+ - Quit the support of {default_column: "text”}
23
+
24
+ - GrnMini::Array
25
+ - Array.new(database_name) -> Array.new(table_name)
26
+ - Remove Array::tmpdb
27
+
28
+ - GrnMini::Hash
29
+ - Hash.new(database_name) -> Hash.new(table_name)
30
+ - Remove Hash::tmpdb
31
+
32
+ - README.md
33
+ - Fix to the new API sample code
34
+
35
+ ## 0.3 - 2014/01/10
36
+
37
+ - Support GrnMini::Hash
38
+
39
+ ## 0.2 - 2014/01/07
40
+
41
+ - Support snippet
42
+
43
+ ## 0.1 - 2014/01/05
44
+
45
+ - 1st Release
data/README.md CHANGED
@@ -1,8 +1,16 @@
1
1
  # GrnMini
2
2
 
3
- Groonga(Rroonga) wrapper for use as the KVS.
4
-
5
- Groonga(Rroonga) for using easily. You can add the data in the column without specifying. You can easy to use and persistence, advanced search query, sort, grouping (drill down), snippets, and pagination. You can make an immediate search engine.
3
+ Groonga(Rroonga) wrapper for using easily.
4
+
5
+ - Automatic generation of the column with data type
6
+ - Specification of column types explicitly
7
+ - Advanced Search Query
8
+ - Persistence
9
+ - Sort
10
+ - Grouping (Drill Down)
11
+ - Snippets
12
+ - Pagination
13
+ - Cooperation between multiple tables
6
14
 
7
15
  ## Installation
8
16
 
@@ -14,7 +22,7 @@ Groonga(Rroonga) for using easily. You can add the data in the column without sp
14
22
 
15
23
  ```ruby
16
24
  require 'grn_mini'
17
- array = GrnMini::Array.new("test.db")
25
+ GrnMini::create_or_open("test.db")
18
26
  ```
19
27
 
20
28
  ### Add the record with the number column and text column.
@@ -22,6 +30,7 @@ array = GrnMini::Array.new("test.db")
22
30
  Determine the column type when you first call "GrnMini::Array#add". (Add inverted index if data type is "string".)
23
31
 
24
32
  ```ruby
33
+ array = GrnMini::Array.new
25
34
  array.add(text: "aaa", number: 1)
26
35
  ```
27
36
 
@@ -37,14 +46,16 @@ array.size #=> 3
37
46
 
38
47
  ```ruby
39
48
  require 'grn_mini'
40
- array = GrnMini::Array.new("test.db")
49
+ GrnMini::create_or_open("test.db")
50
+ array = GrnMini::Array.new
41
51
  array.size #=> 3
42
52
  ```
43
53
 
44
54
  ### Create a temporary database. (Useful for testing)
45
55
 
46
56
  ```ruby
47
- GrnMini::Array.tmpdb do |array|
57
+ GrnMini::tmpdb do
58
+ array = GrnMini::Array.new
48
59
  array << {text: "aaa", number: 1}
49
60
  array << {text: "bbb", number: 2}
50
61
  array << {text: "ccc", number: 3}
@@ -56,8 +67,8 @@ end
56
67
 
57
68
  ```ruby
58
69
  require 'grn_mini'
59
-
60
- hash = GrnMini::Hash.new("test.db")
70
+ GrnMini::create_or_open("test.db")
71
+ hash = GrnMini::Hash.new
61
72
 
62
73
  # Add
63
74
  hash["a"] = {text:"aaa", number:1}
@@ -71,10 +82,57 @@ hash["b"].text #=> "bbb"
71
82
  hash["b"].text = "BBB"
72
83
  ```
73
84
 
85
+ ## Specify table name.
86
+ Default table name is "Array"(GrnMini::Array) or "Hash"(GrnMini::Hash).
87
+
88
+ ```ruby
89
+ GrnMini::tmpdb do
90
+ array = GrnMini::Array.new("Users")
91
+ array << {text: "aaa", number: 1}
92
+ end
93
+ ```
94
+
95
+ ## Specification of column types explicitly
96
+
97
+ Use GrnMini::Table#setup_columns.
98
+
99
+ ```ruby
100
+ GrnMini::tmpdb do
101
+ array = GrnMini::Array.new
102
+
103
+ # Specify dummy data
104
+ array.setup_columns(filename: "",
105
+ int: 0,
106
+ float: 0.0,
107
+ time: Time.new,
108
+ )
109
+
110
+ array << {filename: "a.txt", int: 1, float: 1.5, time: Time.at(1999)}
111
+ end
112
+ ```
113
+
114
+ The following is the same meaning.
115
+
116
+ ```ruby
117
+ GrnMini::tmpdb do
118
+ array = GrnMini::Array.new
119
+ # Automatic generation of the column with data type
120
+ array << {filename: "a.txt", int: 1, float: 1.5, time: Time.at(1999)}
121
+ end
122
+ ```
123
+
124
+ GrnMini::Table#setup_columns is useful for below.
125
+
126
+ - Specification of column types explicitly
127
+ - Refer to itself
128
+ - Cross-reference between tables
129
+ - See "Cooperation between multiple tables"
130
+
74
131
  ## Data Type
75
132
 
76
133
  ```ruby
77
- GrnMini::Array.tmpdb do |array|
134
+ GrnMini::tmpdb do
135
+ array = GrnMini::Array.new
78
136
  array << {filename: "a.txt", int: 1, float: 1.5, time: Time.at(1999)}
79
137
  array << {filename: "b.doc", int: 2, float: 2.5, time: Time.at(2000)}
80
138
 
@@ -105,7 +163,8 @@ See also [8.4. Data type — Groonga documentation](http://groonga.org/docs/refe
105
163
  ```ruby
106
164
  require 'grn_mini'
107
165
 
108
- array = GrnMini::Array.new("test2.db")
166
+ GrnMini::create_or_open("test2.db")
167
+ array = GrnMini::Array.new
109
168
  array << {name:"Tanaka", age: 11, height: 162.5}
110
169
  array << {name:"Suzuki", age: 31, height: 170.0}
111
170
  ```
@@ -156,7 +215,9 @@ array.first.attributes #=> {"_id"=>2, "age"=>31, "height"=>170.0, "name"=>"Haya
156
215
  It is also possible to pass the block.
157
216
 
158
217
  ```ruby
159
- GrnMini::Array.tmpdb do |array|
218
+ GrnMini::tmpdb do
219
+ array = GrnMini::Array.new
220
+
160
221
  array << {name:"Tanaka", age: 11, height: 162.5}
161
222
  array << {name:"Suzuki", age: 31, height: 170.0}
162
223
  array << {name:"Hayashi", age: 20, height: 165.0}
@@ -173,41 +234,44 @@ end
173
234
  ## Search
174
235
 
175
236
  Use GrnMini::Array#select method.
176
- `:text` column is set to the `:default_column` implicitly.
177
237
 
178
238
  ```ruby
179
- GrnMini::Array.tmpdb do |array|
239
+ GrnMini::tmpdb do
240
+ array = GrnMini::Array.new
241
+
180
242
  array << {text:"aaa", number:1}
181
243
  array << {text:"bbb", number:20}
182
244
  array << {text:"bbb ccc", number:2}
183
245
  array << {text:"bbb", number:15}
184
246
  array << {text:"ccc", number:3}
185
247
 
186
- results = array.select("aaa")
248
+ results = array.select("text:aaa")
187
249
  results.map {|record| record.attributes} #=> [{"_id"=>1, "_key"=>{"_id"=>1, "number"=>1, "text"=>"aaa"}, "_score"=>1}]
188
250
 
189
251
  # AND
190
- results = array.select("bbb ccc")
252
+ results = array.select("text:@bbb text:@ccc")
191
253
  results.map {|record| record.attributes} #=> [{"_id"=>2, "_key"=>{"_id"=>3, "number"=>2, "text"=>"bbb ccc"}, "_score"=>2}]
192
254
 
193
255
  # Specify column
194
- results = array.select("bbb number:<10")
256
+ results = array.select("text:@bbb number:<10")
195
257
  results.map {|record| record.attributes} #=> [{"_id"=>2, "_key"=>{"_id"=>3, "number"=>2, "text"=>"bbb ccc"}, "_score"=>2}]
196
258
 
197
259
  # AND, OR, Grouping
198
- results = array.select("bbb (number:<= 10 OR number:>=20)")
260
+ results = array.select("text:@bbb (number:<= 10 OR number:>=20)")
199
261
  results.map {|record| record.attributes} #=> [{"_id"=>2, "_key"=>{"_id"=>3, "number"=>2, "text"=>"bbb ccc"}, "_score"=>2}, {"_id"=>4, "_key"=>{"_id"=>2, "number"=>20, "text"=>"bbb"}, "_score"=>2}]
200
262
 
201
263
  # NOT
202
- results = array.select("bbb - ccc")
264
+ results = array.select("text:@bbb - text:@ccc")
203
265
  results.map {|record| record.attributes} #=> [{"_id"=>1, "_key"=>{"_id"=>2, "number"=>20, "text"=>"bbb"}, "_score"=>1}, {"_id"=>3, "_key"=>{"_id"=>4, "number"=>15, "text"=>"bbb"}, "_score"=>1}]
204
266
  end
205
267
  ```
206
268
 
207
- Change `:default_column` to `:filename` column.
269
+ Use `:default_column` option.
208
270
 
209
271
  ```ruby
210
- GrnMini::Array.tmpdb do |array|
272
+ GrnMini::tmpdb do
273
+ array = GrnMini::Array.new
274
+
211
275
  array << {text: "txt", filename:"a.txt"}
212
276
  array << {text: "txt", filename:"a.doc"}
213
277
  array << {text: "txt", filename:"a.rb"}
@@ -229,7 +293,9 @@ See also [8.10.1. Query syntax](http://groonga.org/docs/reference/grn_expr/query
229
293
  Specify column name to sort.
230
294
 
231
295
  ```ruby
232
- GrnMini::Array.tmpdb do |array|
296
+ GrnMini::tmpdb do
297
+ array = GrnMini::Array.new
298
+
233
299
  array << {name:"Tanaka", age: 11, height: 162.5}
234
300
  array << {name:"Suzuki", age: 31, height: 170.0}
235
301
  array << {name:"Hayashi", age: 21, height: 175.4}
@@ -263,7 +329,9 @@ sorted.map {|r| {name: r.name, age: r.age}}
263
329
  Drill down aka.
264
330
 
265
331
  ```ruby
266
- GrnMini::Array.tmpdb do |array|
332
+ GrnMini::tmpdb do
333
+ array = GrnMini::Array.new
334
+
267
335
  array << {text:"aaaa.txt", suffix:"txt", type:1}
268
336
  array << {text:"aaaa.doc", suffix:"doc", type:2}
269
337
  array << {text:"aabb.txt", suffix:"txt", type:2}
@@ -279,13 +347,15 @@ end
279
347
  Grouping from selection results.
280
348
 
281
349
  ```ruby
282
- GrnMini::Array.tmpdb do |array|
350
+ GrnMini::tmpdb do
351
+ array = GrnMini::Array.new
352
+
283
353
  array << {text:"aaaa", suffix:"txt"}
284
354
  array << {text:"aaaa", suffix:"doc"}
285
355
  array << {text:"aaaa", suffix:"txt"}
286
356
  array << {text:"cccc", suffix:"txt"}
287
357
 
288
- results = array.select("aa")
358
+ results = array.select("text:@aa")
289
359
  groups = GrnMini::Util::group_with_sort(results, "suffix")
290
360
 
291
361
  groups.size #=> 2
@@ -300,7 +370,9 @@ Display of keyword surrounding text. It is often used in search engine.
300
370
  Use `GrnMini::Util::text_snippet_from_selection_results`.
301
371
 
302
372
  ```ruby
303
- GrnMini::Array.tmpdb do |array|
373
+ GrnMini::tmpdb do
374
+ array = GrnMini::Array.new
375
+
304
376
  array << {text: <<EOF, filename: "aaa.txt"}
305
377
  [1] This is a pen pep pea pek pet.
306
378
  ------------------------------
@@ -314,7 +386,7 @@ GrnMini::Array.tmpdb do |array|
314
386
  ------------------------------
315
387
  EOF
316
388
 
317
- results = array.select("This pen")
389
+ results = array.select("text:@This pen")
318
390
  snippet = GrnMini::Util::text_snippet_from_selection_results(results)
319
391
 
320
392
  record = results.first
@@ -328,14 +400,16 @@ end
328
400
  `GrnMini::Util::html_snippet_from_selection_results` is HTML escaped.
329
401
 
330
402
  ```ruby
331
- GrnMini::Array.tmpdb do |array|
403
+ GrnMini::tmpdb do
404
+ array = GrnMini::Array.new
405
+
332
406
  array << {text: <<EOF, filename: "aaa.txt"}
333
407
  <html>
334
408
  <div>This is a pen pep pea pek pet.</div>
335
409
  </html>
336
410
  EOF
337
411
 
338
- results = array.select("This pen")
412
+ results = array.select("text:@This pen")
339
413
  snippet = GrnMini::Util::html_snippet_from_selection_results(results, '<span class="strong">', '</span>') # Default value is '<strong>', '</strong>'
340
414
 
341
415
  record = results.first
@@ -352,7 +426,9 @@ See also [Groonga::Expression#snippet](http://ranguba.org/rroonga/en/Groonga/Exp
352
426
  #paginate is more convenient than #sort if you want a pagination.
353
427
 
354
428
  ```ruby
355
- GrnMini::Array.tmpdb do |array|
429
+ GrnMini::tmpdb do
430
+ array = GrnMini::Array.new
431
+
356
432
  array << {text: "aaaa", filename: "1.txt"}
357
433
  array << {text: "aaaa aaaa", filename: "2a.txt"}
358
434
  array << {text: "aaaa aaaa aaaa", filename: "3.txt"}
@@ -362,7 +438,7 @@ GrnMini::Array.tmpdb do |array|
362
438
  array << {text: "aaaa aaaa", filename: "2e.txt"}
363
439
  array << {text: "aaaa aaaa", filename: "2f.txt"}
364
440
 
365
- results = array.select("aaaa")
441
+ results = array.select("text:@aaaa")
366
442
 
367
443
  # -- page1 --
368
444
  page_entries = results.paginate([["_score", :desc]], :page => 1, :size => 5)
@@ -395,3 +471,38 @@ end
395
471
 
396
472
  See also [Groonga::Table#pagenate](http://ranguba.org/rroonga/en/Groonga/Table.html#paginate-instance_method)
397
473
 
474
+ ## Cooperation between multiple tables
475
+
476
+ Micro blog sample.
477
+
478
+ ```ruby
479
+ GrnMini::tmpdb do
480
+ users = GrnMini::Hash.new("Users")
481
+ articles = GrnMini::Hash.new("Articles")
482
+
483
+ users.setup_columns(name: "", favorites: [articles])
484
+ articles.setup_columns(author: users, text: "")
485
+
486
+ users["aaa"] = {name: "Mr.A"}
487
+ users["bbb"] = {name: "Mr.B"}
488
+ users["ccc"] = {name: "Mr.C"}
489
+
490
+ articles["aaa:1"] = {author: "aaa", text: "111"}
491
+ articles["aaa:2"] = {author: "aaa", text: "222"}
492
+ articles["aaa:3"] = {author: "aaa", text: "333"}
493
+ articles["bbb:1"] = {author: "bbb", text: "111"}
494
+ articles["bbb:2"] = {author: "bbb", text: "222"}
495
+ articles["ccc:1"] = {author: "ccc", text: "111"}
496
+
497
+ users["aaa"].favorites = ["aaa:1", "bbb:2"]
498
+ users["bbb"].favorites = ["aaa:2"]
499
+ users["ccc"].favorites = ["aaa:1", "bbb:1", "ccc:1"]
500
+
501
+ # Search record.favorites
502
+ users.select { |record| record.favorites == "aaa:1" } #=> ["aaa", "ccc"]
503
+ users.select { |record| record.favorites == "aaa:2" } #=> ["bbb"]
504
+
505
+ # Search record.favorites.text
506
+ users.select { |record| record.favorites.text =~ "111" } #=> ["aaa", "ccc"]
507
+ end
508
+ ```
data/lib/grn_mini.rb CHANGED
@@ -2,7 +2,24 @@ require "grn_mini/version"
2
2
  require "grn_mini/array"
3
3
  require "grn_mini/hash"
4
4
  require "grn_mini/util"
5
+ require 'groonga'
6
+ require 'tmpdir'
5
7
 
6
8
  module GrnMini
7
- # Your code goes here...
9
+ module_function
10
+
11
+ def create_or_open(path)
12
+ unless File.exist?(path)
13
+ Groonga::Database.create(path: path)
14
+ else
15
+ Groonga::Database.open(path)
16
+ end
17
+ end
18
+
19
+ def tmpdb
20
+ Dir.mktmpdir do |dir|
21
+ create_or_open(File.join(dir, "tmp.db"))
22
+ yield
23
+ end
24
+ end
8
25
  end
@@ -1,81 +1,23 @@
1
- require 'grn_mini/util'
2
- require 'groonga'
3
- require 'tmpdir'
1
+ require 'grn_mini/table'
4
2
 
5
3
  module GrnMini
6
- class Array
7
- attr_accessor :grn
8
- include Enumerable
4
+ class NotSupportColumnType < RuntimeError; end
9
5
 
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
- unless Groonga["Array"]
25
- @grn = Groonga::Array.create(name: "Array", persistent: true)
26
- @terms = Groonga::PatriciaTrie.create(name: "Terms", key_normalize: true, default_tokenizer: "TokenBigramSplitSymbolAlphaDigit")
27
- else
28
- @grn = Groonga["Array"]
29
- @terms = Groonga["Terms"]
30
- end
6
+ class Array < Table
7
+ def initialize(name = "Array")
8
+ super(name,
9
+ Groonga[name] || Groonga::Array.create(name: name, persistent: true))
31
10
  end
32
11
 
33
12
  def add(hash)
34
- if @grn.empty?
35
- hash.each do |key, value|
36
- column = key.to_s
37
-
38
- # @todo Need define_index_column ?
39
- if value.is_a?(Time)
40
- @grn.define_column(column, "Time")
41
- elsif value.is_a?(Float)
42
- @grn.define_column(column, "Float")
43
- elsif value.is_a?(Numeric)
44
- @grn.define_column(column, "Int32")
45
- else
46
- @grn.define_column(column, "ShortText")
47
- @terms.define_index_column("array_#{column}", @grn, source: "Array.#{column}", with_position: true)
48
- end
49
- end
50
- end
51
-
13
+ setup_columns(hash) unless @setup_columns_once
52
14
  @grn.add(hash)
53
15
  end
54
16
 
55
17
  alias << add
56
18
 
57
- def select(query, options = {default_column: "text"})
58
- @grn.select(query, options)
59
- end
60
-
61
- def size
62
- @grn.size
63
- end
64
-
65
- alias length size
66
-
67
- def empty?
68
- size == 0
69
- end
70
-
71
- def each
72
- @grn.each do |record|
73
- yield record
74
- end
75
- end
76
-
77
19
  class IdIsGreaterThanZero < RuntimeError; end
78
-
20
+
79
21
  def [](id)
80
22
  raise IdIsGreaterThanZero if id == 0
81
23
  @grn[id]
@@ -89,13 +31,5 @@ module GrnMini
89
31
  @grn.delete(id)
90
32
  end
91
33
  end
92
-
93
- def sort(keys, options = {})
94
- @grn.sort(keys, options)
95
- end
96
-
97
- def group(key, options = {})
98
- @grn.group(key, options)
99
- end
100
34
  end
101
35
  end