xapian-fu 0.2 → 1.0.1

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.
@@ -2,6 +2,7 @@ require 'xapian'
2
2
  require 'lib/xapian_fu.rb'
3
3
  include XapianFu
4
4
  require 'fileutils'
5
+ require 'date'
5
6
 
6
7
  # Will be deleted
7
8
  tmp_dir = '/tmp/xapian_fu_test.db'
@@ -10,24 +11,36 @@ describe XapianDb do
10
11
  before do
11
12
  FileUtils.rm_rf tmp_dir if File.exists?(tmp_dir)
12
13
  end
14
+
15
+ describe "new" do
16
+ it "should make an in-memory database by default" do
17
+ xdb = XapianDb.new
18
+ xdb.ro.should be_a_kind_of(Xapian::Database)
19
+ xdb.rw.should === xdb.ro
20
+ end
21
+
22
+ it "should make an on-disk database when given a :dir option" do
23
+ xdb = XapianDb.new(:dir => tmp_dir, :create => true)
24
+ xdb.rw
25
+ File.exists?(tmp_dir).should be_true
26
+ xdb.should respond_to(:dir)
27
+ xdb.dir.should == tmp_dir
28
+ xdb.rw.should be_a_kind_of(Xapian::WritableDatabase)
29
+ xdb.ro.should be_a_kind_of(Xapian::Database)
30
+ end
13
31
 
14
- it "should make an in-memory database by default" do
15
- xdb = XapianDb.new
16
- xdb.ro.should be_a_kind_of(Xapian::Database)
17
- xdb.rw.should === xdb.ro
18
32
  end
19
-
20
- it "should make an on-disk database when given a :dir option" do
33
+
34
+ it "should lazily create the on-disk database when rw is used" do
21
35
  xdb = XapianDb.new(:dir => tmp_dir, :create => true)
22
- File.exists?(tmp_dir).should be_true
23
- xdb.should respond_to(:dir)
24
- xdb.dir.should == tmp_dir
25
- xdb.rw.should be_a_kind_of(Xapian::WritableDatabase)
26
- xdb.ro.should be_a_kind_of(Xapian::Database)
36
+ File.exists?(tmp_dir).should be_false
37
+ xdb.rw
38
+ File.exists?(tmp_dir).should be_true
27
39
  end
28
40
 
29
41
  it "should flush documents to the index when flush is called" do
30
42
  xdb = XapianDb.new(:dir => tmp_dir, :create => true)
43
+ xdb.flush
31
44
  xdb.size.should == 0
32
45
  xdb << "Once upon a time"
33
46
  xdb.size.should == 0
@@ -35,261 +48,491 @@ describe XapianDb do
35
48
  xdb.size.should == 1
36
49
  end
37
50
 
38
- it "should support transactions" do
39
- xdb = XapianDb.new(:dir => tmp_dir, :create => true)
40
- xdb << "Once upon a time"
41
- xdb.transaction do
51
+ it "should return a nice string when inspect is called" do
52
+ XapianDb.new.inspect.should =~ /XapianDb/
53
+ end
54
+
55
+ describe "transaction" do
56
+ it "should commit writes when the block completed successfully" do
57
+ xdb = XapianDb.new(:dir => tmp_dir, :create => true)
42
58
  xdb << "Once upon a time"
43
- xdb.size.should == 1
59
+ xdb.transaction do
60
+ xdb << "Once upon a time"
61
+ xdb.size.should == 1
62
+ end
63
+ xdb.flush
64
+ xdb.size.should == 2
44
65
  end
45
- xdb.flush
46
- xdb.size.should == 2
47
- end
48
66
 
49
- it "should serialize attempts at concurrent transactions" do
50
- xdb = XapianDb.new(:dir => tmp_dir, :create => true)
51
- thread = Thread.new do
67
+ it "should serialize attempts at concurrent transactions" do
68
+ xdb = XapianDb.new(:dir => tmp_dir, :create => true)
69
+ thread = Thread.new do
70
+ xdb.transaction do
71
+ sleep 0.1
72
+ xdb << "Once upon a time"
73
+ sleep 0.1
74
+ xdb << "Once upon a time"
75
+ end
76
+ end
52
77
  xdb.transaction do
