xapit 0.2.7 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/{CHANGELOG → CHANGELOG.rdoc} +7 -2
  2. data/Gemfile +19 -0
  3. data/LICENSE +4 -4
  4. data/README.rdoc +61 -108
  5. data/Rakefile +11 -10
  6. data/features/facets.feature +93 -82
  7. data/features/finding.feature +196 -138
  8. data/features/indexing.feature +35 -37
  9. data/features/remote_server.feature +10 -0
  10. data/features/step_definitions/xapit_steps.rb +53 -25
  11. data/features/suggestions.feature +20 -14
  12. data/features/support/env.rb +13 -6
  13. data/features/support/xapit_helpers.rb +8 -9
  14. data/lib/generators/xapit/install_generator.rb +14 -0
  15. data/lib/generators/xapit/templates/xapit.ru +6 -0
  16. data/lib/generators/xapit/templates/xapit.yml +11 -0
  17. data/lib/xapit.rb +106 -64
  18. data/lib/xapit/client/collection.rb +150 -0
  19. data/lib/xapit/client/facet.rb +11 -0
  20. data/lib/xapit/client/facet_option.rb +29 -0
  21. data/lib/xapit/client/index_builder.rb +67 -0
  22. data/lib/xapit/client/membership.rb +46 -0
  23. data/lib/xapit/client/model_adapters/abstract_model_adapter.rb +30 -0
  24. data/lib/xapit/client/model_adapters/active_record_adapter.rb +27 -0
  25. data/lib/xapit/client/model_adapters/default_model_adapter.rb +7 -0
  26. data/lib/xapit/client/railtie.rb +18 -0
  27. data/lib/xapit/client/remote_database.rb +21 -0
  28. data/lib/xapit/client/tasks.rb +18 -0
  29. data/lib/xapit/server/app.rb +27 -0
  30. data/lib/xapit/server/database.rb +47 -0
  31. data/lib/xapit/server/indexer.rb +138 -0
  32. data/lib/xapit/server/query.rb +240 -0
  33. data/spec/fixtures/blankdb/flintlock +0 -0
  34. data/spec/fixtures/blankdb/iamchert +1 -0
  35. data/spec/fixtures/blankdb/postlist.DB +0 -0
  36. data/spec/fixtures/blankdb/postlist.baseA +0 -0
  37. data/spec/fixtures/blankdb/record.DB +0 -0
  38. data/spec/fixtures/blankdb/record.baseA +0 -0
  39. data/spec/fixtures/blankdb/termlist.DB +0 -0
  40. data/spec/fixtures/blankdb/termlist.baseA +0 -0
  41. data/spec/fixtures/xapit.ru +13 -0
  42. data/spec/fixtures/xapit.yml +4 -0
  43. data/spec/spec_helper.rb +8 -9
  44. data/spec/support/spec_macros.rb +6 -0
  45. data/spec/{xapit_member.rb → support/xapit_member.rb} +14 -16
  46. data/spec/xapit/client/collection_spec.rb +63 -0
  47. data/spec/xapit/client/facet_option_spec.rb +26 -0
  48. data/spec/xapit/client/facet_spec.rb +13 -0
  49. data/spec/xapit/client/index_builder_spec.rb +66 -0
  50. data/spec/xapit/client/membership_spec.rb +43 -0
  51. data/spec/xapit/client/model_adapters/active_record_adapter_spec.rb +62 -0
  52. data/spec/xapit/client/model_adapters/default_model_adapter_spec.rb +7 -0
  53. data/spec/xapit/client/remote_database_spec.rb +19 -0
  54. data/spec/xapit/server/app_spec.rb +22 -0
  55. data/spec/xapit/server/database_spec.rb +37 -0
  56. data/spec/xapit/server/indexer_spec.rb +82 -0
  57. data/spec/xapit/server/query_spec.rb +43 -0
  58. data/spec/xapit/xapit_spec.rb +28 -0
  59. metadata +124 -93
  60. data/Manifest +0 -60
  61. data/features/sorting.feature +0 -29
  62. data/init.rb +0 -1
  63. data/install.rb +0 -8
  64. data/lib/xapit/adapters/abstract_adapter.rb +0 -47
  65. data/lib/xapit/adapters/active_record_adapter.rb +0 -20
  66. data/lib/xapit/adapters/data_mapper_adapter.rb +0 -10
  67. data/lib/xapit/collection.rb +0 -187
  68. data/lib/xapit/config.rb +0 -84
  69. data/lib/xapit/facet.rb +0 -67
  70. data/lib/xapit/facet_blueprint.rb +0 -59
  71. data/lib/xapit/facet_option.rb +0 -56
  72. data/lib/xapit/index_blueprint.rb +0 -147
  73. data/lib/xapit/indexers/abstract_indexer.rb +0 -116
  74. data/lib/xapit/indexers/classic_indexer.rb +0 -29
  75. data/lib/xapit/indexers/simple_indexer.rb +0 -38
  76. data/lib/xapit/membership.rb +0 -137
  77. data/lib/xapit/query.rb +0 -89
  78. data/lib/xapit/query_parsers/abstract_query_parser.rb +0 -174
  79. data/lib/xapit/query_parsers/classic_query_parser.rb +0 -29
  80. data/lib/xapit/query_parsers/simple_query_parser.rb +0 -75
  81. data/lib/xapit/rake_tasks.rb +0 -13
  82. data/rails_generators/xapit/USAGE +0 -13
  83. data/rails_generators/xapit/templates/setup_xapit.rb +0 -1
  84. data/rails_generators/xapit/templates/xapit.rake +0 -4
  85. data/rails_generators/xapit/xapit_generator.rb +0 -20
  86. data/spec/xapit/adapters/active_record_adapter_spec.rb +0 -31
  87. data/spec/xapit/adapters/data_mapper_adapter_spec.rb +0 -10
  88. data/spec/xapit/collection_spec.rb +0 -176
  89. data/spec/xapit/config_spec.rb +0 -62
  90. data/spec/xapit/facet_blueprint_spec.rb +0 -29
  91. data/spec/xapit/facet_option_spec.rb +0 -80
  92. data/spec/xapit/facet_spec.rb +0 -73
  93. data/spec/xapit/index_blueprint_spec.rb +0 -112
  94. data/spec/xapit/indexers/abstract_indexer_spec.rb +0 -111
  95. data/spec/xapit/indexers/classic_indexer_spec.rb +0 -35
  96. data/spec/xapit/indexers/simple_indexer_spec.rb +0 -69
  97. data/spec/xapit/membership_spec.rb +0 -55
  98. data/spec/xapit/query_parsers/abstract_query_parser_spec.rb +0 -60
  99. data/spec/xapit/query_parsers/classic_query_parser_spec.rb +0 -20
  100. data/spec/xapit/query_parsers/simple_query_parser_spec.rb +0 -86
  101. data/spec/xapit/query_spec.rb +0 -60
  102. data/tasks/spec.rb +0 -9
  103. data/tasks/xapit.rake +0 -1
  104. data/uninstall.rb +0 -5
  105. data/xapit.gemspec +0 -30
