gojee-sunspot 2.0.4 → 2.0.5

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.
@@ -0,0 +1,853 @@
1
+ # Sunspot
2
+
3
+ [![Build Status](https://secure.travis-ci.org/sunspot/sunspot.png)](http://travis-ci.org/sunspot/sunspot)
4
+
5
+ Sunspot is a Ruby library for expressive, powerful interaction with the Solr
6
+ search engine. Sunspot is built on top of the RSolr library, which
7
+ provides a low-level interface for Solr interaction; Sunspot provides a simple,
8
+ intuitive, expressive DSL backed by powerful features for indexing objects and
9
+ searching for them.
10
+
11
+ Sunspot is designed to be easily plugged in to any ORM, or even non-database-backed
12
+ objects such as the filesystem.
13
+
14
+ This README provides a high level overview; class-by-class and
15
+ method-by-method documentation is available in the [API
16
+ reference](http://sunspot.github.com/sunspot/docs/).
17
+
18
+ ## Quickstart with Rails 3
19
+
20
+ Add to Gemfile:
21
+
22
+ ```ruby
23
+ gem 'sunspot_rails'
24
+ gem 'sunspot_solr' # optional pre-packaged Solr distribution for use in development
25
+ ```
26
+
27
+ Bundle it!
28
+
29
+ ```bash
30
+ bundle install
31
+ ```
32
+
33
+ Generate a default configuration file:
34
+
35
+ ```bash
36
+ rails generate sunspot_rails:install
37
+ ```
38
+
39
+ If `sunspot_solr` was installed, start the packaged Solr distribution
40
+ with:
41
+
42
+ ```bash
43
+ bundle exec rake sunspot:solr:start # or sunspot:solr:run to start in foreground
44
+ ```
45
+
46
+ ## Setting Up Objects
47
+
48
+ Add a `searchable` block to the objects you wish to index.
49
+
50
+ ```ruby
51
+ class Post < ActiveRecord::Base
52
+ searchable do
53
+ text :title, :body
54
+ text :comments do
55
+ comments.map { |comment| comment.body }
56
+ end
57
+
58
+ boolean :featured
59
+ integer :blog_id
60
+ integer :author_id
61
+ integer :category_ids, :multiple => true
62
+ double :average_rating
63
+ time :published_at
64
+ time :expired_at
65
+
66
+ string :sort_title do
67
+ title.downcase.gsub(/^(an?|the)/, '')
68
+ end
69
+ end
70
+ end
71
+ ```
72
+
73
+ `text` fields will be full-text searchable. Other fields (e.g.,
74
+ `integer` and `string`) can be used to scope queries.
75
+
76
+ ## Searching Objects
77
+
78
+ ```ruby
79
+ Post.search do
80
+ fulltext 'best pizza'
81
+
82
+ with :blog_id, 1
83
+ with(:published_at).less_than Time.now
84
+ order_by :published_at, :desc
85
+ paginate :page => 2, :per_page => 15
86
+ facet :category_ids, :author_id
87
+ end
88
+ ```
89
+
90
+ ## Search In Depth
91
+
92
+ Given an object `Post` setup in earlier steps ...
93
+
94
+ ### Full Text
95
+
96
+ ```ruby
97
+ # All posts with a `text` field (:title, :body, or :comments) containing 'pizza'
98
+ Post.search { fulltext 'pizza' }
99
+
100
+ # Posts with pizza, scored higher if pizza appears in the title
101
+ Post.search do
102
+ fulltext 'pizza' do
103
+ boost_fields :title => 2.0
104
+ end
105
+ end
106
+
107
+ # Posts with pizza, scored higher if featured
108
+ Post.search do
109
+ fulltext 'pizza' do
110
+ boost(2.0) { with(:featured, true) }
111
+ end
112
+ end
113
+
114
+ # Posts with pizza *only* in the title
115
+ Post.search do
116
+ fulltext 'pizza' do
117
+ fields(:title)
118
+ end
119
+ end
120
+
121
+ # Posts with pizza in the title (boosted) or in the body (not boosted)
122
+ Post.search do
123
+ fulltext 'pizza' do
124
+ fields(:body, :title => 2.0)
125
+ end
126
+ end
127
+ ```
128
+
129
+ #### Phrases
130
+
131
+ Solr allows searching for phrases: search terms that are close together.
132
+
133
+ In the default query parser used by Sunspot (dismax), phrase searches
134
+ are represented as a double quoted group of words.
135
+
136
+ ```ruby
137
+ # Posts with the exact phrase "great pizza"
138
+ Post.search do
139
+ fulltext '"great pizza"'
140
+ end
141
+ ```
142
+
143
+ If specified, **query_phrase_slop** sets the number of words that may
144
+ appear between the words in a phrase.
145
+
146
+ ```ruby
147
+ # One word can appear between the words in the phrase, so "great big pizza"
148
+ # also matches, in addition to "great pizza"
149
+ Post.search do
150
+ fulltext '"great pizza"' do
151
+ query_phrase_slop 1
152
+ end
153
+ end
154
+ ```
155
+
156
+ ##### Phrase Boosts
157
+
158
+ Phrase boosts add boost to terms that appear in close proximity;
159
+ the terms do not *have* to appear in a phrase, but if they do, the
160
+ document will score more highly.
161
+
162
+ ```ruby
163
+ # Matches documents with great and pizza, and scores documents more
164
+ # highly if the terms appear in a phrase in the title field
165
+ Post.search do
166
+ fulltext 'great pizza' do
167
+ phrase_fields :title => 2.0
168
+ end
169
+ end
170
+
171
+ # Matches documents with great and pizza, and scores documents more
172
+ # highly if the terms appear in a phrase (or with one word between them)
173
+ # in the title field
174
+ Post.search do
175
+ fulltext 'great pizza' do
176
+ phrase_fields :title => 2.0
177
+ phrase_slop 1
178
+ end
179
+ end
180
+ ```
181
+
182
+ ### Scoping (Scalar Fields)
183
+
184
+ Fields not defined as `text` (e.g., `integer`, `boolean`, `time`,
185
+ etc...) can be used to scope (restrict) queries before full-text
186
+ matching is performed.
187
+
188
+ #### Positive Restrictions
189
+
190
+ ```ruby
191
+ # Posts with a blog_id of 1
192
+ Post.search do
193
+ with(:blog_id, 1)
194
+ end
195
+
196
+ # Posts with an average rating between 3.0 and 5.0
197
+ Post.search do
198
+ with(:average_rating, 3.0..5.0)
199
+ end
200
+
201
+ # Posts with a category of 1, 3, or 5
202
+ Post.search do
203
+ with(:category_ids, [1, 3, 5])
204
+ end
205
+
206
+ # Posts published since a week ago
207
+ Post.search do
208
+ with(:published_at).greater_than(1.week.ago)
209
+ end
210
+ ```
211
+
212
+ #### Negative Restrictions
213
+
214
+ ```ruby
215
+ # Posts not in category 1 or 3
216
+ Post.search do
217
+ without(:category_ids, [1, 3])
218
+ end
219
+
220
+ # All examples in "positive" also work negated using `without`
221
+ ```
222
+
223
+ #### Disjunctions and Conjunctions
224
+
225
+ ```ruby
226
+ # Posts that do not have an expired time or have not yet expired
227
+ Post.search do
228
+ any_of do
229
+ with(:expired_at).greater_than(Time.now)
230
+ with(:expired_at, nil)
231
+ end
232
+ end
233
+ ```
234
+
235
+ ```ruby
236
+ # Posts with blog_id 1 and author_id 2
237
+ Post.search do
238
+ all_of do
239
+ with(:blog_id, 1)
240
+ with(:author_id, 2)
241
+ end
242
+ end
243
+ ```
244
+
245
+ Disjunctions and conjunctions may be nested
246
+
247
+ ```ruby
248
+ Post.search do
249
+ any_of do
250
+ with(:blog_id, 1)
251
+ all_of do
252
+ with(:blog_id, 2)
253
+ with(:category_ids, 3)
254
+ end
255
+ end
256
+ end
257
+ ```
258
+
259
+ #### Combined with Full-Text
260
+
261
+ Scopes/restrictions can be combined with full-text searching. The
262
+ scope/restriction pares down the objects that are searched for the
263
+ full-text term.
264
+
265
+ ```ruby
266
+ # Posts with blog_id 1 and 'pizza' in the title
267
+ Post.search do
268
+ with(:blog_id, 1)
269
+ fulltext("pizza")
270
+ end
271
+ ```
272
+
273
+ ### Pagination
274
+
275
+ **All results from Solr are paginated**
276
+
277
+ The results array that is returned has methods mixed in that allow it to
278
+ operate seamlessly with common pagination libraries like will\_paginate
279
+ and kaminari.
280
+
281
+ By default, Sunspot requests the first 30 results from Solr.
282
+
283
+ ```ruby
284
+ search = Post.search do
285
+ fulltext "pizza"
286
+ end
287
+
288
+ # Imagine there are 60 *total* results (at 30 results/page, that is two pages)
289
+ results = search.results # => Array with 30 Post elements
290
+
291
+ search.total # => 60
292
+
293
+ results.total_pages # => 2
294
+ results.first_page? # => true
295
+ results.last_page? # => false
296
+ results.previous_page # => nil
297
+ results.next_page # => 2
298
+ results.out_of_bounds? # => false
299
+ results.offset # => 0
300
+ ```
301
+
302
+ To retrieve the next page of results, recreate the search and use the
303
+ `paginate` method.
304
+
305
+ ```ruby
306
+ search = Post.search do
307
+ fulltext "pizza"
308
+ paginate :page => 2
309
+ end
310
+
311
+ # Again, imagine there are 60 total results; this is the second page
312
+ results = search.results # => Array with 30 Post elements
313
+
314
+ search.total # => 60
315
+
316
+ results.total_pages # => 2
317
+ results.first_page? # => false
318
+ results.last_page? # => true
319
+ results.previous_page # => 1
320
+ results.next_page # => nil
321
+ results.out_of_bounds? # => false
322
+ results.offset # => 30
323
+ ```
324
+
325
+ A custom number of results per page can be specified with the
326
+ `:per_page` option to `paginate`:
327
+
328
+ ```ruby
329
+ search = Post.search do
330
+ fulltext "pizza"
331
+ paginate :page => 1, :per_page => 50
332
+ end
333
+ ```
334
+
335
+ ### Faceting
336
+
337
+ Faceting is a feature of Solr that determines the number of documents
338
+ that match a given search *and* an additional criterion. This allows you
339
+ to build powerful drill-down interfaces for search.
340
+
341
+ Each facet returns zero or more rows, each of which represents a
342
+ particular criterion conjoined with the actual query being performed.
343
+ For **field facets**, each row represents a particular value for a given
344
+ field. For **query facets**, each row represents an arbitrary scope; the
345
+ facet itself is just a means of logically grouping the scopes.
346
+
347
+ #### Field Facets
348
+
349
+ ```ruby
350
+ # Posts that match 'pizza' returning counts for each :author_id
351
+ search = Post.search do
352
+ fulltext "pizza"
353
+ facet :author_id
354
+ end
355
+
356
+ search.facet(:author_id).rows.each do |facet|
357
+ puts "Author #{facet.value} has #{facet.count} pizza posts!"
358
+ end
359
+ ```
360
+
361
+ #### Query Facets
362
+
363
+ ```ruby
364
+ # Posts faceted by ranges of average ratings
365
+ search = Post.search do
366
+ facet(:average_rating) do
367
+ row(1.0..2.0) do
368
+ with(:average_rating, 1.0..2.0)
369
+ end
370
+ row(2.0..3.0) do
371
+ with(:average_rating, 2.0..3.0)
372
+ end
373
+ row(3.0..4.0) do
374
+ with(:average_rating, 3.0..4.0)
375
+ end
376
+ row(4.0..5.0) do
377
+ with(:average_rating, 4.0..5.0)
378
+ end
379
+ end
380
+ end
381
+
382
+ # e.g.,
383
+ # Number of posts with rating withing 1.0..2.0: 2
384
+ # Number of posts with rating withing 2.0..3.0: 1
385
+ search.facet(:average_rating).rows.each do |facet|
386
+ puts "Number of posts with rating withing #{facet.value}: #{facet.count}"
387
+ end
388
+ ```
389
+
390
+ ### Ordering
391
+
392
+ By default, Sunspot orders results by "score": the Solr-determined
393
+ relevancy metric. Sorting can be customized with the `order_by` method:
394
+
395
+ ```ruby
396
+ # Order by average rating, descending
397
+ Post.search do
398
+ fulltext("pizza")
399
+ order_by(:average_rating, :desc)
400
+ end
401
+
402
+ # Order by relevancy score and in the case of a tie, average rating
403
+ Post.search do
404
+ fulltext("pizza")
405
+
406
+ order_by(:score, :desc)
407
+ order_by(:average_rating, :desc)
408
+ end
409
+
410
+ # Randomized ordering
411
+ Post.search do
412
+ fulltext("pizza")
413
+ order_by(:random)
414
+ end
415
+ ```
416
+
417
+ ### Grouping
418
+
419
+ **Solr 3.3 and above**
420
+
421
+ Solr supports grouping documents, similar to an SQL `GROUP BY`. More
422
+ information about result grouping/field collapsing is available on the
423
+ [Solr Wiki](http://wiki.apache.org/solr/FieldCollapsing).
424
+
425
+ **Grouping is only supported on `string` fields that are not
426
+ multivalued. To group on a field of a different type (e.g., integer),
427
+ add a denormalized `string` type**
428
+
429
+ ```ruby
430
+ class Post < ActiveRecord::Base
431
+ searchable do
432
+ # Denormalized `string` field because grouping can only be performed
433
+ # on string fields
434
+ string(:blog_id_str) { |p| p.blog_id.to_s }
435
+ end
436
+ end
437
+
438
+ # Returns only the top scoring document per blog_id
439
+ search = Post.search do
440
+ group :blog_id_str
441
+ end
442
+
443
+ search.group(:blog_id_str).matches # Total number of matches to the query
444
+
445
+ search.group(:blog_id_str).groups.each do |group|
446
+ puts group.value # blog_id of the each document in the group
447
+
448
+ # By default, there is only one document per group (the highest
449
+ # scoring one); if `limit` is specified (see below), multiple
450
+ # documents can be returned per group
451
+ group.results.each do |result|
452
+ # ...
453
+ end
454
+ end
455
+ ```
456
+
457
+ Additional options are supported by the DSL:
458
+
459
+ ```ruby
460
+ # Returns the top 3 scoring documents per blog_id
461
+ Post.search do
462
+ group :blog_id_str do
463
+ limit 3
464
+ end
465
+ end
466
+
467
+ # Returns document ordered within each group by published_at (by
468
+ # default, the ordering is score)
469
+ Post.search do
470
+ group :blog_id_str do
471
+ order_by(:average_rating, :desc)
472
+ end
473
+ end
474
+
475
+ # Facet count is based on the most relevant document of each group
476
+ # matching the query (>= Solr 3.4)
477
+ Post.search do
478
+ group :blog_id_str do
479
+ truncate
480
+ end
481
+
482
+ facet :blog_id_str, :extra => :any
483
+ end
484
+ ```
485
+
486
+ ### Geospatial
487
+
488
+ **Experimental and unreleased. The DSL may change.**
489
+
490
+ Sunspot 2.0 supports geospatial features of Solr 3.1 and above.
491
+
492
+ Geospatial features require a field defined with `latlon`:
493
+
494
+ ```ruby
495
+ class Post < ActiveRecord::Base
496
+ searchable do
497
+ # ...
498
+ latlon(:location) { Sunspot::Util::Coordinates.new(lat, lon) }
499
+ end
500
+ end
501
+ ```
502
+
503
+ #### Filter By Radius
504
+
505
+ ```ruby
506
+ # Searches posts within 100 kilometers of (32, -68)
507
+ Post.search do
508
+ with(:location).in_radius(32, -68, 100)
509
+ end
510
+ ```
511
+
512
+ #### Filter By Radius (inexact with bbox)
513
+
514
+ ```ruby
515
+ # Searches posts within 100 kilometers of (32, -68) with `bbox`. This is
516
+ # an approximation so searches run quicker, but it may include other
517
+ # points that are slightly outside of the required distance
518
+ Post.search do
519
+ with(:location).in_radius(32, -68, 100, :bbox => true)
520
+ end
521
+ ```
522
+
523
+ #### Filter By Bounding Box
524
+
525
+ ```ruby
526
+ # Searches posts within the bounding box defined by the corners (45,
527
+ # -94) to (46, -93)
528
+ Post.search do
529
+ with(:location).in_bounding_box([45, -94], [46, -93])
530
+ end
531
+ ```
532
+
533
+ #### Sort By Distance
534
+
535
+ ```ruby
536
+ # Orders documents by closeness to (32, -68)
537
+ Post.search do
538
+ order_by_geodist(:location, 32, -68)
539
+ end
540
+ ```
541
+
542
+ ### Highlighting
543
+
544
+ Highlighting allows you to display snippets of the part of the document
545
+ that matched the query.
546
+
547
+ The fields you wish to highlight must be **stored**.
548
+
549
+ ```ruby
550
+ class Post < ActiveRecord::Base
551
+ searchable do
552
+ # ...
553
+ text :body, :stored => true
554
+ end
555
+ end
556
+ ```
557
+
558
+ Highlighting matches on the `body` field, for instance, can be acheived
559
+ like:
560
+
561
+ ```ruby
562
+ search = Post.search do
563
+ fulltext "pizza" do
564
+ highlight :body
565
+ end
566
+ end
567
+
568
+ # Will output something similar to:
569
+ # Post #1
570
+ # I really love *pizza*
571
+ # *Pizza* is my favorite thing
572
+ # Post #2
573
+ # Pepperoni *pizza* is delicious
574
+ search.hits.each do |hit|
575
+ puts "Post ##{hit.primary_key}"
576
+
577
+ hit.highlights(:body).each do |highlight|
578
+ puts " " + highlight.format { |word| "*#{word}*" }
579
+ end
580
+ end
581
+ ```
582
+
583
+ ### Functions
584
+
585
+ TODO
586
+
587
+ ### More Like This
588
+
589
+ Sunspot can extract related items using more_like_this. When searching
590
+ for similar items, you can pass a block with the following options:
591
+
592
+ * fields :field_1[, :field_2, ...]
593
+ * minimum_term_frequency ##
594
+ * minimum_document_frequency ##
595
+ * minimum_word_length ##
596
+ * maximum_word_length ##
597
+ * maximum_query_terms ##
598
+ * boost_by_relevance true/false
599
+
600
+ ```ruby
601
+ class Post < ActiveRecord::Base
602
+ searchable do
603
+ # The :more_like_this option must be set to true
604
+ text :body, :more_like_this => true
605
+ end
606
+ end
607
+
608
+ post = Post.first
609
+
610
+ results = Sunspot.more_like_this(post) do
611
+ fields :body
612
+ minimum_term_frequency 5
613
+ end
614
+ ```
615
+
616
+ ## Indexing In Depth
617
+
618
+ TODO
619
+
620
+ ### Index-Time Boosts
621
+
622
+ To specify that a field should be boosted in relation to other fields for
623
+ all queries, you can specify the boost at index time:
624
+
625
+ ```ruby
626
+ class Post < ActiveRecord::Base
627
+ searchable do
628
+ text :title, :boost => 5.0
629
+ text :body
630
+ end
631
+ end
632
+ ```
633
+
634
+ ### Stored Fields
635
+
636
+ Stored fields keep an original (untokenized/unanalyzed) version of their
637
+ contents in Solr.
638
+
639
+ Stored fields allow data to be retrieved without also hitting the
640
+ underlying database (usually an SQL server). They are also required for
641
+ highlighting and more like this queries.
642
+
643
+ Stored fields come at some performance cost in the Solr index, so use
644
+ them wisely.
645
+
646
+ ```ruby
647
+ class Post < ActiveRecord::Base
648
+ searchable do
649
+ text :body, :stored => true
650
+ end
651
+ end
652
+
653
+ # Retrieving stored contents without hitting the database
654
+ Post.search.hits.each do |hit|
655
+ puts hit.stored(:body)
656
+ end
657
+ ```
658
+
659
+ ## Hits vs. Results
660
+
661
+ Sunspot simply stores the type and primary key of objects in Solr.
662
+ When results are retrieved, those primary keys are used to load the
663
+ actual object (usually from an SQL database).
664
+
665
+ ```ruby
666
+ # Using #results pulls in the records from the object-relational
667
+ # mapper (e.g., ActiveRecord + a SQL server)
668
+ Post.search.results.each do |result|
669
+ puts result.body
670
+ end
671
+ ```
672
+
673
+ To access information about the results without querying the underlying
674
+ database, use `hits`:
675
+
676
+ ```ruby
677
+ # Using #hits gives back all information requested from Solr, but does
678
+ # not load the object from the object-relational mapper
679
+ Post.search.hits.each do |hit|
680
+ puts hit.stored(:body)
681
+ end
682
+ ```
683
+
684
+ If you need both the result (ORM-loaded object) and `Hit` (e.g., for
685
+ faceting, highlighting, etc...), you can use the convenience method
686
+ `each_hit_with_result`:
687
+
688
+ ```ruby
689
+ Post.search.each_hit_with_result do |hit, result|
690
+ # ...
691
+ end
692
+ ```
693
+
694
+ ## Reindexing Objects
695
+
696
+ If you are using Rails, objects are automatically indexed to Solr as a
697
+ part of the `save` callbacks.
698
+
699
+ If you make a change to the object's "schema" (code in the `searchable` block),
700
+ you must reindex all objects so the changes are reflected in Solr:
701
+
702
+ ```bash
703
+ bundle exec rake sunspot:solr:reindex
704
+
705
+ # or, to be specific to a certain model with a certain batch size:
706
+ bundle exec rake sunspot:solr:reindex[500,Post] # some shells will require escaping [ with \[ and ] with \]
707
+ ```
708
+
709
+ ## Use Without Rails
710
+
711
+ TODO
712
+
713
+ ## Manually Adjusting Solr Parameters
714
+
715
+ To add or modify parameters sent to Solr, use `adjust_solr_params`:
716
+
717
+ ```ruby
718
+ Post.search do
719
+ adjust_solr_params do |params|
720
+ params[:q] += " AND something_s:more"
721
+ end
722
+ end
723
+ ```
724
+
725
+ ## Session Proxies
726
+
727
+ TODO
728
+
729
+ ## Type Reference
730
+
731
+ TODO
732
+
733
+ ## Development
734
+
735
+ ### Running Tests
736
+
737
+ #### sunspot
738
+
739
+ Install the required gem dependencies:
740
+
741
+ ```bash
742
+ cd /path/to/sunspot/sunspot
743
+ bundle install
744
+ ```
745
+
746
+ Start a Solr instance on port 8983:
747
+
748
+ ```bash
749
+ bundle exec sunspot-solr start -p 8983
750
+ # or `bundle exec sunspot-solr run -p 8983` to run in foreground
751
+ ```
752
+
753
+ Run the tests:
754
+
755
+ ```bash
756
+ bundle exec rake spec
757
+ ```
758
+
759
+ If desired, stop the Solr instance:
760
+
761
+ ```bash
762
+ bundle exec sunspot-solr stop
763
+ ```
764
+
765
+ #### sunspot\_rails
766
+
767
+ Install the gem dependencies for `sunspot`:
768
+
769
+ ```bash
770
+ cd /path/to/sunspot/sunspot
771
+ bundle install
772
+ ```
773
+
774
+ Start a Solr instance on port 8983:
775
+
776
+ ```bash
777
+ bundle exec sunspot-solr start -p 8983
778
+ # or `bundle exec sunspot-solr run -p 8983` to run in foreground
779
+ ```
780
+
781
+ Navigate to the `sunspot_rails` directory:
782
+
783
+ ```bash
784
+ cd ../sunspot_rails
785
+ ```
786
+
787
+ Run the tests:
788
+
789
+ ```bash
790
+ rake spec # all Rails versions
791
+ rake spec RAILS=3.1.1 # specific Rails version only
792
+ ```
793
+
794
+ If desired, stop the Solr instance:
795
+
796
+ ```bash
797
+ cd ../sunspot
798
+ bundle exec sunspot-solr stop
799
+ ```
800
+
801
+ ### Generating Documentation
802
+
803
+ Install the `yard` and `redcarpet` gems:
804
+
805
+ ```bash
806
+ $ gem install yard redcarpet
807
+ ```
808
+
809
+ Uninstall the `rdiscount` gem, if installed:
810
+
811
+ ```bash
812
+ $ gem uninstall rdiscount
813
+ ```
814
+
815
+ Generate the documentation from topmost directory:
816
+
817
+ ```bash
818
+ $ yardoc -o docs */lib/**/*.rb - README.md
819
+ ```
820
+
821
+ ## Tutorials and Articles
822
+
823
+ * [Full Text Searching with Solr and Sunspot](http://collectiveidea.com/blog/archives/2011/03/08/full-text-searching-with-solr-and-sunspot/) (Collective Idea)
824
+ * [Full-text search in Rails with Sunspot](http://tech.favoritemedium.com/2010/01/full-text-search-in-rails-with-sunspot.html) (Tropical Software Observations)
825
+ * [Sunspot Full-text Search for Rails/Ruby](http://therailworld.com/posts/23-Sunspot-Full-text-Search-for-Rails-Ruby) (The Rail World)
826
+ * [A Few Sunspot Tips](http://blog.trydionel.com/2009/11/19/a-few-sunspot-tips/) (spiral_code)
827
+ * [Sunspot: A Solr-Powered Search Engine for Ruby](http://www.linux-mag.com/id/7341) (Linux Magazine)
828
+ * [Sunspot Showed Me the Light](http://bennyfreshness.com/2010/05/sunspot-helped-me-see-the-light/) (ben koonse)
829
+ * [RubyGems.org — A case study in upgrading to full-text search](http://blog.websolr.com/post/3505903537/rubygems-search-upgrade-1) (Websolr)
830
+ * [How to Implement Spatial Search with Sunspot and Solr](http://codequest.eu/articles/how-to-implement-spatial-search-with-sunspot-and-solr) (Code Quest)
831
+ * [Sunspot 1.2 with Spatial Solr Plugin 2.0](http://joelmats.wordpress.com/2011/02/23/getting-sunspot-1-2-with-spatial-solr-plugin-2-0-to-work/) (joelmats)
832
+ * [rails3 + heroku + sunspot : madness](http://anhaminha.tumblr.com/post/632682537/rails3-heroku-sunspot-madness) (anhaminha)
833
+ * [How to get full text search working with Sunspot](http://cookbook.hobocentral.net/recipes/57-how-to-get-full-text-search) (Hobo Cookbook)
834
+ * [Full text search with Sunspot in Rails](http://hemju.com/2011/01/04/full-text-search-with-sunspot-in-rail/) (hemju)
835
+ * [Using Sunspot for Free-Text Search with Redis](http://masonoise.wordpress.com/2010/02/06/using-sunspot-for-free-text-search-with-redis/) (While I Pondered...)
836
+ * [Fuzzy searching in SOLR with Sunspot](http://www.pipetodevnull.com/past/2010/8/5/fuzzy_searching_in_solr_with_sunspot/) (pipe :to => /dev/null)
837
+ * [Default scope with Sunspot](http://www.cloudspace.com/blog/2010/01/15/default-scope-with-sunspot/) (Cloudspace)
838
+ * [Index External Models with Sunspot/Solr](http://www.medihack.org/2011/03/19/index-external-models-with-sunspotsolr/) (Medihack)
839
+ * [Chef recipe for Sunspot in production](http://gist.github.com/336403)
840
+ * [Testing with Sunspot and Cucumber](http://collectiveidea.com/blog/archives/2011/05/25/testing-with-sunspot-and-cucumber/) (Collective Idea)
841
+ * [Cucumber and Sunspot](http://opensoul.org/2010/4/7/cucumber-and-sunspot) (opensoul.org)
842
+ * [Testing Sunspot with Cucumber](http://blog.trydionel.com/2010/02/06/testing-sunspot-with-cucumber/) (spiral_code)
843
+ * [Running cucumber features with sunspot_rails](http://blog.kabisa.nl/2010/02/03/running-cucumber-features-with-sunspot_rails) (Kabisa Blog)
844
+ * [Testing Sunspot with Test::Unit](http://timcowlishaw.co.uk/post/3179661158/testing-sunspot-with-test-unit) (Type Slowly)
845
+ * [How To Use Twitter Lists to Determine Influence](http://www.untitledstartup.com/2010/01/how-to-use-twitter-lists-to-determine-influence/) (Untitled Startup)
846
+ * [Sunspot Quickstart](http://wiki.websolr.com/index.php/Sunspot_Quickstart) (WebSolr)
847
+ * [Solr, and Sunspot](http://www.kuahyeow.com/2009/08/solr-and-sunspot.html) (YT!)
848
+ * [The Saga of the Switch](http://mrb.github.com/2010/04/08/the-saga-of-the-switch.html) (mrb -- includes comparison of Sunspot and Ultrasphinx)
849
+ * [Conditional Indexing with Sunspot](http://mikepackdev.com/blog_posts/19-conditional-indexing-with-sunspot) (mikepack)
850
+
851
+ ## License
852
+
853
+ Sunspot is distributed under the MIT License, copyright (c) 2008-2009 Mat Brown
@@ -1,11 +1,11 @@
1
1
  module Sunspot
2
2
  module Query
3
- #
3
+ #
4
4
  # The classes in this module implement query components that build sort
5
5
  # parameters for Solr. As well as regular sort on fields, there are several
6
6
  # "special" sorts that allow ordering for metrics calculated during the
7
7
  # search.
8
- #
8
+ #
9
9
  module Sort #:nodoc: all
10
10
  DIRECTIONS = {
11
11
  :asc => 'asc',
@@ -15,7 +15,7 @@ module Sunspot
15
15
  }
16
16
 
17
17
  class <<self
18
- #
18
+ #
19
19
  # Certain field names are "special", referring to specific non-field
20
20
  # sorts, which are generally by other metrics associated with hits.
21
21
  #
@@ -30,7 +30,7 @@ module Sunspot
30
30
  end
31
31
  end
32
32
 
33
- #
33
+ #
34
34
  # Base class for sorts. All subclasses should implement the #to_param
35
35
  # method, which is a string that is then concatenated with other sort
36
36
  # strings by the SortComposite to form the sort parameter.
@@ -42,11 +42,11 @@ module Sunspot
42
42
 
43
43
  private
44
44
 
45
- #
45
+ #
46
46
  # Translate fairly forgiving direction argument into solr direction
47
47
  #
48
48
  def direction_for_solr
49
- DIRECTIONS[@direction] ||
49
+ DIRECTIONS[@direction] ||
50
50
  raise(
51
51
  ArgumentError,
52
52
  "Unknown sort direction #{@direction}. Acceptable input is: #{DIRECTIONS.keys.map { |input| input.inspect } * ', '}"
@@ -54,7 +54,7 @@ module Sunspot
54
54
  end
55
55
  end
56
56
 
57
- #
57
+ #
58
58
  # A FieldSort is the usual kind of sort, by the value of a particular
59
59
  # field, ascending or descending
60
60
  #
@@ -71,17 +71,21 @@ module Sunspot
71
71
  end
72
72
  end
73
73
 
74
- #
74
+ #
75
75
  # A RandomSort uses Solr's random field functionality to sort results
76
76
  # (usually) randomly.
77
77
  #
78
78
  class RandomSort < Abstract
79
+ def initialize(options={:seed => rand(1<<16)}, direction=nil)
80
+ @seed, @direction = options[:seed], (direction || :asc).to_sym
81
+ end
82
+
79
83
  def to_param
80
- "random_#{rand(1<<16)} #{direction_for_solr}"
84
+ "random_#{@seed} #{direction_for_solr}"
81
85
  end
82
86
  end
83
87
 
84
- #
88
+ #
85
89
  # A ScoreSort sorts by keyword relevance score. This is only useful when
86
90
  # performing fulltext search.
87
91
  #
@@ -1,3 +1,3 @@
1
1
  module Sunspot
2
- VERSION = '2.0.4'
2
+ VERSION = '2.0.5'
3
3
  end
metadata CHANGED
@@ -1,10 +1,14 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: gojee-sunspot
3
- version: !ruby/object:Gem::Version
4
- version: 2.0.4
5
- prerelease:
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 2
7
+ - 0
8
+ - 5
9
+ version: 2.0.5
6
10
  platform: ruby
7
- authors:
11
+ authors:
8
12
  - Mat Brown
9
13
  - Peer Allan
10
14
  - Dmitriy Dzema
@@ -27,102 +31,91 @@ authors:
27
31
  autorequire:
28
32
  bindir: bin
29
33
  cert_chain: []
30
- date: 2012-09-03 00:00:00.000000000 Z
31
- dependencies:
32
- - !ruby/object:Gem::Dependency
34
+
35
+ date: 2012-11-05 00:00:00 -05:00
36
+ default_executable:
37
+ dependencies:
38
+ - !ruby/object:Gem::Dependency
33
39
  name: rsolr
34
- requirement: !ruby/object:Gem::Requirement
35
- none: false
36
- requirements:
37
- - - ~>
38
- - !ruby/object:Gem::Version
39
- version: 1.0.6
40
- type: :runtime
41
40
  prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- none: false
44
- requirements:
41
+ requirement: &id001 !ruby/object:Gem::Requirement
42
+ requirements:
45
43
  - - ~>
46
- - !ruby/object:Gem::Version
44
+ - !ruby/object:Gem::Version
45
+ segments:
46
+ - 1
47
+ - 0
48
+ - 6
47
49
  version: 1.0.6
48
- - !ruby/object:Gem::Dependency
49
- name: escape
50
- requirement: !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
53
- - - ~>
54
- - !ruby/object:Gem::Version
55
- version: 0.0.4
56
50
  type: :runtime
51
+ version_requirements: *id001
52
+ - !ruby/object:Gem::Dependency
53
+ name: escape
57
54
  prerelease: false
58
- version_requirements: !ruby/object:Gem::Requirement
59
- none: false
60
- requirements:
55
+ requirement: &id002 !ruby/object:Gem::Requirement
56
+ requirements:
61
57
  - - ~>
62
- - !ruby/object:Gem::Version
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ - 0
62
+ - 4
63
63
  version: 0.0.4
64
- - !ruby/object:Gem::Dependency
65
- name: pr_geohash
66
- requirement: !ruby/object:Gem::Requirement
67
- none: false
68
- requirements:
69
- - - ~>
70
- - !ruby/object:Gem::Version
71
- version: '1.0'
72
64
  type: :runtime
65
+ version_requirements: *id002
66
+ - !ruby/object:Gem::Dependency
67
+ name: pr_geohash
73
68
  prerelease: false
74
- version_requirements: !ruby/object:Gem::Requirement
75
- none: false
76
- requirements:
69
+ requirement: &id003 !ruby/object:Gem::Requirement
70
+ requirements:
77
71
  - - ~>
78
- - !ruby/object:Gem::Version
79
- version: '1.0'
80
- - !ruby/object:Gem::Dependency
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 1
75
+ - 0
76
+ version: "1.0"
77
+ type: :runtime
78
+ version_requirements: *id003
79
+ - !ruby/object:Gem::Dependency
81
80
  name: rspec
82
- requirement: !ruby/object:Gem::Requirement
83
- none: false
84
- requirements:
85
- - - ~>
86
- - !ruby/object:Gem::Version
87
- version: 2.6.0
88
- type: :development
89
81
  prerelease: false
90
- version_requirements: !ruby/object:Gem::Requirement
91
- none: false
92
- requirements:
82
+ requirement: &id004 !ruby/object:Gem::Requirement
83
+ requirements:
93
84
  - - ~>
94
- - !ruby/object:Gem::Version
85
+ - !ruby/object:Gem::Version
86
+ segments:
87
+ - 2
88
+ - 6
89
+ - 0
95
90
  version: 2.6.0
96
- - !ruby/object:Gem::Dependency
97
- name: hanna
98
- requirement: !ruby/object:Gem::Requirement
99
- none: false
100
- requirements:
101
- - - ! '>='
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
91
  type: :development
92
+ version_requirements: *id004
93
+ - !ruby/object:Gem::Dependency
94
+ name: hanna
105
95
  prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- none: false
108
- requirements:
109
- - - ! '>='
110
- - !ruby/object:Gem::Version
111
- version: '0'
112
- description: ! " Sunspot is a library providing a powerful, all-ruby API for the
113
- Solr search engine. Sunspot manages the configuration of persistent\n Ruby classes
114
- for search and indexing and exposes Solr's most powerful features through a collection
115
- of DSLs. Complex search operations\n can be performed without hand-writing any
116
- boolean queries or building Solr parameters by hand.\n"
96
+ requirement: &id005 !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ type: :development
104
+ version_requirements: *id005
105
+ description: " Sunspot is a library providing a powerful, all-ruby API for the Solr search engine. Sunspot manages the configuration of persistent\n Ruby classes for search and indexing and exposes Solr's most powerful features through a collection of DSLs. Complex search operations\n can be performed without hand-writing any boolean queries or building Solr parameters by hand.\n"
117
106
  email: mat@patch.com
118
107
  executables: []
108
+
119
109
  extensions: []
110
+
120
111
  extra_rdoc_files: []
121
- files:
112
+
113
+ files:
122
114
  - .gitignore
123
115
  - Gemfile
124
116
  - History.txt
125
117
  - LICENSE
118
+ - README.md
126
119
  - Rakefile
127
120
  - TODO
128
121
  - lib/light_config.rb
@@ -296,36 +289,41 @@ files:
296
289
  - tasks/rdoc.rake
297
290
  - tasks/schema.rake
298
291
  - tasks/todo.rake
292
+ has_rdoc: true
299
293
  homepage: http://outoftime.github.com/sunspot
300
294
  licenses: []
295
+
301
296
  post_install_message:
302
- rdoc_options:
297
+ rdoc_options:
303
298
  - --webcvs=http://github.com/outoftime/sunspot/tree/master/%s
304
299
  - --title
305
300
  - Sunspot - Solr-powered search for Ruby objects - API Documentation
306
301
  - --main
307
302
  - README.rdoc
308
- require_paths:
303
+ require_paths:
309
304
  - lib
310
- required_ruby_version: !ruby/object:Gem::Requirement
311
- none: false
312
- requirements:
313
- - - ! '>='
314
- - !ruby/object:Gem::Version
315
- version: '0'
316
- required_rubygems_version: !ruby/object:Gem::Requirement
317
- none: false
318
- requirements:
319
- - - ! '>='
320
- - !ruby/object:Gem::Version
321
- version: '0'
305
+ required_ruby_version: !ruby/object:Gem::Requirement
306
+ requirements:
307
+ - - ">="
308
+ - !ruby/object:Gem::Version
309
+ segments:
310
+ - 0
311
+ version: "0"
312
+ required_rubygems_version: !ruby/object:Gem::Requirement
313
+ requirements:
314
+ - - ">="
315
+ - !ruby/object:Gem::Version
316
+ segments:
317
+ - 0
318
+ version: "0"
322
319
  requirements: []
320
+
323
321
  rubyforge_project: sunspot
324
- rubygems_version: 1.8.24
322
+ rubygems_version: 1.3.6
325
323
  signing_key:
326
324
  specification_version: 3
327
325
  summary: Library for expressive, powerful interaction with the Solr search engine
328
- test_files:
326
+ test_files:
329
327
  - spec/api/adapters_spec.rb
330
328
  - spec/api/batcher_spec.rb
331
329
  - spec/api/binding_spec.rb