53
- sleep 0.1
54
78
  xdb << "Once upon a time"
55
79
  sleep 0.1
56
80
  xdb << "Once upon a time"
57
81
  end
82
+ thread.join
83
+ xdb.flush
84
+ xdb.size.should == 4
58
85
  end
59
- xdb.transaction do
60
- xdb << "Once upon a time"
61
- sleep 0.1
86
+
87
+ it "should abort a transaction on an exception" do
88
+ xdb = XapianDb.new(:dir => tmp_dir, :create => true)
62
89
  xdb << "Once upon a time"
90
+ begin
91
+ xdb.transaction do
92
+ xdb << "Once upon a time"
93
+ raise StandardError
94
+ end
95
+ rescue StandardError
96
+ end
97
+ xdb.flush
98
+ xdb.size.should == 1
63
99
  end
64
- thread.join
65
- xdb.flush
66
- xdb.size.should == 4
67
100
  end
68
101
 
69
- it "should abort a transaction on an exception" do
70
- xdb = XapianDb.new(:dir => tmp_dir, :create => true)
71
- xdb << "Once upon a time"
72
- begin
73
- xdb.transaction do
74
- xdb << "Once upon a time"
75
- raise StandardError
102
+ describe "documents" do
103
+
104
+ it "should return a new XapianDoc with the db set on new" do
105
+ xdb = XapianDb.new
106
+ doc = xdb.documents.new
107
+ doc.should be_a_kind_of XapianDoc
108
+ doc.db.should == xdb
109
+ end
110
+
111
+ it "should raise a XapianFu::DocNotFound error on find if the document doesn't exist" do
112
+ xdb = XapianDb.new
113
+ xdb << "once upon a time"
114
+ xdb.flush
115
+ lambda { xdb.documents.find(10) }.should raise_error XapianFu::DocNotFound
116
+ end
117
+
118
+ it "should retrieve documents with the find method" do
119
+ xdb = XapianDb.new
120
+ xdb << "Once upon a time"
121
+ xdb.flush
122
+ xdb.documents.find(1).should be_a_kind_of(XapianDoc)
123
+ end
124
+
125
+ it "should retrieve documents like an array and return a XapianDoc" do
126
+ xdb = XapianDb.new
127
+ xdb << "once upon a time"
128
+ xdb.flush
129
+ xdb.documents[1].should be_a_kind_of(XapianDoc)
130
+ end
131
+
132
+ it "should provide the id of retrieved documents" do
133
+ xdb = XapianDb.new
134
+ xdb << "once upon a time"
135
+ xdb.documents[1].id.should == 1
136
+ end
137
+
138
+ it "should set the db field for the retrieved XapianDoc" do
139
+ xdb = XapianDb.new
140
+ xdb << "once upon a time"
141
+ xdb.documents[1].db.should == xdb
142
+ end
143
+
144
+ it "should delete docs by id" do
145
+ xdb = XapianDb.new
146
+ doc = xdb << XapianDoc.new("Once upon a time")
147
+ xdb.flush
148
+ xdb.size.should == 1
149
+ xdb.documents.delete(doc.id).should == 1
150
+ xdb.flush
151
+ xdb.size.should == 0
152
+ end
153
+
154
+ it "should handle being asked to delete docs that don't exist in the db" do
155
+ xdb = XapianDb.new
156
+ doc = xdb << XapianDoc.new("Once upon a time")
157
+ xdb.flush
158
+ xdb.documents.delete(100000).should == nil
159
+ end
160
+
161
+ describe "max" do
162
+ it "should return the doc with the highest id" do
163
+ xdb = XapianDb.new
164
+ xdb << { :id => 20 }
165
+ xdb << { :id => 9 }
166
+ xdb << { :id => 15 }
167
+ xdb.flush
168
+ xdb.documents.max.id.should == 20
169
+ end
170
+
171
+ it "should return the doc with the highest specified stored value" do
172
+ xdb = XapianDb.new(:fields => { :number => { :store => true } })
173
+ xdb << { :id => 8, :number => "200" }
174
+ xdb << { :id => 9, :number => "300" }
175
+ xdb << { :id => 15, :number => "100" }
176
+ xdb.flush
177
+ xdb.documents.max(:number).id.should == 9
76
178
  end
