xapit 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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 |