@@ -1,3 +1,8 @@
1
+ *0.3.0* August 17, 2011
2
+
3
+ * Complete rewrite
4
+
5
+
1
6
  *0.2.7* (July 7th, 2009)
2
7
 
3
8
  * support punctuation in wildcard matching
@@ -5,14 +10,14 @@
5
10
  * fixing nested search calls
6
11
 
7
12
  * chain a separate search with "or_search" to find records matching either one
8
-
13
+
9
14
  search("foo").or_search(:conditions => { :priority => 3 })
10
15
 
11
16
 
12
17
  *0.2.6* (July 6th, 2009)
13
18
 
14
19
  * search for field conditions in query string, only supported by ClassicQueryParser
15
-
20
+
16
21
  search("age:17")
17
22
 
18
23
  * check if xapian database exists before removing
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source "http://rubygems.org"
2
+
3
+ case ENV["MODEL_ADAPTER"]
4
+ when nil, "active_record"
5
+ gem "sqlite3"
6
+ gem "activerecord", :require => "active_record"
7
+ gem "with_model"
8
+ when "data_mapper"
9
+ gem "dm-core", "~> 1.0.2"
10
+ gem "dm-sqlite-adapter", "~> 1.0.2"
11
+ gem "dm-migrations", "~> 1.0.2"
12
+ when "mongoid"
13
+ gem "bson_ext", "~> 1.1"
14
+ gem "mongoid", "~> 2.0.0.beta.20"
15
+ else
16
+ raise "Unknown model adapter: #{ENV["MODEL_ADAPTER"]}"
17
+ end
18
+
19
+ gemspec
data/LICENSE CHANGED
@@ -1,5 +1,5 @@
1
- Copyright (c) 2008 Ryan Bates
2
-
1
+ Copyright (c) 2011 Ryan Bates
2
+
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
5
5
  "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@ without limitation the rights to use, copy, modify, merge, publish,