77
- rescue StandardError
78
179
  end
79
- xdb.flush
80
- xdb.size.should == 1
81
180
  end
82
181
 
83
- it "should index a XapianDoc" do
84
- xdb = XapianDb.new
85
- xdb << XapianDoc.new({ :text => "once upon a time", :title => "A story" })
86
- xdb.flush
87
- xdb.size.should == 1
88
- end
182
+ describe "when indexing" do
183
+ it "should index a XapianDoc" do
184
+ xdb = XapianDb.new
185
+ xdb << XapianDoc.new({ :text => "once upon a time", :title => "A story" })
186
+ xdb.flush
187
+ xdb.size.should == 1
188
+ end
89
189
 
90
- it "should index a Hash" do
91
- xdb = XapianDb.new
92
- xdb << { :text => "once upon a time", :title => "A story" }
93
- xdb.flush
94
- xdb.size.should == 1
95
- end
190
+ it "should index a Hash" do
191
+ xdb = XapianDb.new
192
+ xdb << { :text => "once upon a time", :title => "A story" }
193
+ xdb.flush
194
+ xdb.size.should == 1
195
+ end
96
196
 
97
- it "should index a string" do
98
- xdb = XapianDb.new
99
- xdb << "once upon a time"
100
- xdb.size.should == 1
101
- xdb << XapianDoc.new("once upon a time")
102
- xdb.size.should == 2
197
+ it "should index a string" do
198
+ xdb = XapianDb.new
199
+ xdb << "once upon a time"
200
+ xdb.size.should == 1
201
+ xdb << XapianDoc.new("once upon a time")
202
+ xdb.size.should == 2
203
+ end
204
+
103
205
  end
104
206
 
105
- it "should raise a XapianFu::DocNotFound error on find if the document doesn't exist" do
106
- xdb = XapianDb.new
107
- xdb << "once upon a time"
108
- xdb.flush
109
- lambda { xdb.documents.find(10) }.should raise_error XapianFu::DocNotFound
110
- end
207
+ describe "search" do
208
+ it "should return a list of XapianDocs with the weight and match set" do
209
+ xdb = XapianDb.new
210
+ xdb << XapianDoc.new(:title => 'once upon a time')
211
+ xdb << XapianDoc.new(:title => 'three little pings')
212
+ results = xdb.search("pings")
213
+ results.should be_a_kind_of Array
214
+ results.size.should == 1
215
+ results.first.should be_a_kind_of XapianDoc
216
+ results.first.match.should be_a_kind_of Xapian::Match
217
+ results.first.weight.should be_a_kind_of Float
218
+ end
111
219
 
112
- it "should retrieve documents with the find method" do
113
- xdb = XapianDb.new
114
- xdb << "Once upon a time"
115
- xdb.flush
116
- xdb.documents.find(1).should be_a_kind_of(XapianDoc)
117
- end
220
+ it "should collapse results by the value specified by the :collapse option" do
221
+ xdb = XapianDb.new(:collapsible => :group)
222
+ alpha1 = xdb << XapianDoc.new(:words => "cow dog cat", :group => "alpha")
223
+ alpha2 = xdb << XapianDoc.new(:words => "cow dog", :group => "alpha")
224
+ beta1 = xdb << XapianDoc.new(:words => "cow", :group => "beta")
225
+ results = xdb.search("cow dog cat", :collapse => :group, :default_op => :or)
226
+ results.should == [alpha1, beta1]
227
+ end
118
228
 
119
- it "should retrieve documents like an array and return a XapianDoc" do
120
- xdb = XapianDb.new
121
- xdb << "once upon a time"
122
- xdb.flush
123
- xdb.documents[1].should be_a_kind_of(XapianDoc)
124
- end
229
+ it "should do a case-insensitive boolean AND search by default" do
230
+ xdb = XapianDb.new
231
+ doc1 = xdb << "cow dog cat"
232
+ doc2 = xdb << "cow dog"
233
+ xdb.search("cow dog cat").should == [doc1]
234
+ end
125
235
 
