xapit 0.2.7 → 0.3.0
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.
- data/{CHANGELOG → CHANGELOG.rdoc} +7 -2
- data/Gemfile +19 -0
- data/LICENSE +4 -4
- data/README.rdoc +61 -108
- data/Rakefile +11 -10
- data/features/facets.feature +93 -82
- data/features/finding.feature +196 -138
- data/features/indexing.feature +35 -37
- data/features/remote_server.feature +10 -0
- data/features/step_definitions/xapit_steps.rb +53 -25
- data/features/suggestions.feature +20 -14
- data/features/support/env.rb +13 -6
- data/features/support/xapit_helpers.rb +8 -9
- data/lib/generators/xapit/install_generator.rb +14 -0
- data/lib/generators/xapit/templates/xapit.ru +6 -0
- data/lib/generators/xapit/templates/xapit.yml +11 -0
- data/lib/xapit.rb +106 -64
- data/lib/xapit/client/collection.rb +150 -0
- data/lib/xapit/client/facet.rb +11 -0
- data/lib/xapit/client/facet_option.rb +29 -0
- data/lib/xapit/client/index_builder.rb +67 -0
- data/lib/xapit/client/membership.rb +46 -0
- data/lib/xapit/client/model_adapters/abstract_model_adapter.rb +30 -0
- data/lib/xapit/client/model_adapters/active_record_adapter.rb +27 -0
- data/lib/xapit/client/model_adapters/default_model_adapter.rb +7 -0
- data/lib/xapit/client/railtie.rb +18 -0
- data/lib/xapit/client/remote_database.rb +21 -0
- data/lib/xapit/client/tasks.rb +18 -0
- data/lib/xapit/server/app.rb +27 -0
- data/lib/xapit/server/database.rb +47 -0
- data/lib/xapit/server/indexer.rb +138 -0
- data/lib/xapit/server/query.rb +240 -0
- data/spec/fixtures/blankdb/flintlock +0 -0
- data/spec/fixtures/blankdb/iamchert +1 -0
- data/spec/fixtures/blankdb/postlist.DB +0 -0
- data/spec/fixtures/blankdb/postlist.baseA +0 -0
- data/spec/fixtures/blankdb/record.DB +0 -0
- data/spec/fixtures/blankdb/record.baseA +0 -0
- data/spec/fixtures/blankdb/termlist.DB +0 -0
- data/spec/fixtures/blankdb/termlist.baseA +0 -0
- data/spec/fixtures/xapit.ru +13 -0
- data/spec/fixtures/xapit.yml +4 -0
- data/spec/spec_helper.rb +8 -9
- data/spec/support/spec_macros.rb +6 -0
- data/spec/{xapit_member.rb → support/xapit_member.rb} +14 -16
- data/spec/xapit/client/collection_spec.rb +63 -0
- data/spec/xapit/client/facet_option_spec.rb +26 -0
- data/spec/xapit/client/facet_spec.rb +13 -0
- data/spec/xapit/client/index_builder_spec.rb +66 -0
- data/spec/xapit/client/membership_spec.rb +43 -0
- data/spec/xapit/client/model_adapters/active_record_adapter_spec.rb +62 -0
- data/spec/xapit/client/model_adapters/default_model_adapter_spec.rb +7 -0
- data/spec/xapit/client/remote_database_spec.rb +19 -0
- data/spec/xapit/server/app_spec.rb +22 -0
- data/spec/xapit/server/database_spec.rb +37 -0
- data/spec/xapit/server/indexer_spec.rb +82 -0
- data/spec/xapit/server/query_spec.rb +43 -0
- data/spec/xapit/xapit_spec.rb +28 -0
- metadata +124 -93
- data/Manifest +0 -60
- data/features/sorting.feature +0 -29
- data/init.rb +0 -1
- data/install.rb +0 -8
- data/lib/xapit/adapters/abstract_adapter.rb +0 -47
- data/lib/xapit/adapters/active_record_adapter.rb +0 -20
- data/lib/xapit/adapters/data_mapper_adapter.rb +0 -10
- data/lib/xapit/collection.rb +0 -187
- data/lib/xapit/config.rb +0 -84
- data/lib/xapit/facet.rb +0 -67
- data/lib/xapit/facet_blueprint.rb +0 -59
- data/lib/xapit/facet_option.rb +0 -56
- data/lib/xapit/index_blueprint.rb +0 -147
- data/lib/xapit/indexers/abstract_indexer.rb +0 -116
- data/lib/xapit/indexers/classic_indexer.rb +0 -29
- data/lib/xapit/indexers/simple_indexer.rb +0 -38
- data/lib/xapit/membership.rb +0 -137
- data/lib/xapit/query.rb +0 -89
- data/lib/xapit/query_parsers/abstract_query_parser.rb +0 -174
- data/lib/xapit/query_parsers/classic_query_parser.rb +0 -29
- data/lib/xapit/query_parsers/simple_query_parser.rb +0 -75
- data/lib/xapit/rake_tasks.rb +0 -13
- data/rails_generators/xapit/USAGE +0 -13
- data/rails_generators/xapit/templates/setup_xapit.rb +0 -1
- data/rails_generators/xapit/templates/xapit.rake +0 -4
- data/rails_generators/xapit/xapit_generator.rb +0 -20
- data/spec/xapit/adapters/active_record_adapter_spec.rb +0 -31
- data/spec/xapit/adapters/data_mapper_adapter_spec.rb +0 -10
- data/spec/xapit/collection_spec.rb +0 -176
- data/spec/xapit/config_spec.rb +0 -62
- data/spec/xapit/facet_blueprint_spec.rb +0 -29
- data/spec/xapit/facet_option_spec.rb +0 -80
- data/spec/xapit/facet_spec.rb +0 -73
- data/spec/xapit/index_blueprint_spec.rb +0 -112
- data/spec/xapit/indexers/abstract_indexer_spec.rb +0 -111
- data/spec/xapit/indexers/classic_indexer_spec.rb +0 -35
- data/spec/xapit/indexers/simple_indexer_spec.rb +0 -69
- data/spec/xapit/membership_spec.rb +0 -55
- data/spec/xapit/query_parsers/abstract_query_parser_spec.rb +0 -60
- data/spec/xapit/query_parsers/classic_query_parser_spec.rb +0 -20
- data/spec/xapit/query_parsers/simple_query_parser_spec.rb +0 -86
- data/spec/xapit/query_spec.rb +0 -60
- data/tasks/spec.rb +0 -9
- data/tasks/xapit.rake +0 -1
- data/uninstall.rb +0 -5
- data/xapit.gemspec +0 -30
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Xapit::Client::Facet do
|
|
4
|
+
it "sets the name to capitalized attribute" do
|
|
5
|
+
facet = Xapit::Client::Facet.new("building_type", [])
|
|
6
|
+
facet.name.should eq("Building Type")
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "sets the name as symbol to capitalized attribute" do
|
|
10
|
+
facet = Xapit::Client::Facet.new(:building_type, [])
|
|
11
|
+
facet.name.should eq("Building Type")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Xapit::Client::IndexBuilder do
|
|
4
|
+
it "stores text attributes with option" do
|
|
5
|
+
builder = Xapit::Client::IndexBuilder.new
|
|
6
|
+
builder.text :foo, :weight => 3
|
|
7
|
+
builder.text :bar, :blah
|
|
8
|
+
builder.attributes[:foo].should eq(:text => {:weight => 3})
|
|
9
|
+
builder.attributes[:bar].should eq(:text => {})
|
|
10
|
+
builder.attributes[:blah].should eq(:text => {})
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "stores field attribute with option" do
|
|
14
|
+
builder = Xapit::Client::IndexBuilder.new
|
|
15
|
+
builder.field :foo, :weight => 3
|
|
16
|
+
builder.field :bar, :blah
|
|
17
|
+
builder.attributes[:foo].should eq(:field => {:weight => 3})
|
|
18
|
+
builder.attributes[:bar].should eq(:field => {})
|
|
19
|
+
builder.attributes[:blah].should eq(:field => {})
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "stores sortable attribute with option" do
|
|
23
|
+
builder = Xapit::Client::IndexBuilder.new
|
|
24
|
+
builder.sortable :foo, :weight => 3
|
|
25
|
+
builder.sortable :bar, :blah
|
|
26
|
+
builder.attributes[:foo].should eq(:sortable => {:weight => 3})
|
|
27
|
+
builder.attributes[:bar].should eq(:sortable => {})
|
|
28
|
+
builder.attributes[:blah].should eq(:sortable => {})
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "stores facet attribute with options" do
|
|
32
|
+
builder = Xapit::Client::IndexBuilder.new
|
|
33
|
+
builder.facet :foo
|
|
34
|
+
builder.facet :bar, "Zap"
|
|
35
|
+
builder.attributes[:foo].should eq(:facet => {})
|
|
36
|
+
builder.attributes[:bar].should eq(:facet => {:name => "Zap"})
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "fetches facets back" do
|
|
40
|
+
builder = Xapit::Client::IndexBuilder.new
|
|
41
|
+
builder.text :test
|
|
42
|
+
builder.facet :foo
|
|
43
|
+
builder.facet :bar
|
|
44
|
+
builder.facets.should eq([:foo, :bar])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "merges member values with attributes for index data" do
|
|
48
|
+
builder = Xapit::Client::IndexBuilder.new
|
|
49
|
+
builder.text :greeting, :weight => 3
|
|
50
|
+
builder.field :name
|
|
51
|
+
member = XapitMember.new(:greeting => "hello world", :name => "John")
|
|
52
|
+
data = builder.document_data(member)
|
|
53
|
+
data[:id].should eq(member.id)
|
|
54
|
+
data[:class].should eq("XapitMember")
|
|
55
|
+
data[:attributes].should eq(:greeting => {:value => "hello world", :text => {:weight => 3}}, :name => {:value => "John", :field => {}})
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "indexes an object by adding it to the current database" do
|
|
59
|
+
load_xapit_database
|
|
60
|
+
Xapit.database.xapian_database.doccount.should eq(0)
|
|
61
|
+
builder = Xapit::Client::IndexBuilder.new
|
|
62
|
+
member = XapitMember.new(:greeting => "Hello world")
|
|
63
|
+
builder.add_document(member)
|
|
64
|
+
Xapit.database.xapian_database.doccount.should eq(1)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Xapit::Client::Membership do
|
|
4
|
+
before(:each) do
|
|
5
|
+
@member_class = Class.new
|
|
6
|
+
@member_class.send(:include, Xapit::Client::Membership)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "does not define search class method when xapit isn't called" do
|
|
10
|
+
@member_class.should_not respond_to(:search)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "has a xapit method which makes an index builder" do
|
|
14
|
+
@member_class.xapit { text :foo }
|
|
15
|
+
@member_class.xapit_index_builder.attributes.keys.should eq([:foo])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "returns collection with query on search" do
|
|
19
|
+
@member_class.xapit { text :foo }
|
|
20
|
+
@member_class.search("hello").clauses.should eq([{:in_classes => [@member_class]}, {:search => "hello"}])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "returns collection with no search query" do
|
|
24
|
+
@member_class.xapit { text :foo }
|
|
25
|
+
@member_class.search.clauses.should eq([{:in_classes => [@member_class]}])
|
|
26
|
+
@member_class.search("").clauses.should eq([{:in_classes => [@member_class]}])
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "supports xapit_search instead of just search" do
|
|
30
|
+
@member_class.xapit { text :foo }
|
|
31
|
+
@member_class.xapit_search.clauses.should eq([{:in_classes => [@member_class]}])
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "includes facets" do
|
|
35
|
+
@member_class.xapit { facet :foo }
|
|
36
|
+
@member_class.search.clauses.should eq([{:in_classes => [@member_class]}, {:include_facets => [:foo]}])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "has a model_adapter" do
|
|
40
|
+
@member_class.xapit { } # load up the xapit methods
|
|
41
|
+
@member_class.xapit_model_adapter.should be_kind_of(Xapit::Client::DefaultModelAdapter)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
|
|
2
|
+
require "spec_helper"
|
|
3
|
+
ActiveRecord::Base.send(:include, Xapit::Client::Membership) # normally done in Railtie
|
|
4
|
+
|
|
5
|
+
RSpec.configure do |config|
|
|
6
|
+
config.extend WithModel
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
|
10
|
+
|
|
11
|
+
describe Xapit::Client::ActiveRecordAdapter do
|
|
12
|
+
with_model :article do
|
|
13
|
+
table do |t|
|
|
14
|
+
t.string "name"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
before(:each) do
|
|
19
|
+
load_xapit_database
|
|
20
|
+
Article.xapit { text :name }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "is only for active record classes" do
|
|
24
|
+
Xapit::Client::ActiveRecordAdapter.should_not be_for_class(Object)
|
|
25
|
+
Xapit::Client::ActiveRecordAdapter.should be_for_class(Article)
|
|
26
|
+
Xapit::Client::AbstractModelAdapter.adapter_class(Article).should == Xapit::Client::ActiveRecordAdapter
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "creates document when saved" do
|
|
30
|
+
article = Article.create!(:name => "Foo Bar")
|
|
31
|
+
Article.search("Foo Bar").records.should eq([article])
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "deletes a document when removed" do
|
|
35
|
+
article = Article.create!(:name => "Foo Bar")
|
|
36
|
+
article.destroy
|
|
37
|
+
Article.search("Foo Bar").records.should eq([])
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "update a document when changed" do
|
|
41
|
+
article = Article.create!(:name => "Foo Bar")
|
|
42
|
+
article.update_attribute(:name, "Hello World")
|
|
43
|
+
Article.search("Foo Bar").records.should eq([])
|
|
44
|
+
Article.search("Hello World").records.should eq([article])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "does not index records while disabled" do
|
|
48
|
+
Xapit.config[:enabled] = false
|
|
49
|
+
Article.create!(:name => "Foo Bar")
|
|
50
|
+
Xapit.config[:enabled] = true
|
|
51
|
+
Article.search("Foo Bar").records.should eq([])
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "reindexes all records for a model" do
|
|
55
|
+
Xapit.config[:enabled] = false
|
|
56
|
+
article = Article.create!(:name => "Foo Bar")
|
|
57
|
+
Xapit.config[:enabled] = true
|
|
58
|
+
Xapit.index(Article)
|
|
59
|
+
Article.search("Foo Bar").records.should eq([article])
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Xapit::Client::RemoteDatabase do
|
|
4
|
+
before(:each) do
|
|
5
|
+
@database = Xapit::Client::RemoteDatabase.new("http://localhost:1234")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
Xapit::Server::Database::COMMANDS.each do |command|
|
|
9
|
+
it "passes #{command} to remote server using Net::HTTP" do
|
|
10
|
+
http = Object.new
|
|
11
|
+
response = Object.new
|
|
12
|
+
uri = URI.parse("http://localhost:1234/xapit/#{command}")
|
|
13
|
+
Net::HTTP.should_receive(:start).with(uri.host, uri.port).and_yield(http)
|
|
14
|
+
http.should_receive(:request_post).with(uri.path, {:send => "request"}.to_json).and_return(response)
|
|
15
|
+
response.should_receive(:body).and_return({"receive" => "response"}.to_json)
|
|
16
|
+
@database.send(command, :send => "request").should eq(:receive => "response")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Xapit::Server::App do
|
|
4
|
+
before(:each) do
|
|
5
|
+
@app = Xapit::Server::App.new
|
|
6
|
+
@request = Rack::MockRequest.new(@app)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
Xapit::Server::Database::COMMANDS.each do |command|
|
|
10
|
+
it "passes #{command} to database and returns response in JSON" do
|
|
11
|
+
Xapit.database.stub(command.to_sym).with(:foo => "bar") { {:some => "result"} }
|
|
12
|
+
response = @request.post("/xapit/#{command}", :params => {"foo" => "bar"}.to_json)
|
|
13
|
+
response.status.should eq(200)
|
|
14
|
+
response.body.should eq({:some => "result"}.to_json)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "responds with 404 when unknown url" do
|
|
19
|
+
response = @request.post("/xapit/foo")
|
|
20
|
+
response.status.should eq(404)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Xapit::Server::Database do
|
|
4
|
+
before(:each) do
|
|
5
|
+
load_xapit_database
|
|
6
|
+
@database = Xapit.database
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "has a xapian database" do
|
|
10
|
+
@database.xapian_database.should be_kind_of(Xapian::WritableDatabase)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "adds a document to the database" do
|
|
14
|
+
@database.xapian_database.doccount.should eq(0)
|
|
15
|
+
@database.add_document(:attributes => {:greeting => {:value => "hello world", :text => {}}})
|
|
16
|
+
@database.xapian_database.doccount.should eq(1)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "queries the database for results" do
|
|
20
|
+
@database.add_document(:attributes => {:greeting => {:value => "hello world", :text => {}}}, :id => 123, :class => "Greeting")
|
|
21
|
+
@database.query([{:search => "hello"}])[:records].should eq([{:class => "Greeting", :id => "123", :relevance => 100}])
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "removes a document from the database" do
|
|
25
|
+
@database.xapian_database.doccount.should eq(0)
|
|
26
|
+
@database.add_document(:id => 123, :class => "Greeting")
|
|
27
|
+
@database.xapian_database.doccount.should eq(1)
|
|
28
|
+
@database.remove_document(:id => 123, :class => "Greeting")
|
|
29
|
+
@database.xapian_database.doccount.should eq(0)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "updates a document in the database" do
|
|
33
|
+
@database.add_document(:attributes => {:greeting => {:value => "hello world", :text => {}}}, :id => 123, :class => "Greeting")
|
|
34
|
+
@database.update_document(:attributes => {:greeting => {:value => "aloha", :text => {}}}, :id => 123, :class => "Greeting")
|
|
35
|
+
@database.query([{:search => "aloha"}])[:records].should eq([{:class => "Greeting", :id => "123", :relevance => 100}])
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Xapit::Server::Indexer do
|
|
4
|
+
before(:each) do
|
|
5
|
+
load_xapit_database
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "generates a xapian document with terms and values" do
|
|
9
|
+
indexer = Xapit::Server::Indexer.new(:attributes => {:greeting => {:value => "hello world", :text => {}}, :name => {:value => "John", :field => {}}})
|
|
10
|
+
document = indexer.document
|
|
11
|
+
document.should be_kind_of(Xapian::Document)
|
|
12
|
+
document.terms.map(&:term).should include(*%w[hello world])
|
|
13
|
+
document.values.map(&:value).should eq([Xapit.serialize_value("John")])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "generates a xapian document with text weight data" do
|
|
17
|
+
indexer = Xapit::Server::Indexer.new(:attributes => {:greeting => {:value => "hello", :text => {:weight => 3}}})
|
|
18
|
+
indexer.document.terms.map(&:wdf).should include(3)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "stores sortable attributes as serialized values" do
|
|
22
|
+
time = Time.now
|
|
23
|
+
indexer = Xapit::Server::Indexer.new(:attributes => {:greeting => {:value => time, :sortable => {}}})
|
|
24
|
+
document = indexer.document
|
|
25
|
+
document.values.map(&:value).should eq([Xapit.serialize_value(time)])
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "adds the id and class to xapian document data" do
|
|
29
|
+
indexer = Xapit::Server::Indexer.new(:class => "Foo", :id => "123")
|
|
30
|
+
document = indexer.document
|
|
31
|
+
document.should be_kind_of(Xapian::Document)
|
|
32
|
+
document.data.should eq("Foo-123")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "includes class/id in terms list" do
|
|
36
|
+
indexer = Xapit::Server::Indexer.new(:class => "Foo", :id => "123")
|
|
37
|
+
indexer.terms.should include(["CFoo", 1], ["QFoo-123", 1])
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "includes fields in terms list" do
|
|
41
|
+
indexer = Xapit::Server::Indexer.new(:attributes => {:greeting => {:value => "Hello", :field => {}}})
|
|
42
|
+
indexer.terms.should include(["Xgreeting-hello", 1])
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "adds facets to values and terms" do
|
|
46
|
+
indexer = Xapit::Server::Indexer.new(:attributes => {:greeting => {:value => ["Hello", "Hey"], :facet => {}}})
|
|
47
|
+
document = indexer.document
|
|
48
|
+
document.values.map(&:value).should eq(["Hello\3Hey"])
|
|
49
|
+
indexer.terms.should include(["F#{Xapit.facet_identifier(:greeting, "Hello")}", 1])
|
|
50
|
+
indexer.terms.should include(["F#{Xapit.facet_identifier(:greeting, "Hey")}", 1])
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "indexes array values separately" do
|
|
54
|
+
indexer = Xapit::Server::Indexer.new(:attributes => {:greeting => {:value => ["Hello", "world"], :field => {}}})
|
|
55
|
+
indexer.terms.should include(["Xgreeting-hello", 1], ["Xgreeting-world", 1])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "includes text attributes in terms list" do
|
|
59
|
+
indexer = Xapit::Server::Indexer.new(:attributes => {:greeting => {:value => "hello world", :text => {}}})
|
|
60
|
+
indexer.terms.should include(["hello", 1], ["world", 1])
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "handles odd text attributes correctly" do
|
|
64
|
+
indexer = Xapit::Server::Indexer.new(:attributes => {:greeting => {:value => [6, nil, ""], :text => {}}})
|
|
65
|
+
indexer.terms.should include(["6", 1])
|
|
66
|
+
indexer.terms.should_not include(["", 1])
|
|
67
|
+
indexer.terms.should_not include([nil, 1])
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "handles odd field attributes correctly" do
|
|
71
|
+
# TODO add date handling
|
|
72
|
+
time = Time.now
|
|
73
|
+
indexer = Xapit::Server::Indexer.new(:attributes => {:greeting => {:value => [6, nil, time], :field => {}}})
|
|
74
|
+
indexer.terms.should include(["Xgreeting-6", 1], ["Xgreeting-", 1], ["Xgreeting-#{time.to_i}", 1])
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "includes field and sortable values" do
|
|
78
|
+
indexer = Xapit::Server::Indexer.new(:attributes => {:greeting => {:value => "Hello", :field => {}, :sortable => {}}})
|
|
79
|
+
indexer.values[Xapit.value_index(:field, "greeting")].should eq(Xapit.serialize_value("Hello"))
|
|
80
|
+
indexer.values[Xapit.value_index(:sortable, "greeting")].should eq(Xapit.serialize_value("Hello"))
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Xapit::Server::Query do
|
|
4
|
+
before(:each) do
|
|
5
|
+
load_xapit_database
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "fetches results matching a simple search term" do
|
|
9
|
+
Xapit.database.add_document(:attributes => {:greeting => {:value => "hello world", :text => {}}}, :id => 123, :class => "Greeting")
|
|
10
|
+
query = Xapit::Server::Query.new([{:search => "hello"}])
|
|
11
|
+
query.records.should eq([{:class => "Greeting", :id => "123", :relevance => 100}])
|
|
12
|
+
query = Xapit::Server::Query.new([{:search => "matchnothing"}])
|
|
13
|
+
query.records.should eq([])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "fetches results matching a simple where clause" do
|
|
17
|
+
Xapit.database.add_document(:attributes => {:priority => {:value => "3", :field => {}}}, :id => 123, :class => "Greeting")
|
|
18
|
+
query = Xapit::Server::Query.new([{:where => {:priority => 3}}])
|
|
19
|
+
query.records.should eq([{:class => "Greeting", :id => "123", :relevance => 100}])
|
|
20
|
+
query = Xapit::Server::Query.new([{:where => {:priority => 4}}])
|
|
21
|
+
query.records.should eq([])
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "fetches facets when told to include them" do
|
|
25
|
+
Xapit.database.add_document(:attributes => {:priority => {:value => "3", :facet => {}}}, :id => 123, :class => "Greeting")
|
|
26
|
+
query = Xapit::Server::Query.new([{:include_facets => [:priority]}])
|
|
27
|
+
query.facets.should eq(:priority => [{:value => "3", :count => 1}])
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "fetches results matching a given facet" do
|
|
31
|
+
Xapit.database.add_document(:attributes => {:priority => {:value => "3", :field => {}, :facet => {}}}, :id => 123, :class => "Greeting")
|
|
32
|
+
query = Xapit::Server::Query.new([{:with_facets => [Xapit.facet_identifier(:priority, "3")]}])
|
|
33
|
+
query.records.should eq([{:class => "Greeting", :id => "123", :relevance => 100}])
|
|
34
|
+
query = Xapit::Server::Query.new([{:with_facets => [Xapit.facet_identifier(:priority, "4")]}])
|
|
35
|
+
query.records.should eq([])
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "fetches results containing applied facets" do
|
|
39
|
+
Xapit.database.add_document(:attributes => {:priority => {:value => "3", :facet => {}}}, :id => 123, :class => "Greeting")
|
|
40
|
+
query = Xapit::Server::Query.new([{:with_facets => [Xapit.facet_identifier(:priority, "3")]}])
|
|
41
|
+
query.applied_facet_options.should eq([{:id => Xapit.facet_identifier(:priority, "3"), :name => "priority", :value => "3"}])
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Xapit do
|
|
4
|
+
it "has default config settings" do
|
|
5
|
+
Xapit.config[:enabled].should eq(true)
|
|
6
|
+
Xapit.config[:spelling].should eq(true)
|
|
7
|
+
Xapit.config[:stemming].should eq("english")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "can be enabled" do
|
|
11
|
+
Xapit.config[:enabled] = false
|
|
12
|
+
Xapit.enable
|
|
13
|
+
Xapit.config[:enabled].should eq(true)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "loads and reloads a configuration file via load_config" do
|
|
17
|
+
Xapit.load_config("spec/fixtures/xapit.yml", "development")
|
|
18
|
+
Xapit.config[:database_path].should eq("development_database")
|
|
19
|
+
Xapit.config[:database_path] = "foo"
|
|
20
|
+
Xapit.reload
|
|
21
|
+
Xapit.config[:database_path].should eq("development_database")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "raises an exception when accessing the database while disabled" do
|
|
25
|
+
Xapit.config[:enabled] = false
|
|
26
|
+
lambda { Xapit.database }.should raise_exception(Xapit::Disabled)
|
|
27
|
+
end
|
|
28
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: xapit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
|
|
4
|
+
hash: 19
|
|
5
|
+
prerelease:
|
|
6
|
+
segments:
|
|
7
|
+
- 0
|
|
8
|
+
- 3
|
|
9
|
+
- 0
|
|
10
|
+
version: 0.3.0
|
|
5
11
|
platform: ruby
|
|
6
12
|
authors:
|
|
7
13
|
- Ryan Bates
|
|
@@ -9,135 +15,160 @@ autorequire:
|
|
|
9
15
|
bindir: bin
|
|
10
16
|
cert_chain: []
|
|
11
17
|
|
|
12
|
-
date:
|
|
18
|
+
date: 2011-08-17 00:00:00 -07:00
|
|
13
19
|
default_executable:
|
|
14
|
-
dependencies:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
dependencies:
|
|
21
|
+
- !ruby/object:Gem::Dependency
|
|
22
|
+
name: rack
|
|
23
|
+
prerelease: false
|
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ~>
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
hash: 27
|
|
30
|
+
segments:
|
|
31
|
+
- 1
|
|
32
|
+
- 2
|
|
33
|
+
- 2
|
|
34
|
+
version: 1.2.2
|
|
35
|
+
type: :runtime
|
|
36
|
+
version_requirements: *id001
|
|
37
|
+
- !ruby/object:Gem::Dependency
|
|
38
|
+
name: rspec
|
|
39
|
+
prerelease: false
|
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ~>
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
hash: 27
|
|
46
|
+
segments:
|
|
47
|
+
- 2
|
|
48
|
+
- 5
|
|
49
|
+
- 0
|
|
50
|
+
version: 2.5.0
|
|
51
|
+
type: :development
|
|
52
|
+
version_requirements: *id002
|
|
53
|
+
- !ruby/object:Gem::Dependency
|
|
54
|
+
name: cucumber
|
|
55
|
+
prerelease: false
|
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
|
57
|
+
none: false
|
|
58
|
+
requirements:
|
|
59
|
+
- - ~>
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
hash: 51
|
|
62
|
+
segments:
|
|
63
|
+
- 0
|
|
64
|
+
- 10
|
|
65
|
+
- 2
|
|
66
|
+
version: 0.10.2
|
|
67
|
+
type: :development
|
|
68
|
+
version_requirements: *id003
|
|
69
|
+
description: Ruby library for interacting with Xapian. Includes full text search, faceted options, spelling suggestions, and more.
|
|
70
|
+
email: ryan@railscasts.com
|
|
18
71
|
executables: []
|
|
19
72
|
|
|
20
73
|
extensions: []
|
|
21
74
|
|
|
22
|
-
extra_rdoc_files:
|
|
23
|
-
|
|
24
|
-
- lib/xapit/adapters/abstract_adapter.rb
|
|
25
|
-
- lib/xapit/adapters/active_record_adapter.rb
|
|
26
|
-
- lib/xapit/adapters/data_mapper_adapter.rb
|
|
27
|
-
- lib/xapit/collection.rb
|
|
28
|
-
- lib/xapit/config.rb
|
|
29
|
-
- lib/xapit/facet.rb
|
|
30
|
-
- lib/xapit/facet_blueprint.rb
|
|
31
|
-
- lib/xapit/facet_option.rb
|
|
32
|
-
- lib/xapit/index_blueprint.rb
|
|
33
|
-
- lib/xapit/indexers/abstract_indexer.rb
|
|
34
|
-
- lib/xapit/indexers/classic_indexer.rb
|
|
35
|
-
- lib/xapit/indexers/simple_indexer.rb
|
|
36
|
-
- lib/xapit/membership.rb
|
|
37
|
-
- lib/xapit/query.rb
|
|
38
|
-
- lib/xapit/query_parsers/abstract_query_parser.rb
|
|
39
|
-
- lib/xapit/query_parsers/classic_query_parser.rb
|
|
40
|
-
- lib/xapit/query_parsers/simple_query_parser.rb
|
|
41
|
-
- lib/xapit/rake_tasks.rb
|
|
42
|
-
- lib/xapit.rb
|
|
43
|
-
- LICENSE
|
|
44
|
-
- README.rdoc
|
|
45
|
-
- tasks/spec.rb
|
|
46
|
-
- tasks/xapit.rake
|
|
75
|
+
extra_rdoc_files: []
|
|
76
|
+
|
|
47
77
|
files:
|
|
48
|
-
-
|
|
78
|
+
- lib/generators/xapit/install_generator.rb
|
|
79
|
+
- lib/generators/xapit/templates/xapit.ru
|
|
80
|
+
- lib/generators/xapit/templates/xapit.yml
|
|
81
|
+
- lib/xapit/client/collection.rb
|
|
82
|
+
- lib/xapit/client/facet.rb
|
|
83
|
+
- lib/xapit/client/facet_option.rb
|
|
84
|
+
- lib/xapit/client/index_builder.rb
|
|
85
|
+
- lib/xapit/client/membership.rb
|
|
86
|
+
- lib/xapit/client/model_adapters/abstract_model_adapter.rb
|
|
87
|
+
- lib/xapit/client/model_adapters/active_record_adapter.rb
|
|
88
|
+
- lib/xapit/client/model_adapters/default_model_adapter.rb
|
|
89
|
+
- lib/xapit/client/railtie.rb
|
|
90
|
+
- lib/xapit/client/remote_database.rb
|
|
91
|
+
- lib/xapit/client/tasks.rb
|
|
92
|
+
- lib/xapit/server/app.rb
|
|
93
|
+
- lib/xapit/server/database.rb
|
|
94
|
+
- lib/xapit/server/indexer.rb
|
|
95
|
+
- lib/xapit/server/query.rb
|
|
96
|
+
- lib/xapit.rb
|
|
97
|
+
- spec/fixtures/blankdb/flintlock
|
|
98
|
+
- spec/fixtures/blankdb/iamchert
|
|
99
|
+
- spec/fixtures/blankdb/postlist.baseA
|
|
100
|
+
- spec/fixtures/blankdb/postlist.DB
|
|
101
|
+
- spec/fixtures/blankdb/record.baseA
|
|
102
|
+
- spec/fixtures/blankdb/record.DB
|
|
103
|
+
- spec/fixtures/blankdb/termlist.baseA
|
|
104
|
+
- spec/fixtures/blankdb/termlist.DB
|
|
105
|
+
- spec/fixtures/xapit.ru
|
|
106
|
+
- spec/fixtures/xapit.yml
|
|
107
|
+
- spec/spec_helper.rb
|
|
108
|
+
- spec/support/spec_macros.rb
|
|
109
|
+
- spec/support/xapit_member.rb
|
|
110
|
+
- spec/xapit/client/collection_spec.rb
|
|
111
|
+
- spec/xapit/client/facet_option_spec.rb
|
|
112
|
+
- spec/xapit/client/facet_spec.rb
|
|
113
|
+
- spec/xapit/client/index_builder_spec.rb
|
|
114
|
+
- spec/xapit/client/membership_spec.rb
|
|
115
|
+
- spec/xapit/client/model_adapters/active_record_adapter_spec.rb
|
|
116
|
+
- spec/xapit/client/model_adapters/default_model_adapter_spec.rb
|
|
117
|
+
- spec/xapit/client/remote_database_spec.rb
|
|
118
|
+
- spec/xapit/server/app_spec.rb
|
|
119
|
+
- spec/xapit/server/database_spec.rb
|
|
120
|
+
- spec/xapit/server/indexer_spec.rb
|
|
121
|
+
- spec/xapit/server/query_spec.rb
|
|
122
|
+
- spec/xapit/xapit_spec.rb
|
|
49
123
|
- features/facets.feature
|
|
50
124
|
- features/finding.feature
|
|
51
125
|
- features/indexing.feature
|
|
52
|
-
- features/
|
|
126
|
+
- features/remote_server.feature
|
|
53
127
|
- features/step_definitions/common_steps.rb
|
|
54
128
|
- features/step_definitions/xapit_steps.rb
|
|
55
129
|
- features/suggestions.feature
|
|
56
130
|
- features/support/env.rb
|
|
57
131
|
- features/support/xapit_helpers.rb
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
- lib/xapit/adapters/abstract_adapter.rb
|
|
61
|
-
- lib/xapit/adapters/active_record_adapter.rb
|
|
62
|
-
- lib/xapit/adapters/data_mapper_adapter.rb
|
|
63
|
-
- lib/xapit/collection.rb
|
|
64
|
-
- lib/xapit/config.rb
|
|
65
|
-
- lib/xapit/facet.rb
|
|
66
|
-
- lib/xapit/facet_blueprint.rb
|
|
67
|
-
- lib/xapit/facet_option.rb
|
|
68
|
-
- lib/xapit/index_blueprint.rb
|
|
69
|
-
- lib/xapit/indexers/abstract_indexer.rb
|
|
70
|
-
- lib/xapit/indexers/classic_indexer.rb
|
|
71
|
-
- lib/xapit/indexers/simple_indexer.rb
|
|
72
|
-
- lib/xapit/membership.rb
|
|
73
|
-
- lib/xapit/query.rb
|
|
74
|
-
- lib/xapit/query_parsers/abstract_query_parser.rb
|
|
75
|
-
- lib/xapit/query_parsers/classic_query_parser.rb
|
|
76
|
-
- lib/xapit/query_parsers/simple_query_parser.rb
|
|
77
|
-
- lib/xapit/rake_tasks.rb
|
|
78
|
-
- lib/xapit.rb
|
|
132
|
+
- CHANGELOG.rdoc
|
|
133
|
+
- Gemfile
|
|
79
134
|
- LICENSE
|
|
80
|
-
- Manifest
|
|
81
|
-
- rails_generators/xapit/templates/setup_xapit.rb
|
|
82
|
-
- rails_generators/xapit/templates/xapit.rake
|
|
83
|
-
- rails_generators/xapit/USAGE
|
|
84
|
-
- rails_generators/xapit/xapit_generator.rb
|
|
85
135
|
- Rakefile
|
|
86
136
|
- README.rdoc
|
|
87
|
-
- spec/spec_helper.rb
|
|
88
|
-
- spec/xapit/adapters/active_record_adapter_spec.rb
|
|
89
|
-
- spec/xapit/adapters/data_mapper_adapter_spec.rb
|
|
90
|
-
- spec/xapit/collection_spec.rb
|
|
91
|
-
- spec/xapit/config_spec.rb
|
|
92
|
-
- spec/xapit/facet_blueprint_spec.rb
|
|
93
|
-
- spec/xapit/facet_option_spec.rb
|
|
94
|
-
- spec/xapit/facet_spec.rb
|
|
95
|
-
- spec/xapit/index_blueprint_spec.rb
|
|
96
|
-
- spec/xapit/indexers/abstract_indexer_spec.rb
|
|
97
|
-
- spec/xapit/indexers/classic_indexer_spec.rb
|
|
98
|
-
- spec/xapit/indexers/simple_indexer_spec.rb
|
|
99
|
-
- spec/xapit/membership_spec.rb
|
|
100
|
-
- spec/xapit/query_parsers/abstract_query_parser_spec.rb
|
|
101
|
-
- spec/xapit/query_parsers/classic_query_parser_spec.rb
|
|
102
|
-
- spec/xapit/query_parsers/simple_query_parser_spec.rb
|
|
103
|
-
- spec/xapit/query_spec.rb
|
|
104
|
-
- spec/xapit_member.rb
|
|
105
|
-
- tasks/spec.rb
|
|
106
|
-
- tasks/xapit.rake
|
|
107
|
-
- uninstall.rb
|
|
108
|
-
- xapit.gemspec
|
|
109
137
|
has_rdoc: true
|
|
110
138
|
homepage: http://github.com/ryanb/xapit
|
|
111
139
|
licenses: []
|
|
112
140
|
|
|
113
141
|
post_install_message:
|
|
114
|
-
rdoc_options:
|
|
115
|
-
|
|
116
|
-
- --inline-source
|
|
117
|
-
- --title
|
|
118
|
-
- Xapit
|
|
119
|
-
- --main
|
|
120
|
-
- README.rdoc
|
|
142
|
+
rdoc_options: []
|
|
143
|
+
|
|
121
144
|
require_paths:
|
|
122
145
|
- lib
|
|
123
146
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
|
+
none: false
|
|
124
148
|
requirements:
|
|
125
149
|
- - ">="
|
|
126
150
|
- !ruby/object:Gem::Version
|
|
151
|
+
hash: 3
|
|
152
|
+
segments:
|
|
153
|
+
- 0
|
|
127
154
|
version: "0"
|
|
128
|
-
version:
|
|
129
155
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
|
+
none: false
|
|
130
157
|
requirements:
|
|
131
158
|
- - ">="
|
|
132
159
|
- !ruby/object:Gem::Version
|
|
133
|
-
|
|
134
|
-
|
|
160
|
+
hash: 19
|
|
161
|
+
segments:
|
|
162
|
+
- 1
|
|
163
|
+
- 3
|
|
164
|
+
- 4
|
|
165
|
+
version: 1.3.4
|
|
135
166
|
requirements: []
|
|
136
167
|
|
|
137
168
|
rubyforge_project: xapit
|
|
138
|
-
rubygems_version: 1.
|
|
169
|
+
rubygems_version: 1.6.2
|
|
139
170
|
signing_key:
|
|
140
171
|
specification_version: 3
|
|
141
|
-
summary: Ruby library for interacting with Xapian
|
|
172
|
+
summary: Ruby library for interacting with the Xapian full text search engine.
|
|
142
173
|
test_files: []
|
|
143
174
|
|