xapit 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/Manifest +178 -0
- data/README.rdoc +183 -0
- data/Rakefile +15 -0
- data/TODO +23 -0
- data/features/facets.feature +51 -0
- data/features/finding.feature +119 -0
- data/features/indexing.feature +41 -0
- data/features/step_definitions/common_steps.rb +7 -0
- data/features/step_definitions/xapit_steps.rb +117 -0
- data/features/support/env.rb +7 -0
- data/features/support/xapit_helpers.rb +27 -0
- data/init.rb +3 -0
- data/install.rb +9 -0
- data/lib/xapit.rb +39 -0
- data/lib/xapit/collection.rb +165 -0
- data/lib/xapit/config.rb +83 -0
- data/lib/xapit/facet.rb +59 -0
- data/lib/xapit/facet_blueprint.rb +59 -0
- data/lib/xapit/facet_option.rb +56 -0
- data/lib/xapit/index_blueprint.rb +117 -0
- data/lib/xapit/indexers/abstract_indexer.rb +101 -0
- data/lib/xapit/indexers/classic_indexer.rb +27 -0
- data/lib/xapit/indexers/simple_indexer.rb +31 -0
- data/lib/xapit/membership.rb +103 -0
- data/lib/xapit/query.rb +62 -0
- data/lib/xapit/query_parsers/abstract_query_parser.rb +115 -0
- data/lib/xapit/query_parsers/classic_query_parser.rb +19 -0
- data/lib/xapit/query_parsers/simple_query_parser.rb +75 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/tmp/xapdb/flintlock +0 -0
- data/spec/tmp/xapdb/iamflint +0 -0
- data/spec/tmp/xapdb/postlist.DB +0 -0
- data/spec/tmp/xapdb/postlist.baseA +0 -0
- data/spec/tmp/xapdb/postlist.baseB +0 -0
- data/spec/tmp/xapdb/record.DB +0 -0
- data/spec/tmp/xapdb/record.baseA +0 -0
- data/spec/tmp/xapdb/record.baseB +0 -0
- data/spec/tmp/xapdb/spelling.DB +0 -0
- data/spec/tmp/xapdb/spelling.baseA +0 -0
- data/spec/tmp/xapdb/spelling.baseB +0 -0
- data/spec/tmp/xapdb/termlist.DB +0 -0
- data/spec/tmp/xapdb/termlist.baseA +0 -0
- data/spec/tmp/xapdb/termlist.baseB +0 -0
- data/spec/tmp/xapian_db/flintlock +0 -0
- data/spec/tmp/xapian_db/iamflint +0 -0
- data/spec/tmp/xapian_db/postlist.DB +0 -0
- data/spec/tmp/xapian_db/postlist.baseA +0 -0
- data/spec/tmp/xapian_db/record.DB +0 -0
- data/spec/tmp/xapian_db/record.baseA +0 -0
- data/spec/tmp/xapian_db/termlist.DB +0 -0
- data/spec/tmp/xapian_db/termlist.baseA +0 -0
- data/spec/tmp/xapiandab/flintlock +0 -0
- data/spec/tmp/xapiandab/iamflint +0 -0
- data/spec/tmp/xapiandab/postlist.DB +0 -0
- data/spec/tmp/xapiandab/postlist.baseA +0 -0
- data/spec/tmp/xapiandab/postlist.baseB +0 -0
- data/spec/tmp/xapiandab/record.DB +0 -0
- data/spec/tmp/xapiandab/record.baseA +0 -0
- data/spec/tmp/xapiandab/record.baseB +0 -0
- data/spec/tmp/xapiandab/spelling.DB +0 -0
- data/spec/tmp/xapiandab/spelling.baseA +0 -0
- data/spec/tmp/xapiandab/spelling.baseB +0 -0
- data/spec/tmp/xapiandab/termlist.DB +0 -0
- data/spec/tmp/xapiandab/termlist.baseA +0 -0
- data/spec/tmp/xapiandab/termlist.baseB +0 -0
- data/spec/tmp/xapiandatab/flintlock +0 -0
- data/spec/tmp/xapiandatab/iamflint +0 -0
- data/spec/tmp/xapiandatab/postlist.DB +0 -0
- data/spec/tmp/xapiandatab/postlist.baseA +0 -0
- data/spec/tmp/xapiandatab/postlist.baseB +0 -0
- data/spec/tmp/xapiandatab/record.DB +0 -0
- data/spec/tmp/xapiandatab/record.baseA +0 -0
- data/spec/tmp/xapiandatab/record.baseB +0 -0
- data/spec/tmp/xapiandatab/spelling.DB +0 -0
- data/spec/tmp/xapiandatab/spelling.baseA +0 -0
- data/spec/tmp/xapiandatab/spelling.baseB +0 -0
- data/spec/tmp/xapiandatab/termlist.DB +0 -0
- data/spec/tmp/xapiandatab/termlist.baseA +0 -0
- data/spec/tmp/xapiandatab/termlist.baseB +0 -0
- data/spec/tmp/xapiandataba/flintlock +0 -0
- data/spec/tmp/xapiandataba/iamflint +0 -0
- data/spec/tmp/xapiandataba/postlist.DB +0 -0
- data/spec/tmp/xapiandataba/postlist.baseA +0 -0
- data/spec/tmp/xapiandataba/postlist.baseB +0 -0
- data/spec/tmp/xapiandataba/record.DB +0 -0
- data/spec/tmp/xapiandataba/record.baseA +0 -0
- data/spec/tmp/xapiandataba/record.baseB +0 -0
- data/spec/tmp/xapiandataba/spelling.DB +0 -0
- data/spec/tmp/xapiandataba/spelling.baseA +0 -0
- data/spec/tmp/xapiandataba/spelling.baseB +0 -0
- data/spec/tmp/xapiandataba/termlist.DB +0 -0
- data/spec/tmp/xapiandataba/termlist.baseA +0 -0
- data/spec/tmp/xapiandataba/termlist.baseB +0 -0
- data/spec/tmp/xapiandatabas/flintlock +0 -0
- data/spec/tmp/xapiandatabas/iamflint +0 -0
- data/spec/tmp/xapiandatabas/postlist.DB +0 -0
- data/spec/tmp/xapiandatabas/postlist.baseA +0 -0
- data/spec/tmp/xapiandatabas/record.DB +0 -0
- data/spec/tmp/xapiandatabas/record.baseA +0 -0
- data/spec/tmp/xapiandatabas/termlist.DB +0 -0
- data/spec/tmp/xapiandatabas/termlist.baseA +0 -0
- data/spec/tmp/xapiandatb/flintlock +0 -0
- data/spec/tmp/xapiandatb/iamflint +0 -0
- data/spec/tmp/xapiandatb/postlist.DB +0 -0
- data/spec/tmp/xapiandatb/postlist.baseA +0 -0
- data/spec/tmp/xapiandatb/postlist.baseB +0 -0
- data/spec/tmp/xapiandatb/record.DB +0 -0
- data/spec/tmp/xapiandatb/record.baseA +0 -0
- data/spec/tmp/xapiandatb/record.baseB +0 -0
- data/spec/tmp/xapiandatb/spelling.DB +0 -0
- data/spec/tmp/xapiandatb/spelling.baseA +0 -0
- data/spec/tmp/xapiandatb/spelling.baseB +0 -0
- data/spec/tmp/xapiandatb/termlist.DB +0 -0
- data/spec/tmp/xapiandatb/termlist.baseA +0 -0
- data/spec/tmp/xapiandatb/termlist.baseB +0 -0
- data/spec/tmp/xapiandbase/flintlock +0 -0
- data/spec/tmp/xapiandbase/iamflint +0 -0
- data/spec/tmp/xapiandbase/postlist.DB +0 -0
- data/spec/tmp/xapiandbase/postlist.baseA +0 -0
- data/spec/tmp/xapiandbase/postlist.baseB +0 -0
- data/spec/tmp/xapiandbase/record.DB +0 -0
- data/spec/tmp/xapiandbase/record.baseA +0 -0
- data/spec/tmp/xapiandbase/record.baseB +0 -0
- data/spec/tmp/xapiandbase/spelling.DB +0 -0
- data/spec/tmp/xapiandbase/spelling.baseA +0 -0
- data/spec/tmp/xapiandbase/spelling.baseB +0 -0
- data/spec/tmp/xapiandbase/termlist.DB +0 -0
- data/spec/tmp/xapiandbase/termlist.baseA +0 -0
- data/spec/tmp/xapiandbase/termlist.baseB +0 -0
- data/spec/xapit/collection_spec.rb +153 -0
- data/spec/xapit/config_spec.rb +48 -0
- data/spec/xapit/facet_blueprint_spec.rb +29 -0
- data/spec/xapit/facet_option_spec.rb +80 -0
- data/spec/xapit/facet_spec.rb +73 -0
- data/spec/xapit/index_blueprint_spec.rb +60 -0
- data/spec/xapit/indexers/abstract_indexer_spec.rb +74 -0
- data/spec/xapit/indexers/classic_indexer_spec.rb +26 -0
- data/spec/xapit/indexers/simple_indexer_spec.rb +53 -0
- data/spec/xapit/membership_spec.rb +39 -0
- data/spec/xapit/query_parsers/abstract_query_parser_spec.rb +23 -0
- data/spec/xapit/query_parsers/classic_query_parser_spec.rb +15 -0
- data/spec/xapit/query_parsers/simple_query_parser_spec.rb +86 -0
- data/spec/xapit/query_spec.rb +41 -0
- data/spec/xapit_member.rb +32 -0
- data/tasks/spec.rb +9 -0
- data/tasks/xapit.rake +9 -0
- data/tmp/xapiandatabase/flintlock +0 -0
- data/tmp/xapiandatabase/iamflint +0 -0
- data/tmp/xapiandatabase/postlist.DB +0 -0
- data/tmp/xapiandatabase/postlist.baseA +0 -0
- data/tmp/xapiandatabase/postlist.baseB +0 -0
- data/tmp/xapiandatabase/record.DB +0 -0
- data/tmp/xapiandatabase/record.baseA +0 -0
- data/tmp/xapiandatabase/record.baseB +0 -0
- data/tmp/xapiandatabase/spelling.DB +0 -0
- data/tmp/xapiandatabase/spelling.baseA +0 -0
- data/tmp/xapiandatabase/spelling.baseB +0 -0
- data/tmp/xapiandatabase/termlist.DB +0 -0
- data/tmp/xapiandatabase/termlist.baseA +0 -0
- data/tmp/xapiandatabase/termlist.baseB +0 -0
- data/tmp/xapiandatabase/value.baseB +0 -0
- data/tmp/xapiandb/flintlock +0 -0
- data/tmp/xapiandb/iamflint +0 -0
- data/tmp/xapiandb/postlist.DB +0 -0
- data/tmp/xapiandb/postlist.baseA +0 -0
- data/tmp/xapiandb/postlist.baseB +0 -0
- data/tmp/xapiandb/record.DB +0 -0
- data/tmp/xapiandb/record.baseA +0 -0
- data/tmp/xapiandb/record.baseB +0 -0
- data/tmp/xapiandb/spelling.DB +0 -0
- data/tmp/xapiandb/spelling.baseA +0 -0
- data/tmp/xapiandb/spelling.baseB +0 -0
- data/tmp/xapiandb/termlist.DB +0 -0
- data/tmp/xapiandb/termlist.baseA +0 -0
- data/tmp/xapiandb/termlist.baseB +0 -0
- data/tmp/xapiandb/value.baseB +0 -0
- data/uninstall.rb +5 -0
- data/xapit.gemspec +30 -0
- metadata +257 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Xapit::Facet do
|
4
|
+
describe "with database" do
|
5
|
+
before(:each) do
|
6
|
+
XapitMember.xapit do |index|
|
7
|
+
index.facet :visible
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "indexed" do
|
12
|
+
before(:each) do
|
13
|
+
@visible1 = XapitMember.new(:visible => true)
|
14
|
+
@visible2 = XapitMember.new(:visible => true)
|
15
|
+
@invisible = XapitMember.new(:visible => false)
|
16
|
+
Xapit.index_all
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "facet from empty search" do
|
20
|
+
before(:each) do
|
21
|
+
@facet = XapitMember.search("").facets.first
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should have the name of 'Visible'" do
|
25
|
+
@facet.name.should == 'Visible'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have true and false options" do
|
29
|
+
@facet.options.map(&:name).sort.should == %w[false true]
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should have record count" do
|
33
|
+
@facet.options.detect { |o| o.name == 'true' }.count.should == 2
|
34
|
+
@facet.options.detect { |o| o.name == 'false' }.count.should == 1
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should have identifier for options" do
|
38
|
+
blueprint = Xapit::FacetBlueprint.new(XapitMember, 0, :visible)
|
39
|
+
@facet.options.detect { |o| o.name == 'true' }.identifier.should == blueprint.identifiers_for(@visible1).first
|
40
|
+
@facet.options.detect { |o| o.name == 'false' }.identifier.should == blueprint.identifiers_for(@invisible).first
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should have matching identifiers" do
|
44
|
+
blueprint = Xapit::FacetBlueprint.new(XapitMember, 0, :visible)
|
45
|
+
hash = { blueprint.identifiers_for(@visible1).first => 2, blueprint.identifiers_for(@invisible).first => 1 }
|
46
|
+
@facet.matching_identifiers.should == hash
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not include matching identifiers that are current" do
|
50
|
+
blueprint = Xapit::FacetBlueprint.new(XapitMember, 0, :visible)
|
51
|
+
@facet.existing_facet_identifiers = blueprint.identifiers_for(@visible1)
|
52
|
+
@facet.matching_identifiers.should == { blueprint.identifiers_for(@invisible).first => 1 }
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return identifier on to_param" do
|
56
|
+
blueprint = Xapit::FacetBlueprint.new(XapitMember, 0, :visible)
|
57
|
+
@facet.options.detect { |o| o.name == 'true' }.to_param.should == blueprint.identifiers_for(@visible1).first
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should sort options in alphabetical order" do
|
61
|
+
@facet.options.first.name.should == 'false'
|
62
|
+
@facet.options.last.name.should == 'true'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should not list facets if only one option is found" do
|
67
|
+
blueprint = Xapit::FacetBlueprint.new(XapitMember, 0, :visible)
|
68
|
+
facets = XapitMember.search("", :facets => blueprint.identifiers_for(@visible1)).facets
|
69
|
+
facets.should be_empty
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Xapit::IndexBlueprint do
|
4
|
+
before(:each) do
|
5
|
+
@index = Xapit::IndexBlueprint.new(XapitMember)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should remember text attributes" do
|
9
|
+
@index.text(:foo)
|
10
|
+
@index.text(:bar, :blah)
|
11
|
+
@index.text(:custom) { |t| t*t }
|
12
|
+
@index.text_attributes.keys.should include(:foo, :bar, :blah, :custom)
|
13
|
+
@index.text_attributes[:foo][:proc].should be_nil
|
14
|
+
@index.text_attributes[:custom][:proc].should be_kind_of(Proc)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should remember field attributes" do
|
18
|
+
@index.field(:foo)
|
19
|
+
@index.field(:bar, :blah)
|
20
|
+
@index.field_attributes.should include(:foo, :bar, :blah)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should remember facets" do
|
24
|
+
@index.facet(:foo)
|
25
|
+
@index.facet(:bar, "Baz")
|
26
|
+
@index.facets.map(&:name).should == ["Foo", "Baz"]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should remember sortable attributes" do
|
30
|
+
@index.sortable(:foo)
|
31
|
+
@index.sortable(:bar, :blah)
|
32
|
+
@index.sortable_attributes.should include(:foo, :bar, :blah)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should have a sortable position offset by facets" do
|
36
|
+
@index.facet(:foo)
|
37
|
+
@index.facet(:test)
|
38
|
+
@index.sortable(:bar, :blah)
|
39
|
+
@index.sortable_position_for(:blah).should == 3
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should index member document into database" do
|
43
|
+
XapitMember.new
|
44
|
+
@index.index_all
|
45
|
+
Xapit::Config.writable_database.doccount.should >= 1
|
46
|
+
Xapit::Config.writable_database.flush
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should remember all blueprints and index each of them" do
|
50
|
+
stub(Xapit::Config.writable_database).add_document
|
51
|
+
mock(@index).index_all
|
52
|
+
Xapit::IndexBlueprint.index_all
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should pass in extra arguments to each method" do
|
56
|
+
index = Xapit::IndexBlueprint.new(Object, :foo, :bar => :blah)
|
57
|
+
mock(Object).find_each(:foo, :bar => :blah)
|
58
|
+
index.index_all
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Xapit::AbstractIndexer do
|
4
|
+
before(:each) do
|
5
|
+
XapitMember.xapit { } # to ensure methods are included
|
6
|
+
@index = Xapit::IndexBlueprint.new(XapitMember)
|
7
|
+
@indexer = Xapit::SimpleIndexer.new(@index)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should map field to term with 'X' prefix" do
|
11
|
+
member = Object.new
|
12
|
+
stub(member).category { "Water" }
|
13
|
+
@index.field(:category)
|
14
|
+
@indexer.field_terms(member).should == %w[Xcategory-water]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should add terms separately when array is returned" do
|
18
|
+
member = Object.new
|
19
|
+
stub(member).category { ["Water", "Liquid"] }
|
20
|
+
@index.field(:category)
|
21
|
+
@indexer.field_terms(member).should == %w[Xcategory-water Xcategory-liquid]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should have base terms with class name and id" do
|
25
|
+
member = Object.new
|
26
|
+
stub(member).id { 123 }
|
27
|
+
@indexer.base_terms(member).should == %w[CObject QObject-123]
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should add terms, values and options for facets" do
|
31
|
+
Xapit::Config.writable_database # force xapit to use a writable database at the beginning
|
32
|
+
stub(XapitMember).xapit_index_blueprint { @index }
|
33
|
+
member = XapitMember.new(:foo => ["ABC", "DEF"])
|
34
|
+
ids = Xapit::FacetBlueprint.new(XapitMember, 0, :foo).identifiers_for(member)
|
35
|
+
@index.facet(:foo)
|
36
|
+
@indexer.facet_terms(member).should == ids.map { |id| "F#{id}" }
|
37
|
+
@indexer.values(member).should == [ids.join('-')]
|
38
|
+
@indexer.save_facet_options_for(member)
|
39
|
+
ids.map { |id| Xapit::FacetOption.find(id).name }.should == ["ABC", "DEF"]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should add values for sortable fields" do
|
43
|
+
member = Object.new
|
44
|
+
stub(member).name { "Foo" }
|
45
|
+
@index.sortable(:name)
|
46
|
+
@indexer.values(member).should == ["foo"]
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should add terms and values to xapian document" do
|
50
|
+
member = Object.new
|
51
|
+
stub(member).id { 123 }
|
52
|
+
stub(@indexer).values.returns(%w[value list])
|
53
|
+
stub(@indexer).other_terms { %w[term list] }
|
54
|
+
doc = @indexer.document_for(member)
|
55
|
+
doc.should be_kind_of(Xapian::Document)
|
56
|
+
doc.data.should == "Object-123"
|
57
|
+
doc.values.map(&:value).sort.should == %w[value list].sort
|
58
|
+
doc.terms.map(&:term).sort.should == %w[term list].sort
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should convert time to integer before saving as field term" do
|
62
|
+
member = Object.new
|
63
|
+
stub(member).created_at { Time.now }
|
64
|
+
@index.field(:created_at)
|
65
|
+
@indexer.field_terms(member).should == ["Xcreated_at-#{member.created_at.to_i}"]
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should convert date to time then integer before saving as field term" do
|
69
|
+
member = Object.new
|
70
|
+
stub(member).created_on { Date.today }
|
71
|
+
@index.field(:created_on)
|
72
|
+
@indexer.field_terms(member).should == ["Xcreated_on-#{member.created_on.to_time.to_i}"]
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Xapit::ClassicIndexer do
|
4
|
+
before(:each) do
|
5
|
+
@index = Xapit::IndexBlueprint.new(XapitMember)
|
6
|
+
@indexer = Xapit::ClassicIndexer.new(@index)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should add text terms to document when indexing attributes" do
|
10
|
+
member = Object.new
|
11
|
+
stub(member).name { "jumping high" }
|
12
|
+
@index.text(:name)
|
13
|
+
document = Xapian::Document.new
|
14
|
+
@indexer.index_text_attributes(member, document)
|
15
|
+
document.terms.map(&:term).sort.should == %w[Zjump Zhigh jumping high].sort
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should use given block to generate text terms" do
|
19
|
+
member = Object.new
|
20
|
+
stub(member).name { "foobar" }
|
21
|
+
@index.text(:name) { |t| [t.length] }
|
22
|
+
document = Xapian::Document.new
|
23
|
+
@indexer.index_text_attributes(member, document)
|
24
|
+
document.terms.map(&:term).sort.should == %w[6].sort
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Xapit::SimpleIndexer do
|
4
|
+
before(:each) do
|
5
|
+
@index = Xapit::IndexBlueprint.new(XapitMember)
|
6
|
+
@indexer = Xapit::SimpleIndexer.new(@index)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return terms for text attributes" do
|
10
|
+
member = Object.new
|
11
|
+
stub(member).description { "This is a test" }
|
12
|
+
@index.text(:description)
|
13
|
+
@indexer.terms_for_attribute_without_stemming(member, :description, {}).should == %w[this is a test]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return text term with stemming added" do
|
17
|
+
member = Object.new
|
18
|
+
stub(member).description { "jumping high" }
|
19
|
+
@index.text(:description)
|
20
|
+
@indexer.terms_for_attribute(member, :description, {}).should == %w[jumping Zjump high Zhigh]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should convert attribute to string when converting text to terms" do
|
24
|
+
member = Object.new
|
25
|
+
stub(member).num { 123 }
|
26
|
+
@index.text(:num)
|
27
|
+
@indexer.terms_for_attribute_without_stemming(member, :num, {}).should == %w[123]
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should add text terms to document when indexing attributes" do
|
31
|
+
@index.text(:description)
|
32
|
+
stub(@indexer).terms_for_attribute { %w[term list] }
|
33
|
+
document = Xapian::Document.new
|
34
|
+
@indexer.index_text_attributes(nil, document)
|
35
|
+
document.terms.map(&:term).sort.should == %w[term list].sort
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should use given block to generate text terms" do
|
39
|
+
member = Object.new
|
40
|
+
stub(member).name { "foobar" }
|
41
|
+
proc = lambda { |t| [t.length] }
|
42
|
+
@indexer.terms_for_attribute_without_stemming(member, :name, { :proc => proc }).should == ["6"]
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should increment term frequency by weight option" do
|
46
|
+
member = Object.new
|
47
|
+
stub(member).description { "This is a test" }
|
48
|
+
@index.text(:description, :weight => 10)
|
49
|
+
document = Xapian::Document.new
|
50
|
+
@indexer.index_text_attributes(member, document)
|
51
|
+
document.terms.first.wdf.should == 10
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
class OtherMember
|
4
|
+
include Xapit::Membership
|
5
|
+
end
|
6
|
+
|
7
|
+
describe XapitMember do
|
8
|
+
it "should have xapit method" do
|
9
|
+
OtherMember.should respond_to(:xapit)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should not respond to xapit_index_blueprint if xapit isn't called" do
|
13
|
+
OtherMember.should_not respond_to(:xapit_index_blueprint)
|
14
|
+
OtherMember.should_not respond_to(:search)
|
15
|
+
OtherMember.new.should_not respond_to(:search_similar)
|
16
|
+
OtherMember.new.should_not respond_to(:xapit_relevance)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "with description indexed" do
|
20
|
+
before(:each) do
|
21
|
+
XapitMember.xapit do |index|
|
22
|
+
index.text :description
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should have xapit index blueprint" do
|
27
|
+
XapitMember.xapit_index_blueprint.should be_kind_of(Xapit::IndexBlueprint)
|
28
|
+
end
|
29
|
+
it "should return collection from search" do
|
30
|
+
XapitMember.search("foo").class.should == Xapit::Collection
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should store xapit_relevance" do
|
34
|
+
member = XapitMember.new
|
35
|
+
member.xapit_relevance = 123
|
36
|
+
member.xapit_relevance.should == 123
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Xapit::AbstractQueryParser do
|
4
|
+
before(:each) do
|
5
|
+
end
|
6
|
+
|
7
|
+
it "parse conditions hash into terms" do
|
8
|
+
parser = Xapit::AbstractQueryParser.new(:conditions => { :foo => 'bar', 'hello' => :world })
|
9
|
+
parser.condition_terms.sort.should == ["Xfoo-bar", "Xhello-world"].sort
|
10
|
+
end
|
11
|
+
|
12
|
+
it "convert time into integer before placing in condition term" do
|
13
|
+
time = Time.now
|
14
|
+
parser = Xapit::AbstractQueryParser.new(:conditions => { :time => time })
|
15
|
+
parser.condition_terms.should == ["Xtime-#{time.to_i}"]
|
16
|
+
end
|
17
|
+
|
18
|
+
it "convert date into time then integer before placing in condition term" do
|
19
|
+
date = Date.today
|
20
|
+
parser = Xapit::AbstractQueryParser.new(:conditions => { :date => date })
|
21
|
+
parser.condition_terms.should == ["Xdate-#{date.to_time.to_i}"]
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Xapit::ClassicQueryParser do
|
4
|
+
before(:each) do
|
5
|
+
@parser = Xapit::ClassicQueryParser.new(nil, nil)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should have an initial xapian parser with stemming and default operator support" do
|
9
|
+
expected = Xapian::QueryParser.new
|
10
|
+
expected.stemmer = Xapian::Stem.new("english")
|
11
|
+
expected.stemming_strategy = Xapian::QueryParser::STEM_SOME
|
12
|
+
expected.default_op = Xapian::Query::OP_AND
|
13
|
+
@parser.xapian_query_from_text("foo bar").description.should == expected.parse_query("foo bar").description
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Xapit::SimpleQueryParser do
|
4
|
+
describe "with stemming" do
|
5
|
+
it "should include stemmed variation for single word" do
|
6
|
+
Xapit::SimpleQueryParser.new(nil, "jumping").parsed.should == "Zjump"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should include stemmed variations for multiple words" do
|
10
|
+
Xapit::SimpleQueryParser.new(nil, "jumping high").parsed.should == [:and, "Zjump", "Zhigh"]
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should add stemmed variation for 'not' option" do
|
14
|
+
Xapit::SimpleQueryParser.new(nil, "jumping not high").parsed.should == [:and, "Zjump", [:not, "Zhigh"]]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "without stemming" do
|
19
|
+
before(:each) do
|
20
|
+
Xapit::Config.options[:stemming] = false
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should parse nothing for simple string" do
|
24
|
+
Xapit::SimpleQueryParser.new(nil, "foobar").parsed.should == "foobar"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should parse empty string as blank string" do
|
28
|
+
Xapit::SimpleQueryParser.new(nil, "").parsed.should == ""
|
29
|
+
Xapit::SimpleQueryParser.new(nil, " \t ").parsed.should == ""
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should parse white space as AND" do
|
33
|
+
Xapit::SimpleQueryParser.new(nil, "foo bar").parsed.should == [:and, "foo", "bar"]
|
34
|
+
Xapit::SimpleQueryParser.new(nil, "\t foo \t bar ").parsed.should == [:and, "foo", "bar"]
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should parse simple 'or' query" do
|
38
|
+
Xapit::SimpleQueryParser.new(nil, "foo or bar").parsed.should == [:or, "foo", "bar"]
|
39
|
+
Xapit::SimpleQueryParser.new(nil, " foo or\t bar \t ").parsed.should == [:or, "foo", "bar"]
|
40
|
+
Xapit::SimpleQueryParser.new(nil, "foo OR bar").parsed.should == [:or, "foo", "bar"]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should parse 'and' within 'or' giving 'or' presedence" do
|
44
|
+
Xapit::SimpleQueryParser.new(nil, "foo or bar blah").parsed.should == [:or, "foo", [:and, "bar", "blah"]]
|
45
|
+
Xapit::SimpleQueryParser.new(nil, "foo bar or blah").parsed.should == [:or, [:and, "foo", "bar"], "blah"]
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should parse simple 'not' query" do
|
49
|
+
Xapit::SimpleQueryParser.new(nil, "foo not bar").parsed.should == [:and, "foo", [:not, "bar"]]
|
50
|
+
Xapit::SimpleQueryParser.new(nil, "foo NOT bar blah").parsed.should == [:and, "foo", [:not, "bar"], "blah"]
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should convert simple query to xapian query" do
|
54
|
+
Xapit::SimpleQueryParser.new(nil, "foo bar").xapian_query.description.should == Xapian::Query.new(Xapian::Query::OP_AND, "foo", "bar").description
|
55
|
+
Xapit::SimpleQueryParser.new(nil, "foo OR bar").xapian_query.description.should == Xapian::Query.new(Xapian::Query::OP_OR, "foo", "bar").description
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should convert deep query to xapian query" do
|
59
|
+
query = Xapian::Query.new(Xapian::Query::OP_OR,
|
60
|
+
Xapian::Query.new(Xapian::Query::OP_OR, ["foo"]),
|
61
|
+
Xapian::Query.new(Xapian::Query::OP_AND, ["bar", "blah"])
|
62
|
+
)
|
63
|
+
Xapit::SimpleQueryParser.new(nil, "foo or bar blah").xapian_query.description.should == query.description
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should convert multi-deep query to xapian query" do
|
67
|
+
query = Xapian::Query.new(Xapian::Query::OP_OR,
|
68
|
+
Xapian::Query.new(Xapian::Query::OP_AND, ["foo", "bar"]),
|
69
|
+
Xapian::Query.new(Xapian::Query::OP_AND, ["test", "blah"])
|
70
|
+
)
|
71
|
+
Xapit::SimpleQueryParser.new(nil, "foo bar or test blah").xapian_query.description.should == query.description
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should convert single word query to xapian query" do
|
75
|
+
Xapit::SimpleQueryParser.new(nil, "foo").xapian_query.description.should == Xapian::Query.new(Xapian::Query::OP_AND, ["foo"]).description
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should convert negative query to xapian query" do
|
79
|
+
query = Xapian::Query.new(Xapian::Query::OP_AND_NOT,
|
80
|
+
Xapian::Query.new(Xapian::Query::OP_AND, ["foo"]),
|
81
|
+
Xapian::Query.new(Xapian::Query::OP_AND, ["bar"])
|
82
|
+
)
|
83
|
+
Xapit::SimpleQueryParser.new(nil, "foo not bar").xapian_query.description.should == query.description
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|