126
- it "should provide the id of retrieved documents" do
127
- xdb = XapianDb.new
128
- xdb << "once upon a time"
129
- xdb.documents[1].id.should == 1
130
- end
236
+ it "should do a case-sensitive boolean search when the :boolean_anycase option is set to false" do
237
+ pending
238
+ xdb = XapianDb.new
239
+ doc1 = xdb << "cow dog"
240
+ doc2 = xdb << "COW dog"
241
+ xdb.search("cow", :boolean_anycase => false).should == [doc1]
242
+ xdb.search("COW", :boolean_anycase => false).should == [doc2]
243
+ end
131
244
 
132
- it "should store data in the database" do
133
- xdb = XapianDb.new
134
- xdb << XapianDoc.new({ :text => "once upon a time" }, :data => { :thing => 0xdeadbeef })
135
- xdb.size.should == 1
136
- doc = xdb.documents[1]
137
- doc.data.should == { :thing => 0xdeadbeef }
138
- end
245
+ it "should allow LOVEHATE style queries by default" do
246
+ xdb = XapianDb.new
247
+ doc1 = xdb << "cow dog cat moose"
248
+ doc2 = xdb << "cow dog"
249
+ doc3 = xdb << "cow dog moose"
250
+ doc4 = xdb << "cow moose"
251
+ xdb.search("cow +dog -cat", :default_op => :or).should == [doc2, doc3]
252
+ end
139
253
 
140
- it "should return a XapianDoc with an id after indexing" do
141
- xdb = XapianDb.new
142
- doc = XapianDoc.new("once upon a time")
143
- doc.id.should == nil
144
- new_doc = xdb << doc
145
- new_doc.id.should == 1
146
- end
254
+ it "should do a boolean OR search when :default_op option is set to :or" do
255
+ xdb = XapianDb.new
256
+ doc1 = xdb << "cow dog cat"
257
+ doc2 = xdb << "cow dog"
258
+ xdb.search("cow dog cat", :default_op => :or).should == [doc1, doc2]
259
+ end
147
260
 
148
- it "should replace docs that already have an id when adding to the db" do
149
- xdb = XapianDb.new
150
- doc = xdb << XapianDoc.new("Once upon a time")
151
- xdb.flush
152
- xdb.size.should == 1
153
- doc.id.should == 1
154
- updated_doc = xdb << doc
155
- xdb.flush
156
- xdb.size.should == 1
157
- updated_doc.id.should == doc.id
158
- end
261
+ it "should allow a wildcard search by default" do
262
+ xdb = XapianDb.new
263
+ doc1 = xdb << "fox"
264
+ doc2 = xdb << "follow"
265
+ doc3 = xdb << "fantastic"
266
+ xdb.search("fo*").should == [doc1, doc2]
267
+ end
159
268
 
160
- it "should delete docs by id" do
161
- xdb = XapianDb.new
162
- doc = xdb << XapianDoc.new("Once upon a time")
163
- xdb.flush
164
- xdb.size.should == 1
165
- xdb.documents.delete(doc.id).should == 1
166
- xdb.flush
167
- xdb.size.should == 0
168
- end
269
+ it "should ignore wildcard searches when the :wildcards option is false" do
270
+ xdb = XapianDb.new
271
+ doc1 = xdb << "fox"
272
+ doc2 = xdb << "follow"
273
+ doc3 = xdb << "fo"
274
+ xdb.search("fo*", :wildcards => false).should == [doc3]
275
+ end
169
276
 
