xapit 0.1.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.
Files changed (180) hide show
  1. data/LICENSE +20 -0
  2. data/Manifest +178 -0
  3. data/README.rdoc +183 -0
  4. data/Rakefile +15 -0
  5. data/TODO +23 -0
  6. data/features/facets.feature +51 -0
  7. data/features/finding.feature +119 -0
  8. data/features/indexing.feature +41 -0
  9. data/features/step_definitions/common_steps.rb +7 -0
  10. data/features/step_definitions/xapit_steps.rb +117 -0
  11. data/features/support/env.rb +7 -0
  12. data/features/support/xapit_helpers.rb +27 -0
  13. data/init.rb +3 -0
  14. data/install.rb +9 -0
  15. data/lib/xapit.rb +39 -0
  16. data/lib/xapit/collection.rb +165 -0
  17. data/lib/xapit/config.rb +83 -0
  18. data/lib/xapit/facet.rb +59 -0
  19. data/lib/xapit/facet_blueprint.rb +59 -0
  20. data/lib/xapit/facet_option.rb +56 -0
  21. data/lib/xapit/index_blueprint.rb +117 -0
  22. data/lib/xapit/indexers/abstract_indexer.rb +101 -0
  23. data/lib/xapit/indexers/classic_indexer.rb +27 -0
  24. data/lib/xapit/indexers/simple_indexer.rb +31 -0
  25. data/lib/xapit/membership.rb +103 -0
  26. data/lib/xapit/query.rb +62 -0
  27. data/lib/xapit/query_parsers/abstract_query_parser.rb +115 -0
  28. data/lib/xapit/query_parsers/classic_query_parser.rb +19 -0
  29. data/lib/xapit/query_parsers/simple_query_parser.rb +75 -0
  30. data/spec/spec_helper.rb +15 -0
  31. data/spec/tmp/xapdb/flintlock +0 -0
  32. data/spec/tmp/xapdb/iamflint +0 -0
  33. data/spec/tmp/xapdb/postlist.DB +0 -0
  34. data/spec/tmp/xapdb/postlist.baseA +0 -0
  35. data/spec/tmp/xapdb/postlist.baseB +0 -0
  36. data/spec/tmp/xapdb/record.DB +0 -0
  37. data/spec/tmp/xapdb/record.baseA +0 -0
  38. data/spec/tmp/xapdb/record.baseB +0 -0
  39. data/spec/tmp/xapdb/spelling.DB +0 -0
  40. data/spec/tmp/xapdb/spelling.baseA +0 -0
  41. data/spec/tmp/xapdb/spelling.baseB +0 -0
  42. data/spec/tmp/xapdb/termlist.DB +0 -0
  43. data/spec/tmp/xapdb/termlist.baseA +0 -0
  44. data/spec/tmp/xapdb/termlist.baseB +0 -0
  45. data/spec/tmp/xapian_db/flintlock +0 -0
  46. data/spec/tmp/xapian_db/iamflint +0 -0
  47. data/spec/tmp/xapian_db/postlist.DB +0 -0
  48. data/spec/tmp/xapian_db/postlist.baseA +0 -0
  49. data/spec/tmp/xapian_db/record.DB +0 -0
  50. data/spec/tmp/xapian_db/record.baseA +0 -0
  51. data/spec/tmp/xapian_db/termlist.DB +0 -0
  52. data/spec/tmp/xapian_db/termlist.baseA +0 -0
  53. data/spec/tmp/xapiandab/flintlock +0 -0
  54. data/spec/tmp/xapiandab/iamflint +0 -0
  55. data/spec/tmp/xapiandab/postlist.DB +0 -0
  56. data/spec/tmp/xapiandab/postlist.baseA +0 -0
  57. data/spec/tmp/xapiandab/postlist.baseB +0 -0
  58. data/spec/tmp/xapiandab/record.DB +0 -0
  59. data/spec/tmp/xapiandab/record.baseA +0 -0
  60. data/spec/tmp/xapiandab/record.baseB +0 -0
  61. data/spec/tmp/xapiandab/spelling.DB +0 -0
  62. data/spec/tmp/xapiandab/spelling.baseA +0 -0
  63. data/spec/tmp/xapiandab/spelling.baseB +0 -0
  64. data/spec/tmp/xapiandab/termlist.DB +0 -0
  65. data/spec/tmp/xapiandab/termlist.baseA +0 -0
  66. data/spec/tmp/xapiandab/termlist.baseB +0 -0
  67. data/spec/tmp/xapiandatab/flintlock +0 -0
  68. data/spec/tmp/xapiandatab/iamflint +0 -0
  69. data/spec/tmp/xapiandatab/postlist.DB +0 -0
  70. data/spec/tmp/xapiandatab/postlist.baseA +0 -0
  71. data/spec/tmp/xapiandatab/postlist.baseB +0 -0
  72. data/spec/tmp/xapiandatab/record.DB +0 -0
  73. data/spec/tmp/xapiandatab/record.baseA +0 -0
  74. data/spec/tmp/xapiandatab/record.baseB +0 -0
  75. data/spec/tmp/xapiandatab/spelling.DB +0 -0
  76. data/spec/tmp/xapiandatab/spelling.baseA +0 -0
  77. data/spec/tmp/xapiandatab/spelling.baseB +0 -0
  78. data/spec/tmp/xapiandatab/termlist.DB +0 -0
  79. data/spec/tmp/xapiandatab/termlist.baseA +0 -0
  80. data/spec/tmp/xapiandatab/termlist.baseB +0 -0
  81. data/spec/tmp/xapiandataba/flintlock +0 -0
  82. data/spec/tmp/xapiandataba/iamflint +0 -0
  83. data/spec/tmp/xapiandataba/postlist.DB +0 -0
  84. data/spec/tmp/xapiandataba/postlist.baseA +0 -0
  85. data/spec/tmp/xapiandataba/postlist.baseB +0 -0
  86. data/spec/tmp/xapiandataba/record.DB +0 -0
  87. data/spec/tmp/xapiandataba/record.baseA +0 -0
  88. data/spec/tmp/xapiandataba/record.baseB +0 -0
  89. data/spec/tmp/xapiandataba/spelling.DB +0 -0
  90. data/spec/tmp/xapiandataba/spelling.baseA +0 -0
  91. data/spec/tmp/xapiandataba/spelling.baseB +0 -0
  92. data/spec/tmp/xapiandataba/termlist.DB +0 -0
  93. data/spec/tmp/xapiandataba/termlist.baseA +0 -0
  94. data/spec/tmp/xapiandataba/termlist.baseB +0 -0
  95. data/spec/tmp/xapiandatabas/flintlock +0 -0
  96. data/spec/tmp/xapiandatabas/iamflint +0 -0
  97. data/spec/tmp/xapiandatabas/postlist.DB +0 -0
  98. data/spec/tmp/xapiandatabas/postlist.baseA +0 -0
  99. data/spec/tmp/xapiandatabas/record.DB +0 -0
  100. data/spec/tmp/xapiandatabas/record.baseA +0 -0
  101. data/spec/tmp/xapiandatabas/termlist.DB +0 -0
  102. data/spec/tmp/xapiandatabas/termlist.baseA +0 -0
  103. data/spec/tmp/xapiandatb/flintlock +0 -0
  104. data/spec/tmp/xapiandatb/iamflint +0 -0
  105. data/spec/tmp/xapiandatb/postlist.DB +0 -0
  106. data/spec/tmp/xapiandatb/postlist.baseA +0 -0
  107. data/spec/tmp/xapiandatb/postlist.baseB +0 -0
  108. data/spec/tmp/xapiandatb/record.DB +0 -0
  109. data/spec/tmp/xapiandatb/record.baseA +0 -0
  110. data/spec/tmp/xapiandatb/record.baseB +0 -0
  111. data/spec/tmp/xapiandatb/spelling.DB +0 -0
  112. data/spec/tmp/xapiandatb/spelling.baseA +0 -0
  113. data/spec/tmp/xapiandatb/spelling.baseB +0 -0
  114. data/spec/tmp/xapiandatb/termlist.DB +0 -0
  115. data/spec/tmp/xapiandatb/termlist.baseA +0 -0
  116. data/spec/tmp/xapiandatb/termlist.baseB +0 -0
  117. data/spec/tmp/xapiandbase/flintlock +0 -0
  118. data/spec/tmp/xapiandbase/iamflint +0 -0
  119. data/spec/tmp/xapiandbase/postlist.DB +0 -0
  120. data/spec/tmp/xapiandbase/postlist.baseA +0 -0
  121. data/spec/tmp/xapiandbase/postlist.baseB +0 -0
  122. data/spec/tmp/xapiandbase/record.DB +0 -0
  123. data/spec/tmp/xapiandbase/record.baseA +0 -0
  124. data/spec/tmp/xapiandbase/record.baseB +0 -0
  125. data/spec/tmp/xapiandbase/spelling.DB +0 -0
  126. data/spec/tmp/xapiandbase/spelling.baseA +0 -0
  127. data/spec/tmp/xapiandbase/spelling.baseB +0 -0
  128. data/spec/tmp/xapiandbase/termlist.DB +0 -0
  129. data/spec/tmp/xapiandbase/termlist.baseA +0 -0
  130. data/spec/tmp/xapiandbase/termlist.baseB +0 -0
  131. data/spec/xapit/collection_spec.rb +153 -0
  132. data/spec/xapit/config_spec.rb +48 -0
  133. data/spec/xapit/facet_blueprint_spec.rb +29 -0
  134. data/spec/xapit/facet_option_spec.rb +80 -0
  135. data/spec/xapit/facet_spec.rb +73 -0
  136. data/spec/xapit/index_blueprint_spec.rb +60 -0
  137. data/spec/xapit/indexers/abstract_indexer_spec.rb +74 -0
  138. data/spec/xapit/indexers/classic_indexer_spec.rb +26 -0
  139. data/spec/xapit/indexers/simple_indexer_spec.rb +53 -0
  140. data/spec/xapit/membership_spec.rb +39 -0
  141. data/spec/xapit/query_parsers/abstract_query_parser_spec.rb +23 -0
  142. data/spec/xapit/query_parsers/classic_query_parser_spec.rb +15 -0
  143. data/spec/xapit/query_parsers/simple_query_parser_spec.rb +86 -0
  144. data/spec/xapit/query_spec.rb +41 -0
  145. data/spec/xapit_member.rb +32 -0
  146. data/tasks/spec.rb +9 -0
  147. data/tasks/xapit.rake +9 -0
  148. data/tmp/xapiandatabase/flintlock +0 -0
  149. data/tmp/xapiandatabase/iamflint +0 -0
  150. data/tmp/xapiandatabase/postlist.DB +0 -0
  151. data/tmp/xapiandatabase/postlist.baseA +0 -0
  152. data/tmp/xapiandatabase/postlist.baseB +0 -0
  153. data/tmp/xapiandatabase/record.DB +0 -0
  154. data/tmp/xapiandatabase/record.baseA +0 -0
  155. data/tmp/xapiandatabase/record.baseB +0 -0
  156. data/tmp/xapiandatabase/spelling.DB +0 -0
  157. data/tmp/xapiandatabase/spelling.baseA +0 -0
  158. data/tmp/xapiandatabase/spelling.baseB +0 -0
  159. data/tmp/xapiandatabase/termlist.DB +0 -0
  160. data/tmp/xapiandatabase/termlist.baseA +0 -0
  161. data/tmp/xapiandatabase/termlist.baseB +0 -0
  162. data/tmp/xapiandatabase/value.baseB +0 -0
  163. data/tmp/xapiandb/flintlock +0 -0
  164. data/tmp/xapiandb/iamflint +0 -0
  165. data/tmp/xapiandb/postlist.DB +0 -0
  166. data/tmp/xapiandb/postlist.baseA +0 -0
  167. data/tmp/xapiandb/postlist.baseB +0 -0
  168. data/tmp/xapiandb/record.DB +0 -0
  169. data/tmp/xapiandb/record.baseA +0 -0
  170. data/tmp/xapiandb/record.baseB +0 -0
  171. data/tmp/xapiandb/spelling.DB +0 -0
  172. data/tmp/xapiandb/spelling.baseA +0 -0
  173. data/tmp/xapiandb/spelling.baseB +0 -0
  174. data/tmp/xapiandb/termlist.DB +0 -0
  175. data/tmp/xapiandb/termlist.baseA +0 -0
  176. data/tmp/xapiandb/termlist.baseB +0 -0
  177. data/tmp/xapiandb/value.baseB +0 -0
  178. data/uninstall.rb +5 -0
  179. data/xapit.gemspec +30 -0
  180. metadata +257 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Ryan Bates
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,178 @@
1
+ features/facets.feature
2
+ features/finding.feature
3
+ features/indexing.feature
4
+ features/step_definitions/common_steps.rb
5
+ features/step_definitions/xapit_steps.rb
6
+ features/support/env.rb
7
+ features/support/xapit_helpers.rb
8
+ init.rb
9
+ install.rb
10
+ lib/xapit/collection.rb
11
+ lib/xapit/config.rb
12
+ lib/xapit/facet.rb
13
+ lib/xapit/facet_blueprint.rb
14
+ lib/xapit/facet_option.rb
15
+ lib/xapit/index_blueprint.rb
16
+ lib/xapit/indexers/abstract_indexer.rb
17
+ lib/xapit/indexers/classic_indexer.rb
18
+ lib/xapit/indexers/simple_indexer.rb
19
+ lib/xapit/membership.rb
20
+ lib/xapit/query.rb
21
+ lib/xapit/query_parsers/abstract_query_parser.rb
22
+ lib/xapit/query_parsers/classic_query_parser.rb
23
+ lib/xapit/query_parsers/simple_query_parser.rb
24
+ lib/xapit.rb
25
+ LICENSE
26
+ Rakefile
27
+ README.rdoc
28
+ spec/spec_helper.rb
29
+ spec/tmp/xapdb/flintlock
30
+ spec/tmp/xapdb/iamflint
31
+ spec/tmp/xapdb/postlist.baseA
32
+ spec/tmp/xapdb/postlist.baseB
33
+ spec/tmp/xapdb/postlist.DB
34
+ spec/tmp/xapdb/record.baseA
35
+ spec/tmp/xapdb/record.baseB
36
+ spec/tmp/xapdb/record.DB
37
+ spec/tmp/xapdb/spelling.baseA
38
+ spec/tmp/xapdb/spelling.baseB
39
+ spec/tmp/xapdb/spelling.DB
40
+ spec/tmp/xapdb/termlist.baseA
41
+ spec/tmp/xapdb/termlist.baseB
42
+ spec/tmp/xapdb/termlist.DB
43
+ spec/tmp/xapian_db/flintlock
44
+ spec/tmp/xapian_db/iamflint
45
+ spec/tmp/xapian_db/postlist.baseA
46
+ spec/tmp/xapian_db/postlist.DB
47
+ spec/tmp/xapian_db/record.baseA
48
+ spec/tmp/xapian_db/record.DB
49
+ spec/tmp/xapian_db/termlist.baseA
50
+ spec/tmp/xapian_db/termlist.DB
51
+ spec/tmp/xapiandab/flintlock
52
+ spec/tmp/xapiandab/iamflint
53
+ spec/tmp/xapiandab/postlist.baseA
54
+ spec/tmp/xapiandab/postlist.baseB
55
+ spec/tmp/xapiandab/postlist.DB
56
+ spec/tmp/xapiandab/record.baseA
57
+ spec/tmp/xapiandab/record.baseB
58
+ spec/tmp/xapiandab/record.DB
59
+ spec/tmp/xapiandab/spelling.baseA
60
+ spec/tmp/xapiandab/spelling.baseB
61
+ spec/tmp/xapiandab/spelling.DB
62
+ spec/tmp/xapiandab/termlist.baseA
63
+ spec/tmp/xapiandab/termlist.baseB
64
+ spec/tmp/xapiandab/termlist.DB
65
+ spec/tmp/xapiandatab/flintlock
66
+ spec/tmp/xapiandatab/iamflint
67
+ spec/tmp/xapiandatab/postlist.baseA
68
+ spec/tmp/xapiandatab/postlist.baseB
69
+ spec/tmp/xapiandatab/postlist.DB
70
+ spec/tmp/xapiandatab/record.baseA
71
+ spec/tmp/xapiandatab/record.baseB
72
+ spec/tmp/xapiandatab/record.DB
73
+ spec/tmp/xapiandatab/spelling.baseA
74
+ spec/tmp/xapiandatab/spelling.baseB
75
+ spec/tmp/xapiandatab/spelling.DB
76
+ spec/tmp/xapiandatab/termlist.baseA
77
+ spec/tmp/xapiandatab/termlist.baseB
78
+ spec/tmp/xapiandatab/termlist.DB
79
+ spec/tmp/xapiandataba/flintlock
80
+ spec/tmp/xapiandataba/iamflint
81
+ spec/tmp/xapiandataba/postlist.baseA
82
+ spec/tmp/xapiandataba/postlist.baseB
83
+ spec/tmp/xapiandataba/postlist.DB
84
+ spec/tmp/xapiandataba/record.baseA
85
+ spec/tmp/xapiandataba/record.baseB
86
+ spec/tmp/xapiandataba/record.DB
87
+ spec/tmp/xapiandataba/spelling.baseA
88
+ spec/tmp/xapiandataba/spelling.baseB
89
+ spec/tmp/xapiandataba/spelling.DB
90
+ spec/tmp/xapiandataba/termlist.baseA
91
+ spec/tmp/xapiandataba/termlist.baseB
92
+ spec/tmp/xapiandataba/termlist.DB
93
+ spec/tmp/xapiandatabas/flintlock
94
+ spec/tmp/xapiandatabas/iamflint
95
+ spec/tmp/xapiandatabas/postlist.baseA
96
+ spec/tmp/xapiandatabas/postlist.DB
97
+ spec/tmp/xapiandatabas/record.baseA
98
+ spec/tmp/xapiandatabas/record.DB
99
+ spec/tmp/xapiandatabas/termlist.baseA
100
+ spec/tmp/xapiandatabas/termlist.DB
101
+ spec/tmp/xapiandatb/flintlock
102
+ spec/tmp/xapiandatb/iamflint
103
+ spec/tmp/xapiandatb/postlist.baseA
104
+ spec/tmp/xapiandatb/postlist.baseB
105
+ spec/tmp/xapiandatb/postlist.DB
106
+ spec/tmp/xapiandatb/record.baseA
107
+ spec/tmp/xapiandatb/record.baseB
108
+ spec/tmp/xapiandatb/record.DB
109
+ spec/tmp/xapiandatb/spelling.baseA
110
+ spec/tmp/xapiandatb/spelling.baseB
111
+ spec/tmp/xapiandatb/spelling.DB
112
+ spec/tmp/xapiandatb/termlist.baseA
113
+ spec/tmp/xapiandatb/termlist.baseB
114
+ spec/tmp/xapiandatb/termlist.DB
115
+ spec/tmp/xapiandbase/flintlock
116
+ spec/tmp/xapiandbase/iamflint
117
+ spec/tmp/xapiandbase/postlist.baseA
118
+ spec/tmp/xapiandbase/postlist.baseB
119
+ spec/tmp/xapiandbase/postlist.DB
120
+ spec/tmp/xapiandbase/record.baseA
121
+ spec/tmp/xapiandbase/record.baseB
122
+ spec/tmp/xapiandbase/record.DB
123
+ spec/tmp/xapiandbase/spelling.baseA
124
+ spec/tmp/xapiandbase/spelling.baseB
125
+ spec/tmp/xapiandbase/spelling.DB
126
+ spec/tmp/xapiandbase/termlist.baseA
127
+ spec/tmp/xapiandbase/termlist.baseB
128
+ spec/tmp/xapiandbase/termlist.DB
129
+ spec/xapit/collection_spec.rb
130
+ spec/xapit/config_spec.rb
131
+ spec/xapit/facet_blueprint_spec.rb
132
+ spec/xapit/facet_option_spec.rb
133
+ spec/xapit/facet_spec.rb
134
+ spec/xapit/index_blueprint_spec.rb
135
+ spec/xapit/indexers/abstract_indexer_spec.rb
136
+ spec/xapit/indexers/classic_indexer_spec.rb
137
+ spec/xapit/indexers/simple_indexer_spec.rb
138
+ spec/xapit/membership_spec.rb
139
+ spec/xapit/query_parsers/abstract_query_parser_spec.rb
140
+ spec/xapit/query_parsers/classic_query_parser_spec.rb
141
+ spec/xapit/query_parsers/simple_query_parser_spec.rb
142
+ spec/xapit/query_spec.rb
143
+ spec/xapit_member.rb
144
+ tasks/spec.rb
145
+ tasks/xapit.rake
146
+ tmp/xapiandatabase/flintlock
147
+ tmp/xapiandatabase/iamflint
148
+ tmp/xapiandatabase/postlist.baseA
149
+ tmp/xapiandatabase/postlist.baseB
150
+ tmp/xapiandatabase/postlist.DB
151
+ tmp/xapiandatabase/record.baseA
152
+ tmp/xapiandatabase/record.baseB
153
+ tmp/xapiandatabase/record.DB
154
+ tmp/xapiandatabase/spelling.baseA
155
+ tmp/xapiandatabase/spelling.baseB
156
+ tmp/xapiandatabase/spelling.DB
157
+ tmp/xapiandatabase/termlist.baseA
158
+ tmp/xapiandatabase/termlist.baseB
159
+ tmp/xapiandatabase/termlist.DB
160
+ tmp/xapiandatabase/value.baseB
161
+ tmp/xapiandb/flintlock
162
+ tmp/xapiandb/iamflint
163
+ tmp/xapiandb/postlist.baseA
164
+ tmp/xapiandb/postlist.baseB
165
+ tmp/xapiandb/postlist.DB
166
+ tmp/xapiandb/record.baseA
167
+ tmp/xapiandb/record.baseB
168
+ tmp/xapiandb/record.DB
169
+ tmp/xapiandb/spelling.baseA
170
+ tmp/xapiandb/spelling.baseB
171
+ tmp/xapiandb/spelling.DB
172
+ tmp/xapiandb/termlist.baseA
173
+ tmp/xapiandb/termlist.baseB
174
+ tmp/xapiandb/termlist.DB
175
+ tmp/xapiandb/value.baseB
176
+ TODO
177
+ uninstall.rb
178
+ Manifest
@@ -0,0 +1,183 @@
1
+ = Xapit
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.
6
+
7
+
8
+ == Install
9
+
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
12
+
13
+ To install as a Rails plugin, run this command.
14
+
15
+ script/plugin install git://github.com/ryanb/xapit.git
16
+
17
+ Note: this will soon also be available as a Ruby gem, but not yet.
18
+
19
+
20
+ == Setup
21
+
22
+ Simply call "xapit" in the model and pass a block to define the indexed attributes.
23
+
24
+ class Article < ActiveRecord::Base
25
+ xapit do |index|
26
+ index.text :name, :content
27
+ index.field :category_id
28
+ index.facet :author_name, "Author"
29
+ index.sortable :id, :category_id
30
+ end
31
+ end
32
+
33
+ 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.
34
+
35
+ 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.
36
+
37
+ def author_name
38
+ author.name
39
+ end
40
+
41
+ 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.
42
+
43
+ def author_names
44
+ authors.map(&:name) # => ["John", "Bob"]
45
+ end
46
+
47
+ 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.
48
+
49
+ xapit(:batch_size => 100, :include => :author, :conditions => { :visible => true })
50
+
51
+ 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.
52
+
53
+ index.text :name, :weight => 10
54
+
55
+
56
+ == Index
57
+
58
+ To perform the indexing, run the xapit:index rake task.
59
+
60
+ rake xapit:index
61
+
62
+ It can also be triggered through Ruby code using this command.
63
+
64
+ Xapit::Config.remove_database
65
+ Xapit.index_all
66
+
67
+
68
+ == Search
69
+
70
+ You can then perform a search on the model.
71
+
72
+ # perform a simple full text search
73
+ @articles = Article.search("phone")
74
+
75
+ # add pagination if you're using will_paginate
76
+ @articles = Article.search("phone", :per_page => 10, :page => params[:page])
77
+
78
+ # search based on indexed fields
79
+ @articles = Article.search("phone", :conditions => { :category_id => params[:category_id] })
80
+
81
+ # manually sort based on any number of indexed fields, sort defaults to most relevant
82
+ @articles = Article.search("phone", :order => [:category_id, :id], :descending => true)
83
+
84
+ # basic boolean matching is supported
85
+ @articles = Article.search("phone OR fax NOT email")
86
+
87
+
88
+ You can also search all indexed models through Xapit.search.
89
+
90
+ # search all indexed models
91
+ @records = Xapit.search("phone")
92
+
93
+
94
+ == Results
95
+
96
+ Simply iterate through the returned set to display the results.
97
+
98
+ <% for article in @articles %>
99
+ <%= article.name %>
100
+ <%= article.xapit_relevance %>
101
+ <% end %>
102
+
103
+ The "xapit_relevance" holds a percentage (between 0 and 100) determining how relevant the given document is to the user's search query.
104
+
105
+
106
+ == Spelling
107
+
108
+ If the searched term isn't found, but it is similar to another term then it will show up as a spelling suggestion.
109
+
110
+ <% if @articles.spelling_suggestion %>
111
+ Did you mean <%= link_to h(@articles.spelling_suggestion), :overwrite_params => { :keywords => @articles.spelling_suggestion } %>?
112
+ <% end %>
113
+
114
+
115
+ == Facets
116
+
117
+ Facets allow you to further filter the result set based on certain attributes.
118
+
119
+ <% for facet in @articles.facets %>
120
+ <%= facet.name %>
121
+ <% for option in facet.options %>
122
+ <%= link_to option.name, :overwrite_params => { :facets => option } %>
123
+ (<%= option.count %>)
124
+ <% end %>
125
+ <% end %>
126
+
127
+ The to_param method is defined on option to return an identifier which will be passed through the URL. Use this in the search.
128
+
129
+ Article.search("phone", :facets => params[:facets])
130
+
131
+ You can also list the applied facets along with a remove link.
132
+
133
+ <% for option in @articles.applied_facet_options %>
134
+ <%=h option.name %>
135
+ <%= link_to "remove", :overwrite_params => { :facets => option } %>
136
+ <% end %>
137
+
138
+
139
+ == Config
140
+
141
+ When installing Xapit as a Rails plugin, an initializer file is automatically created to setup. It looks like this.
142
+
143
+ Xapit::Config.setup(:database_path => "#{Rails.root}/db/xapiandb")
144
+
145
+ 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.
146
+
147
+ Xapit::Config.setup(
148
+ :database_path => "#{Rails.root}/db/external/xapiandb",
149
+ :spelling => false,
150
+ :stemming => "german",
151
+ :indexer => ClassicIndexer,
152
+ :query_parser => ClassicQueryParser
153
+ )
154
+
155
+
156
+ == Outside of Rails
157
+
158
+ Xapit can be used outside of Rails too. You'll just need to include the membership module:
159
+
160
+ class Product # not Active Record
161
+ include Xapit::Membership
162
+
163
+ xapit # ...
164
+ end
165
+
166
+ This class is expected to respond to "find_each" (Product.find_each) which is used to iterate through the records when indexing and "find" for fetching a record by "id".
167
+
168
+
169
+ == Bug Reports
170
+
171
+ 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.
172
+
173
+ http://github.com/ryanb/xapit/issues/
174
+
175
+
176
+ == Development
177
+
178
+ This project can be found on github at the following URL.
179
+
180
+ http://github.com/ryanb/xapit
181
+
182
+ If you would like to contribute to this project, please fork the
183
+ repository and send me a pull request.
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('xapit', '0.1.0') 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/*"]
12
+ p.development_dependencies = []
13
+ end
14
+
15
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rb"].sort.each { |ext| load ext }
data/TODO ADDED
@@ -0,0 +1,23 @@
1
+ Indexing
2
+ + re-indexing support for new/changed models (?)
3
+ + auto-reload xapian database in memory if database recently indexed
4
+
5
+ Finding
6
+ ? support non-ascii characters in find (å, ä, ö)
7
+ + range in conditions
8
+ + support "age:17" condition matching in query
9
+ + add classes option to Xapit.search to limit which classes are included
10
+ + support @collection.facets on Xapit.search (multiple classes)
11
+ + support :order option for Xapit.search (multiple classes)
12
+
13
+ Facets
14
+ + sort facet options
15
+ + handle unique id collision gracefully
16
+
17
+ Performance
18
+ - benchmark indexing
19
+ - multiple id finds in a single query
20
+
21
+ Other
22
+ - turn into Ruby Gem with clear instructions on requirements
23
+ + remove dependency on active_support
@@ -0,0 +1,51 @@
1
+ Background:
2
+ Given an empty database at "tmp/xapiandatabase"
3
+
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 |
17
+
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 |
29
+
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 |
41
+
42
+ Scenario: List Multiple Facets Applied to One Record
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 |
51
+ | Name | John | 2 |