7
7
  distribute, sublicense, and/or sell copies of the Software, and to
8
8
  permit persons to whom the Software is furnished to do so, subject to
9
9
  the following conditions:
10
-
10
+
11
11
  The above copyright notice and this permission notice shall be
12
12
  included in all copies or substantial portions of the Software.
13
-
13
+
14
14
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -1,119 +1,71 @@
1
1
  = Xapit
2
2
 
3
- Xapit (pronounced "zap it") is a high level interface for working with a Xapian database.
4
-
5
- Note: This project is early in development and the API is subject to change.
3
+ Xapit (pronounced "zap it") is a Ruby gem for doing full text searching through {Xapian}[http://xapian.org/]. This project was recently rewritten and is not yet ready for production. Please try it out and let me know if there are any issues.
6
4
 
7
5
 
8
6
  == Install
9
7
 
10
- If you haven't already, first install Xapian and the Xapian Bindings for Ruby.
11
- http://wiki.github.com/Overbryd/acts_as_xapian/installation
8
+ First, install Xapian with the Ruby bindings. The easiest way is through {Homebrew}[http://mxcl.github.com/homebrew/].
9
+
10
+ brew install xapian --ruby
12
11
 
13
- To install as a Rails plugin, run this command.
12
+ Note: this is tied to the current version of Ruby you have installed. If you use RVM be certain you're in the correct version. See {Installing Xapian}[https://github.com/ryanb/xapit/wiki/Xapian-Installation] for other methods.
14
13
 
15
- script/plugin install git://github.com/ryanb/xapit.git
14
+ Next add Xapit to your Gemfile and run the +bundle+ command.
16
15
 
17
- Or to install as a gem in Rails first add this to config/environment.rb.
16
+ gem "xapit"
18
17
 
19
- config.gem 'xapit'
20
-
21
- And then install the gem and run the generator.
18
+ Then run the install generator.
22
19
 
23
- sudo rake gems:install
24
- script/generate xapit
20
+ rails g xapit:install
25
21
 
26
- Important: only run the generator script on a gem install, not for the plugin.
22
+ This creates a {configuration file}[https://github.com/ryanb/xapit/wiki/Configuration] and a rackup file for production use.
27
23
 
28
24
 
29
- == Setup
25
+ == Index
30
26
 
31
- Simply call "xapit" in the model and pass a block to define the indexed attributes.
27
+ To make a model searchable you must define an index through the +xapit+ method. Here is an example of the four methods you can call there:
32
28
 
33
29
  class Article < ActiveRecord::Base
34
- xapit do |index|
35
- index.text :name, :content
36
- index.field :category_id
37
- index.facet :author_name, "Author"
38
- index.sortable :id, :category_id
30
+ xapit do
31
+ text :name, :content
32
+ field :category_id
33
+ sortable :id, :created_at
34
+ facet :author_name, "Author"
39
35
  end
40
36
  end
41
37
 
42
- First we index "name" and "content" attributes for full text searching. The "category_id" field is indexed for :conditions searching. The "author_name" is indexed as a facet with "Author" being the display name of the facet. See the facets section below for details. Finally the "id" and "category_id" attributes are indexed as sortable attributes so they can be included in the :order option in a search.
43
-
44
- Because the indexing happens in Ruby these attributes do no have to be database columns. They can be simple Ruby methods. For example, the "author_name" attribute mentioned above can be defined like this.
45
-
46
- def author_name
47
- author.name
48
- end
49
-
50
- This way you can create a completely custom facet by simply defining your own method. Multiple facet options or field values per record are supported if you return an array.
51
-
52
- def author_names
53
- authors.map(&:name) # => ["John", "Bob"]
54
- end
55
-
56
- Finally, you can pass any find options to the xapit method to determine what gets indexed or improve performance with eager loading or a different batch size.
57
-
58
- xapit(:batch_size => 100, :include => :author, :conditions => { :visible => true })
59
-
60
- You can specify a :weight option to give a text attribute more importance. This will cause search terms matching that attribute to have a higher rank. The default weight is 1. Decimal (0.5) weight values are not supported.
61
-
62
- index.text :name, :weight => 10
63
-
64
-
65
- == Index
38
+ This indexes the model to be searched in a variety of ways (shown below). See the {Indexing}[https://github.com/ryanb/xapit/wiki/Indexing] wiki page for details.
66
39
 
67
- To perform the indexing, run the xapit:index rake task.
40
+ The index will automatically be updated when records are added or removed. You can regenerate the index manually to fill it with any existing records.
68
41
 
69
42
  rake xapit:index
70
43
 
71
- It can also be triggered through Ruby code using this command.
72
-
73
- Xapit.remove_database
74
- Xapit.index_all
75
-
76
- You may want to trigger this via a cron job on a recurring schedule (i.e. every day) to update the Xapian database. However it will only take effect after the Rails application is restarted because the Xapian database is stored in memory.
77
-
78
- There are two projects in development to help improve this reindexing.
79
-
80
- * http://github.com/ryanb/xapit-sync/tree/master
81
- * http://github.com/ryanb/xapit-server/tree/master
82
-
83
44
 
84
45
  == Search
85
46
 
86
- You can then perform a search on the model.
87
-
88
- # perform a simple full text search
47
+ Use the +search+ class method to perform a full text search on the index. This returns a Xapit scope where additional scoping methods can be called similar to Active Record scopes.
48
+
49
+ # simple full text search
89
50
  @articles = Article.search("phone")
90
-
91
- # add pagination if you're using will_paginate
92
- @articles = Article.search("phone", :per_page => 10, :page => params[:page])
93
-
94
- # search based on indexed fields
95
- @articles = Article.search("phone", :conditions => { :category_id => params[:category_id] })
96
-
97
- # search for multiple negative conditions (doesn't match 3, 5, or 8)
98
- @articles = Article.search(:not_conditions => { :category_id => [3, 5, 8] })
99
-
100
- # search for range of conditions by number
101
- @articles = Article.search(:conditions => { :released_at => 2.years.ago..Time.now })
102
-
103
- # manually sort based on any number of indexed fields, sort defaults to most relevant
104
- @articles = Article.search("phone", :order => [:category_id, :id], :descending => true)
105
-
106
- # basic boolean matching is supported
51
+
52
+ # full text search with basic boolean matching
107
53
  @articles = Article.search("phone OR fax NOT email")
108
54
 
55
+ # pagination works with kaminari and will_paginate
56
+ @articles = Article.search("phone").page(10).per(20)
109
57
 
110
- You can also search all indexed models through Xapit.search.
58
+ # search based on a specific field
59
+ @articles = Article.search("phone").where(:category_id => params[:category_id])
111
60
 
112
- # search all indexed models
113
- @records = Xapit.search("phone")
61
+ # search for multiple negative conditions (doesn't match 3, 5, or 8)
62
+ @articles = Article.search("phone").not_where(:category_id => [3, 5, 8])
114
63
 
64
+ # search for range of conditions by number
65
+ @articles = Article.search.where(:released_at => 2.years.ago..Time.now)
115
66
 
116
- == Results
67
+ # order based on sortable fields, sorting defaults to most relevant
68
+ @articles = Article.search("phone").order(:created_at, :descending => true)
117
69
 
118
70
  Simply iterate through the returned set to display the results.
119
71
 
@@ -124,15 +76,19 @@ Simply iterate through the returned set to display the results.
124
76
 
125
77
  The "xapit_relevance" holds a percentage (between 0 and 100) determining how relevant the given document is to the user's search query.
126
78
 
79
+ See the {Searching}[https://github.com/ryanb/xapit/wiki/Searching] wiki page for more details.
80
+
127
81
 
128
82
  == Spelling
129
83
 
130
- If the searched term isn't found, but it is similar to another term then it will show up as a spelling suggestion.
84
+ Spelling suggestions are available when there is a simlarly indexed term.
131
85
 
132
86
  <% if @articles.spelling_suggestion %>
133
- Did you mean <%= link_to h(@articles.spelling_suggestion), :overwrite_params => { :keywords => @articles.spelling_suggestion } %>?
87
+ Did you mean <%= link_to @articles.spelling_suggestion, :overwrite_params => { :keywords => @articles.spelling_suggestion } %>?
134
88
  <% end %>
135
89
 
90
+ Note: the spelling feature is disabled by default in the test environment because it uses an in-memory database.
91
+
136
92
 
137
93
  == Facets
138
94
 
@@ -146,52 +102,49 @@ Facets allow you to further filter the result set based on certain attributes.
146
102
  <% end %>
147
103
  <% end %>
148
104
 
149
- The to_param method is defined on option to return an identifier which will be passed through the URL. Use this in the search.
105
+ The facet option is passed in through the URL which you can add to the search.
150
106
 
151
- Article.search("phone", :facets => params[:facets])
107
+ Article.search("phone").with_facets(params[:facets])
152
108
 
153
109
  You can also list the applied facets along with a remove link.
154
110
 
155
111
  <% for option in @articles.applied_facet_options %>
156
- <%=h option.name %>
112
+ <%= option.name %>
157
113
  <%= link_to "remove", :overwrite_params => { :facets => option } %>
158
114
  <% end %>
159
115
 
116
+ See the {Facets}[https://github.com/ryanb/xapit/wiki/Facets] wiki page for more details.
160
117
 
161
- == Config
162
118
 
163
- When installing Xapit as a Rails plugin, an initializer file is automatically created to setup. It looks like this.
119
+ == Testing
164
120
 
165
- Xapit.setup(:database_path => "#{Rails.root}/db/xapiandb")
121
+ To use Xapit in the test environment, you will need to reload the configuration before each test. For example, you can do this in RSpec:
166
122
 
167
- There are many other options you can pass into here. This is a more advanced configuration setting which changes the stemming language, disables spelling, and changes the indexer and parser to a classic variation. The classic ones use Xapian's built-in term generator and query parser instead of the ones offered by Xapit.
123
+ config.before(:each) do
124
+ Xapit.reload
125
+ end
168
126
 
169
- Xapit.setup(
170
- :database_path => "#{Rails.root}/db/external/xapiandb",
171
- :spelling => false,
172
- :stemming => "german",
173
- :indexer => ClassicIndexer,
174
- :query_parser => ClassicQueryParser
175
- )
127
+ Xapit is also disabled by default in the test environment so you can enable it on a per-test basis. This way it doesn't slow down tests which don't need Xapit search.
176
128
 
129
+ Xapit.enable
130
+ # create records and test searching functionality
177
131
 
178
- == Adapters
132
+ If you have existing records in the database you want to search (maybe loaded by fixtures) you can index those.
179
133
 
180
- Adapters are used to support multiple ORMs since not everyone uses ActiveRecord. The right adapter is detected automatically so you should not have to do anything for popular ORMs. However if your ORM is not supported then it is very easy to make your own adapter. See AbstractAdapter class for details.
134
+ Xapit.index(Article, Comment) # or whatever models you need
181
135
 
136
+ By default, the test environment keeps the Xapian database in memory which makes it much faster and easier to reset. The problem is that the spelling suggestion feature does not work with in-memory databases, so it is disabled in the test environment by default. All of this can be customized in the {configuration file}[https://github.com/ryanb/xapit/wiki/Configuration].
182
137
 
183
- == Bug Reports
184
138
 
185
- If you have found a bug to report or a feature to request, please add it to the GitHub issue tracker if it is not there already.
139
+ == Production
186
140
 
187
- http://github.com/ryanb/xapit/issues
141
+ The default Xapit setup works well in development because there is only one instance of the Rails app running. However in production you will need to move Xapit to a separate process so all of the instances can communicate to it. To do this, start up the rackup file provided. You will likely want to put this behind a server such as Passenger.
188
142
 
143
+ rackup xapit.ru
189
144
 
190
- == Development
145
+ Now when you start up your Rails app in production it will use this server. You can configure the server URL in the {configuration file}[https://github.com/ryanb/xapit/wiki/Configuration].
191
146
 
192
- This project can be found on github at the following URL.
193
147
 
194
- http://github.com/ryanb/xapit
148
+ == Bug Reports
195
149
 
196
- If you would like to contribute to this project, please fork the
197
- repository and send me a pull request.
150
+ If you have found a bug to report or a feature to request, please add it to the {GitHub issue tracker}[https://github.com/ryanb/xapit/issues] if it is not there already. Feel free to treat it as a mailing list and discuss new ideas or bring up any confusion you may have.
data/Rakefile CHANGED
@@ -1,15 +1,16 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
- require 'echoe'
3
+ require 'cucumber/rake/task'
4
+ require 'rspec/core/rake_task'
4
5
 
5
- Echoe.new('xapit', '0.2.7') do |p|
6
- p.summary = "Ruby library for interacting with Xapian, a full text search engine."
7
- p.description = "Ruby library for interacting with Xapian, a full text search engine."
8
- p.url = "http://github.com/ryanb/xapit"
9
- p.author = 'Ryan Bates'
10
- p.email = "ryan (at) railscasts (dot) com"
11
- p.ignore_pattern = ["tmp/**/*", "spec/tmp/**/*"]
12
- p.development_dependencies = []
6
+ desc "Run RSpec"
7
+ RSpec::Core::RakeTask.new do |t|
8
+ t.verbose = false
13
9
  end
14
10
 
15
- Dir["#{File.dirname(__FILE__)}/tasks/*.rb"].sort.each { |ext| load ext }
11
+ desc "Run Cucumber"
12
+ Cucumber::Rake::Task.new do |t|
13
+ t.cucumber_opts = %w[--format progress]
14
+ end
15
+
16
+ task :default => [:spec, :cucumber]
@@ -1,90 +1,101 @@
1
- Background:
2
- Given an empty database at "tmp/xapiandatabase"
1
+ Feature: Facets
3
2
 
4
- Scenario: List All Facets
5
- Given the following indexed records
6
- | name | age |
7
- | John | 23 |
8
- | John | 17 |
9
- | Jack | 17 |
10
- When I query for ""
11
- Then I should have the following facets
12
- | facet | option | count |
13
- | Name | Jack | 1 |
14
- | Name | John | 2 |
15
- | Age | 17 | 2 |
16
- | Age | 23 | 1 |
3
+ Scenario: List All Facets
4
+ Given the following indexed records
5
+ | name | age |
6
+ | John | 23 |
7
+ | John | 17 |
8
+ | Jack | 17 |
9
+ When I query for ""
10
+ Then I should have the following facets
11
+ | facet | option | count |
12
+ | Name | Jack | 1 |
13
+ | Name | John | 2 |
14
+ | Age | 17 | 2 |
15
+ | Age | 23 | 1 |
17
16
 
18
- Scenario: List Matching Facets
19
- Given the following indexed records
20
- | name | age |
21
- | John | 23 |
22
- | John | 17 |
23
- | Jack | 17 |
24
- When I query for "John"
25
- Then I should have the following facets
26
- | facet | option | count |
27
- | Age | 17 | 1 |
28
- | Age | 23 | 1 |
17
+ Scenario: List Matching Facets
18
+ Given the following indexed records
19
+ | name | age |
20
+ | John | 23 |
21
+ | John | 17 |
22
+ | Jack | 17 |
23
+ When I query for "John"
24
+ Then I should have the following facets
25
+ | facet | option | count |
26
+ | Age | 17 | 1 |
27
+ | Age | 23 | 1 |
29
28
 
30
- Scenario: List Applied Facets
31
- Given the following indexed records
32
- | name | age |
33
- | John | 23 |
34
- | Jane | 17 |
35
- | Jack | 17 |
36
- When I query facets "0c93ee1-078661c"
37
- Then I should have the following applied facets
38
- | facet | option |
39
- | Age | 17 |
40
- | Name | Jane |
29
+ Scenario: List Multiple Facets Applied to One Record
30
+ Given the following indexed records
31
+ | name |
32
+ | John, Jack |
33
+ | John |
34
+ | Joe, Jack |
35
+ When I query for ""
36
+ Then I should have the following facets
37
+ | facet | option | count |
38
+ | Name | Jack | 2 |
39
+ | Name | Joe | 1 |
40
+ | Name | John | 2 |
41
41
 
42
- Scenario: List Multiple Facets Applied to One Record
43
- Given the following indexed records
44
- | name |
45
- | John, Jack |
46
- | John |
47
- | Joe, Jack |
48
- When I query for ""
49
- Then I should have the following facets
50
- | facet | option | count |
51
- | Name | Jack | 2 |
52
- | Name | Joe | 1 |
53
- | Name | John | 2 |
42
+ Scenario: Ignore Facets That Do Not Narrow Down List
43
+ Given the following indexed records
44
+ | name |
45
+ | John, Jack |
46
+ | John |
47
+ When I query for ""
48
+ Then I should have the following facets
49
+ | facet | option | count |
50
+ | Name | Jack | 1 |
54
51
 
55
- Scenario: Ignore Facets That Do Not Narrow Down List
56
- Given the following indexed records
57
- | name |
58
- | John, Jack |
59
- | John |
60
- When I query for ""
61
- Then I should have the following facets
62
- | facet | option | count |
63
- | Name | Jack | 1 |
52
+ Scenario: Query for One Facet
53
+ Given the following indexed records
54
+ | name | age |
55
+ | John | 23 |
56
+ | Jane | 17 |
57
+ | Jack | 17 |
58
+ When I query facets "9f33345"
59
+ Then I should find records named "Jane, Jack"
64
60
 
65
- Scenario: Query for One Facet
66
- Given the following indexed records
67
- | name | age |
68
- | John | 23 |
69
- | Jane | 17 |
70
- | Jack | 17 |
71
- When I query facets "0c93ee1"
72
- Then I should find records named "Jane, Jack"
61
+ Scenario: Query for Two Facets
62
+ Given the following indexed records
63
+ | name | age |
64
+ | John | 23 |
65
+ | Jane | 17 |
66
+ | Jack | 17 |
67
+ When I query facets "9f33345-9a10ff2"
68
+ Then I should find records named "Jane"
73
69
 
74
- Scenario: Query for Two Facets
75
- Given the following indexed records
76
- | name | age |
77
- | John | 23 |
78
- | Jane | 17 |
79
- | Jack | 17 |
80
- When I query facets "0c93ee1-078661c"
81
- Then I should find records named "Jane"
70
+ Scenario: Query for Facets with Keywords
71
+ Given the following indexed records
72
+ | name | age |
73
+ | John | 23 |
74
+ | Jane | 17 |
75
+ | Jack | 17 |
76
+ When I query "Jane" with facets "9f33345"
77
+ Then I should find record named "Jane"
82
78
 
83
- Scenario: Query for Facets with Keywords
84
- Given the following indexed records
85
- | name | age |
86
- | John | 23 |
87
- | Jane | 17 |
88
- | Jack | 17 |
89
- When I query "Jane" with facets "0c93ee1"
90
- Then I should find record named "Jane"
79
+ Scenario: List Applied Facets
80
+ Given the following indexed records
81
+ | name | age |
82
+ | John | 23 |
83
+ | Jane | 17 |
84
+ | Jack | 17 |
85
+ When I query facets "9f33345-9a10ff2"
86
+ Then I should have the following applied facets
87
+ | facet | option |
88
+ | Age | 17 |
89
+ | Name | Jane |
90
+
91
+ Scenario: Includes applied facets in facet params
92
+ Given the following indexed records
93
+ | name | age |
94
+ | John | 23 |
95
+ | Jane | 17 |
96
+ | Jack | 17 |
97
+ When I query facets "9f33345"
98
+ Then I should have the following facets
99
+ | facet | option | count | param |
100
+ | Name | Jack | 1 | 9f33345-bff6e04 |
101
+ | Name | Jane | 1 | 9f33345-9a10ff2 |