170
- it "should handle being asked to delete docs that don't exist in the db" do
171
- xdb = XapianDb.new
172
- doc = xdb << XapianDoc.new("Once upon a time")
173
- xdb.flush
174
- xdb.documents.delete(100000).should == nil
175
- end
277
+ it "should provide a corrected spelling string by default" do
278
+ pending
279
+ xdb = XapianDb.new(:dir => tmp_dir + 'corrected_spelling', :create => true)
280
+ xdb.rw.add_spelling("house mouse louse")
281
+ xdb << "there is a mouse in this house"
282
+ xdb.flush
283
+ results = xdb.search("moose")
284
+ results.corrected_query.should == "mouse"
285
+ end
176
286
 
177
- it "should add new docs with the given id" do
178
- xdb = XapianDb.new
179
- doc = xdb << XapianDoc.new(:id => 0xbeef, :title => "Once upon a time")
180
- xdb.flush
181
- xdb.documents[0xbeef].id.should == 0xbeef
182
- doc.id.should == 0xbeef
183
- end
287
+ it "should do phrase matching by default when then :default_op option is :phrase"
184
288
 
185
- it "should tokenize strings" do
186
- xdb = XapianDb.new
187
- doc = xdb << XapianDoc.new("once upon a time")
188
- doc.terms.should be_a_kind_of Array
189
- doc.terms.last.should be_a_kind_of Xapian::Term
190
- doc.terms.last.term.should == "upon"
191
- end
289
+ it "should do AND_MAYBE matching by default when the :default_op option is :and_maybe"
192
290
 
193
- it "should tokenize a hash" do
194
- xdb = XapianDb.new
195
- doc = xdb << XapianDoc.new(:title => 'once upon a time')
196
- doc.terms.should be_a_kind_of Array
197
- doc.terms.last.should be_a_kind_of Xapian::Term
198
- doc.terms.last.term.should == "upon"
199
- end
291
+ it "should do PURE_NOT matching by default when the :default_op option is :pure_not"
200
292
 
201
- it "should return a list of XapianDocs with the weight and match set when returning search results" do
202
- xdb = XapianDb.new
203
- xdb << XapianDoc.new(:title => 'once upon a time')
204
- xdb << XapianDoc.new(:title => 'three little pings')
205
- results = xdb.search("pings")
206
- results.should be_a_kind_of Array
207
- results.size.should == 1
208
- results.first.should be_a_kind_of XapianDoc
209
- results.first.match.should be_a_kind_of Xapian::Match
210
- results.first.weight.should be_a_kind_of Float
211
- end
293
+ it "should page results when given the :page and :per_page options" do
294
+ xdb = XapianDb.new
295
+ content = "word"
296
+ 200.times { xdb << XapianDoc.new(content) }
297
+ xdb.size.should == 200
298
+ results = xdb.search(content, :page => 1, :per_page => 12)
299
+ results.first.id.should == 1
300
+ results.size.should == 12
301
+ results = xdb.search(content, :page => 5, :per_page => 18)
302
+ results.first.id.should == 18 * 4 + 1
303
+ results.size.should == 18
304
+ results = xdb.search(content, :page => 100, :per_page => 12)
305
+ results.size.should == 0
306
+ end
212
307
 
213
- it "should support searching with :page and :per_page options" do
214
- xdb = XapianDb.new
215
- content = "word"
216
- 200.times { xdb << XapianDoc.new(content) }
217
- xdb.size.should == 200
218
- results = xdb.search(content, :page => 1, :per_page => 12)
219
- results.first.id.should == 1
220
- results.size.should == 12
221
- results = xdb.search(content, :page => 5, :per_page => 18)
222
- results.first.id.should == 18 * 4 + 1
223
- results.size.should == 18
224
- results = xdb.search(content, :page => 100, :per_page => 12)
225
- results.size.should == 0
226
- end
308
+ it "should limit results when the :limit option is given" do
309
+ xdb = XapianDb.new
310
+ content = "word"
311
+ 30.times { xdb << XapianDoc.new(content) }
312
+ xdb.size.should == 30
313
+ results = xdb.search(content, :limit => 16)
314
+ results.size.should == 16
315
+ end
227
316
 
228
- it "should store no fields by default" do
229
- xdb = XapianDb.new
230
- xdb << XapianDoc.new(:title => "Once upon a time")
231
- xdb.flush
232
- xdb.documents.find(1).fields[:title].should be_nil
233
- end
317
+ it "should return an array that can be used with will_paginate" do
318
+ xdb = XapianDb.new
319
+ content = "word"
320
+ 30.times { xdb << XapianDoc.new(content) }
321
+ xdb.size.should == 30
322
+ results = xdb.search(content, :page => 1, :per_page => 16)
323
+ results.should be_a_kind_of XapianFu::ResultSet
324
+ results.per_page.should == 16
325
+ results.current_page.should == 1
326
+ results.total_entries.should == 30
327
+ results.total_pages.should == 2
328
+ results.previous_page.should == nil
329
+ results.next_page.should == 2
330
+ results.offset.should == 0
331
+ results = xdb.search(content, :page => 2, :per_page => 16)
332
+ results.current_page.should == 2
333
+ results.previous_page.should == 1
334
+ results.next_page.should == nil
335
+ results.offset.should == 16
336
+ end
234
337
 
235
- it "should store fields declared as to be stored" do
236
- xdb = XapianDb.new(:store => :title)
237
- xdb << XapianDoc.new(:title => "Once upon a time", :author => "Jim Jones")
238
- xdb.flush
239
- doc = xdb.documents.find(1)
240
- doc.fields[:title].should == "Once upon a time"
241
- doc.fields[:author].should be_nil
242
- end
243
-
244
- it "should store values declared as to be sortable" do
245
- xdb = XapianDb.new(:sortable => :created_at)
246
- time = Time.now
247
- xdb << XapianDoc.new(:created_at => time.to_i.to_s, :author => "Jim Jones")
248
- xdb.flush
249
- doc = xdb.documents.find(1)
250
- doc.get_value(:created_at).should == time.to_i.to_s
338
+ it "should do searches with and without field names" do
339
+ xdb = XapianDb.new(:fields => [:name, :partner])
340
+ john = xdb << { :name => "John", :partner => "Louisa" }
341
+ katherine = xdb << { :name => "Katherine", :partner => "John" }
342
+ louisa = xdb << { :name => "Louisa", :partner => "John" }
343
+ xdb.search("name:john").should == [john]
344
+ xdb.search("partner:john").should == [katherine, louisa]
345
+ xdb.search("partner:louisa").should == [john]
346
+ xdb.search("louisa").should == [john,louisa]
347
+ xdb.search("john").should == [john,katherine,louisa]
348
+ xdb.search("john -name:john").should == [katherine,louisa]
349
+ end
251
350
  end
252
-
253
- it "should store values declared as to be collapsible" do
254
- xdb = XapianDb.new(:collapsible => :group_id)
255
- xdb << XapianDoc.new(:group_id => "666", :author => "Jim Jones")
256
- xdb.flush
257
- doc = xdb.documents.find(1)
258
- doc.get_value(:group_id).should == "666"
351
+
352
+ describe "add_doc" do
353
+ it "should return a XapianDoc with an id" do
354
+ xdb = XapianDb.new
355
+ doc = XapianDoc.new("once upon a time")
356
+ doc.id.should == nil
357
+ new_doc = xdb << doc
358
+ new_doc.id.should == 1
359
+ end
360
+
361
+ it "should add new docs with the given id" do
362
+ xdb = XapianDb.new
363
+ doc = xdb << XapianDoc.new(:id => 0xbeef, :title => "Once upon a time")
364
+ xdb.documents[0xbeef].id.should == 0xbeef
365
+ doc.id.should == 0xbeef
366
+ end
367
+
368
+ it "should replace docs that already have an id when adding to the db" do
369
+ xdb = XapianDb.new
370
+ doc = xdb << XapianDoc.new("Once upon a time")
371
+ xdb.size.should == 1
372
+ doc.id.should == 1
373
+ updated_doc = xdb << doc
374
+ xdb.size.should == 1
375
+ updated_doc.id.should == doc.id
376
+ end
377
+
378
+ it "should store no fields by default" do
379
+ xdb = XapianDb.new
380
+ xdb << XapianDoc.new(:title => "Once upon a time")
381
+ xdb.flush
382
+ xdb.documents.find(1).values[:title].should be_empty
383
+ end
384
+
385
+ it "should store fields declared to be stored as values" do
386
+ xdb = XapianDb.new(:fields => { :title => { :store => true } })
387
+ xdb << XapianDoc.new(:title => "Once upon a time", :author => "Jim Jones")
388
+ doc = xdb.documents.find(1)
389
+ doc.values[:title].should == "Once upon a time"
390
+ doc.values[:author].should be_empty
391
+ end
392
+
393
+ it "should store values declared as to be sortable" do
394
+ xdb = XapianDb.new(:sortable => :age)
395
+ xdb << XapianDoc.new(:age => "32", :author => "Jim Jones")
396
+ doc = xdb.documents.find(1)
397
+ doc.values.fetch(:age).should == "32"
398
+ end
399
+
400
+ it "should store values declared as to be collapsible" do
401
+ xdb = XapianDb.new(:collapsible => :group_id)
402
+ xdb << XapianDoc.new(:group_id => "666", :author => "Jim Jones")
403
+ doc = xdb.documents.find(1)
404
+ doc.values.fetch(:group_id).should == "666"
405
+ end
406
+
407
+ it "should store data in the database" do
408
+ xdb = XapianDb.new
409
+ xdb << XapianDoc.new({ :text => "once upon a time" }, :data => Marshal::dump({ :thing => 0xdeadbeef }))
410
+ xdb.size.should == 1
411
+ doc = xdb.documents[1]
412
+ Marshal::load(doc.data).should == { :thing => 0xdeadbeef }
413
+ end
259
414
  end
260
415
 
261
416
  describe "search results sort order" do
262
417
  before(:each) do
263
418
  @xdb = XapianDb.new(:sortable => :number)
264
419
  @expected_results = []
265
- @expected_results << (@xdb << XapianDoc.new(:words => "cow dog cat", :number => 1))
266
- @expected_results << (@xdb << XapianDoc.new(:words => "cow dog", :number => 3))
267
- @expected_results << (@xdb << XapianDoc.new(:words => "cow", :number => 2))
420
+ @expected_results << (@xdb << XapianDoc.new(:words => "cow dog", :number => 3, :relevance => 2))
421
+ @expected_results << (@xdb << XapianDoc.new(:words => "cow dog cat", :number => 1, :relevance => 3))
422
+ @expected_results << (@xdb << XapianDoc.new(:words => "cow", :number => 2, :relevance => 1))
268
423
  end
269
-
270
- it "should be by relevance by default" do
271
- results = @xdb.search("cow dog cat")
272
- results.should == @expected_results
424
+
425
+ it "should be by search result weight by default" do
426
+ results = @xdb.search("cow dog cat", :default_op => :or)
427
+ results.should == @expected_results.sort_by { |r| r.fields[:relevance] }.reverse
273
428
  end
274
-
429
+
275
430
  it "should be by the value specified in descending numerical order" do
276
- results = @xdb.search("cow dog cat", :order => :number)
431
+ results = @xdb.search("cow dog cat", :default_op => :or, :order => :number)
277
432
  results.should == @expected_results.sort_by { |r| r.fields[:number] }
278
433
  end
279
-
434
+
280
435
  it "should be reversed when the reverse option is set to true" do
281
- results = @xdb.search("cow dog cat", :order => :number, :reverse => true)
436
+ results = @xdb.search("cow dog cat", :default_op => :or, :order => :number, :reverse => true)
282
437
  results.should == @expected_results.sort_by { |r| r.fields[:number] }.reverse
283
438
  end
439
+
440
+ it "should be by the id when specified and in ascending numerical order by default" do
441
+ results = @xdb.search("cow dog cat", :default_op => :or, :order => :id)
442
+ results.should == @expected_results.sort_by { |r| r.id }
443
+ end
444
+
445
+ it "should be by the id in descending numerical order when specified" do
446
+ results = @xdb.search("cow dog cat", :default_op => :or, :order => :id, :reverse => true)
447
+ results.should == @expected_results.sort_by { |r| r.id }.reverse
448
+ end
449
+
284
450
  end
285
-
286
- it "should collapse results by the value specified by the :collapse option" do
287
- xdb = XapianDb.new(:collapsible => :group)
288
- alpha1 = xdb << XapianDoc.new(:words => "cow dog cat", :group => "alpha")
289
- alpha2 = xdb << XapianDoc.new(:words => "cow dog", :group => "alpha")
290
- beta1 = xdb << XapianDoc.new(:words => "cow", :group => "beta")
291
- results = xdb.search("cow dog cat", :collapse => :group)
292
- results.should == [alpha1, beta1]
451
+
452
+ describe "stemmer" do
453
+ it "should return an english stemmer by default" do
454
+ xdb = XapianDb.new
455
+ xdb.stemmer.call("fishing").should == "fish"
456
+ xdb.stemmer.call("contournait").should == "contournait"
457
+ end
458
+ it "should return a stemmer for the database language" do
459
+ xdb = XapianDb.new(:language => :french)
460
+ xdb.stemmer.call("contournait").should == "contourn"
461
+ xdb.stemmer.call("fishing").should == "fishing"
462
+ end
293
463
  end
294
-
464
+
465
+ describe "stopper" do
466
+ it "should return an english stopper by default" do
467
+ xdb = XapianDb.new
468
+ xdb.stopper.call("and").should == true
469
+ xdb.stopper.call("avec").should == false
470
+ end
471
+ it "should return a stopper for the database language" do
472
+ xdb = XapianDb.new(:language => :french)
473
+ xdb.stopper.call("avec").should == true
474
+ xdb.stopper.call("and").should == false
475
+ end
476
+ end
477
+
478
+ describe "fields" do
479
+ it "should return a hash of field names set as an array with the :fields option using String as the default type" do
480
+ xdb = XapianDb.new(:fields => [:name, :age])
481
+ xdb.fields[:name].should == String
482
+ xdb.fields[:age].should == String
483
+ end
484
+
485
+ it "should return a hash of field names set as a hash with the :fields option" do
486
+ xdb = XapianDb.new(:fields => { :name => String, :gender => String,
487
+ :age => { :type => Fixnum } })
488
+ xdb.fields[:name].should == String
489
+ xdb.fields[:gender].should == String
490
+ xdb.fields[:age].should == Fixnum
491
+ end
492
+
493
+ it "should return an empty array by default" do
494
+ XapianDb.new.fields.keys.should be_empty
495
+ end
496
+
497
+ end
498
+
499
+ describe "stored_values" do
500
+ it "should return an array of field names passed in the :store option" do
501
+ xdb = XapianDb.new(:store => [:name, :title])
502
+ xdb.store_values.should == [:name, :title]
503
+ end
504
+
505
+ it "should return an array of fields defined as storable in the :fields option" do
506
+ xdb = XapianDb.new(:fields => {
507
+ :name => { :store => true },
508
+ :title => { :store => true } })
509
+ xdb.store_values.should include :name
510
+ xdb.store_values.should include :title
511
+ end
512
+
513
+ it "should return an array of fields both passed in the :store option and defined as storable in the :fields option" do
514
+ xdb = XapianDb.new(:fields => {
515
+ :name => { :store => true },
516
+ :title => { :store => true } }, :store => [:name, :gender])
517
+ xdb.store_values.size == 3
518
+ [:gender, :title, :name].each { |f| xdb.store_values.should include f }
519
+ end
520
+ end
521
+
522
+ describe "unindexed_fields" do
523
+ it "should return an empty array by default" do
524
+ xdb = XapianDb.new(:fields => { :name => String, :title => String })
525
+ xdb.unindexed_fields.should == []
526
+ end
527
+
528
+ it "should return fields defined as not indexed in the fields option" do
529
+ xdb = XapianDb.new(:fields => {
530
+ :name => { :type => String, :index => false },
531
+ :title => String })
532
+ xdb.unindexed_fields.should include :name
533
+ xdb.unindexed_fields.should_not include :title
534
+ end
535
+ end
536
+
295
537
  end
538
+