acts_as_solr_reloaded 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README.markdown +64 -0
- data/README.rdoc +93 -0
- data/Rakefile +71 -0
- data/TESTING_THE_PLUGIN +25 -0
- data/VERSION +1 -0
- data/config/solr.yml +14 -0
- data/config/solr_environment.rb +35 -0
- data/generators/dynamic_attributes_migration/dynamic_attributes_migration_generator.rb +7 -0
- data/generators/dynamic_attributes_migration/templates/migration.rb +15 -0
- data/generators/local_migration/local_migration_generator.rb +7 -0
- data/generators/local_migration/templates/migration.rb +16 -0
- data/lib/acts_as_solr.rb +65 -0
- data/lib/acts_as_solr/acts_methods.rb +363 -0
- data/lib/acts_as_solr/class_methods.rb +240 -0
- data/lib/acts_as_solr/common_methods.rb +89 -0
- data/lib/acts_as_solr/deprecation.rb +61 -0
- data/lib/acts_as_solr/dynamic_attribute.rb +3 -0
- data/lib/acts_as_solr/instance_methods.rb +194 -0
- data/lib/acts_as_solr/lazy_document.rb +18 -0
- data/lib/acts_as_solr/local.rb +4 -0
- data/lib/acts_as_solr/parser_methods.rb +248 -0
- data/lib/acts_as_solr/search_results.rb +74 -0
- data/lib/acts_as_solr/solr_fixtures.rb +13 -0
- data/lib/acts_as_solr/tasks.rb +10 -0
- data/lib/acts_as_solr/tasks/database.rake +16 -0
- data/lib/acts_as_solr/tasks/solr.rake +142 -0
- data/lib/acts_as_solr/tasks/test.rake +5 -0
- data/lib/solr.rb +26 -0
- data/lib/solr/connection.rb +177 -0
- data/lib/solr/document.rb +75 -0
- data/lib/solr/exception.rb +13 -0
- data/lib/solr/field.rb +36 -0
- data/lib/solr/importer.rb +19 -0
- data/lib/solr/importer/array_mapper.rb +26 -0
- data/lib/solr/importer/delimited_file_source.rb +38 -0
- data/lib/solr/importer/hpricot_mapper.rb +27 -0
- data/lib/solr/importer/mapper.rb +51 -0
- data/lib/solr/importer/solr_source.rb +41 -0
- data/lib/solr/importer/xpath_mapper.rb +35 -0
- data/lib/solr/indexer.rb +52 -0
- data/lib/solr/request.rb +26 -0
- data/lib/solr/request/add_document.rb +58 -0
- data/lib/solr/request/base.rb +36 -0
- data/lib/solr/request/commit.rb +29 -0
- data/lib/solr/request/delete.rb +48 -0
- data/lib/solr/request/dismax.rb +46 -0
- data/lib/solr/request/index_info.rb +22 -0
- data/lib/solr/request/modify_document.rb +46 -0
- data/lib/solr/request/optimize.rb +19 -0
- data/lib/solr/request/ping.rb +36 -0
- data/lib/solr/request/select.rb +54 -0
- data/lib/solr/request/spellcheck.rb +30 -0
- data/lib/solr/request/standard.rb +406 -0
- data/lib/solr/request/update.rb +23 -0
- data/lib/solr/response.rb +27 -0
- data/lib/solr/response/add_document.rb +17 -0
- data/lib/solr/response/base.rb +42 -0
- data/lib/solr/response/commit.rb +15 -0
- data/lib/solr/response/delete.rb +13 -0
- data/lib/solr/response/dismax.rb +8 -0
- data/lib/solr/response/index_info.rb +26 -0
- data/lib/solr/response/modify_document.rb +17 -0
- data/lib/solr/response/optimize.rb +14 -0
- data/lib/solr/response/ping.rb +26 -0
- data/lib/solr/response/ruby.rb +42 -0
- data/lib/solr/response/select.rb +17 -0
- data/lib/solr/response/spellcheck.rb +20 -0
- data/lib/solr/response/standard.rb +65 -0
- data/lib/solr/response/xml.rb +39 -0
- data/lib/solr/solrtasks.rb +27 -0
- data/lib/solr/util.rb +32 -0
- data/lib/solr/xml.rb +44 -0
- data/solr/README.txt +36 -0
- data/solr/etc/jetty.xml +212 -0
- data/solr/etc/webdefault.xml +379 -0
- data/solr/exampledocs/books.csv +11 -0
- data/solr/exampledocs/hd.xml +46 -0
- data/solr/exampledocs/ipod_other.xml +50 -0
- data/solr/exampledocs/ipod_video.xml +35 -0
- data/solr/exampledocs/locales.xml +16 -0
- data/solr/exampledocs/mem.xml +58 -0
- data/solr/exampledocs/monitor.xml +31 -0
- data/solr/exampledocs/monitor2.xml +30 -0
- data/solr/exampledocs/mp500.xml +39 -0
- data/solr/exampledocs/post.jar +0 -0
- data/solr/exampledocs/post.sh +28 -0
- data/solr/exampledocs/sd500.xml +33 -0
- data/solr/exampledocs/solr.xml +38 -0
- data/solr/exampledocs/spellchecker.xml +58 -0
- data/solr/exampledocs/test_utf8.sh +83 -0
- data/solr/exampledocs/utf8-example.xml +42 -0
- data/solr/exampledocs/vidcard.xml +52 -0
- data/solr/lib/jetty-6.1.3.jar +0 -0
- data/solr/lib/jetty-util-6.1.3.jar +0 -0
- data/solr/lib/jsp-2.1/ant-1.6.5.jar +0 -0
- data/solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
- data/solr/lib/jsp-2.1/jsp-2.1.jar +0 -0
- data/solr/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
- data/solr/lib/servlet-api-2.5-6.1.3.jar +0 -0
- data/solr/multicore/README.txt +3 -0
- data/solr/multicore/core0/conf/schema.xml +41 -0
- data/solr/multicore/core0/conf/solrconfig.xml +40 -0
- data/solr/multicore/core1/conf/schema.xml +41 -0
- data/solr/multicore/core1/conf/solrconfig.xml +40 -0
- data/solr/multicore/exampledocs/ipod_other.xml +34 -0
- data/solr/multicore/exampledocs/ipod_video.xml +22 -0
- data/solr/multicore/solr.xml +35 -0
- data/solr/solr/README.txt +52 -0
- data/solr/solr/bin/abc +190 -0
- data/solr/solr/bin/abo +190 -0
- data/solr/solr/bin/backup +117 -0
- data/solr/solr/bin/backupcleaner +142 -0
- data/solr/solr/bin/commit +133 -0
- data/solr/solr/bin/optimize +134 -0
- data/solr/solr/bin/readercycle +129 -0
- data/solr/solr/bin/rsyncd-disable +77 -0
- data/solr/solr/bin/rsyncd-enable +76 -0
- data/solr/solr/bin/rsyncd-start +145 -0
- data/solr/solr/bin/rsyncd-stop +105 -0
- data/solr/solr/bin/scripts-util +99 -0
- data/solr/solr/bin/snapcleaner +154 -0
- data/solr/solr/bin/snapinstaller +198 -0
- data/solr/solr/bin/snappuller +269 -0
- data/solr/solr/bin/snappuller-disable +77 -0
- data/solr/solr/bin/snappuller-enable +77 -0
- data/solr/solr/bin/snapshooter +136 -0
- data/solr/solr/conf/admin-extra.html +31 -0
- data/solr/solr/conf/elevate.xml +36 -0
- data/solr/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
- data/solr/solr/conf/protwords.txt +21 -0
- data/solr/solr/conf/schema.xml +132 -0
- data/solr/solr/conf/scripts.conf +24 -0
- data/solr/solr/conf/solrconfig.xml +906 -0
- data/solr/solr/conf/spellings.txt +2 -0
- data/solr/solr/conf/stopwords.txt +58 -0
- data/solr/solr/conf/synonyms.txt +31 -0
- data/solr/solr/conf/xslt/example.xsl +132 -0
- data/solr/solr/conf/xslt/example_atom.xsl +67 -0
- data/solr/solr/conf/xslt/example_rss.xsl +66 -0
- data/solr/solr/conf/xslt/luke.xsl +337 -0
- data/solr/solr/lib/localsolr.jar +0 -0
- data/solr/solr/lib/lucene-spatial-2.9-dev.jar +0 -0
- data/solr/start.jar +0 -0
- data/solr/webapps/solr.war +0 -0
- data/test/config/solr.yml +2 -0
- data/test/db/connections/mysql/connection.rb +11 -0
- data/test/db/connections/sqlite/connection.rb +8 -0
- data/test/db/migrate/001_create_books.rb +15 -0
- data/test/db/migrate/002_create_movies.rb +12 -0
- data/test/db/migrate/003_create_categories.rb +11 -0
- data/test/db/migrate/004_create_electronics.rb +16 -0
- data/test/db/migrate/005_create_authors.rb +12 -0
- data/test/db/migrate/006_create_postings.rb +9 -0
- data/test/db/migrate/007_create_posts.rb +13 -0
- data/test/db/migrate/008_create_gadgets.rb +11 -0
- data/test/db/migrate/009_create_dynamic_attributes.rb +15 -0
- data/test/db/migrate/010_create_advertises.rb +13 -0
- data/test/db/migrate/011_create_locals.rb +15 -0
- data/test/db/test.db +0 -0
- data/test/fixtures/advertises.yml +12 -0
- data/test/fixtures/authors.yml +9 -0
- data/test/fixtures/books.yml +13 -0
- data/test/fixtures/categories.yml +7 -0
- data/test/fixtures/db_definitions/mysql.sql +41 -0
- data/test/fixtures/dynamic_attributes.yml +11 -0
- data/test/fixtures/electronics.yml +49 -0
- data/test/fixtures/locals.yml +9 -0
- data/test/fixtures/movies.yml +9 -0
- data/test/fixtures/postings.yml +10 -0
- data/test/functional/acts_as_solr_test.rb +463 -0
- data/test/functional/association_indexing_test.rb +37 -0
- data/test/functional/faceted_search_test.rb +163 -0
- data/test/functional/multi_solr_search_test.rb +57 -0
- data/test/models/advertise.rb +6 -0
- data/test/models/author.rb +10 -0
- data/test/models/book.rb +10 -0
- data/test/models/category.rb +8 -0
- data/test/models/dynamic_attribute.rb +7 -0
- data/test/models/electronic.rb +25 -0
- data/test/models/gadget.rb +9 -0
- data/test/models/local.rb +7 -0
- data/test/models/movie.rb +17 -0
- data/test/models/novel.rb +2 -0
- data/test/models/post.rb +3 -0
- data/test/models/posting.rb +11 -0
- data/test/test_helper.rb +56 -0
- data/test/unit/acts_methods_shoulda.rb +95 -0
- data/test/unit/class_methods_shoulda.rb +85 -0
- data/test/unit/common_methods_shoulda.rb +111 -0
- data/test/unit/instance_methods_shoulda.rb +372 -0
- data/test/unit/lazy_document_shoulda.rb +34 -0
- data/test/unit/parser_instance.rb +19 -0
- data/test/unit/parser_methods_shoulda.rb +338 -0
- data/test/unit/solr_instance.rb +74 -0
- data/test/unit/test_helper.rb +24 -0
- metadata +290 -0
Binary file
|
Binary file
|
data/solr/start.jar
ADDED
Binary file
|
Binary file
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateBooks < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :books, :force => true do |t|
|
4
|
+
t.column :category_id, :integer
|
5
|
+
t.column :name, :string
|
6
|
+
t.column :author, :string
|
7
|
+
t.column :type, :string
|
8
|
+
t.column :published_on, :date
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
drop_table :books
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateElectronics < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :electronics, :force => true do |t|
|
4
|
+
t.column :name, :string
|
5
|
+
t.column :manufacturer, :string
|
6
|
+
t.column :features, :string
|
7
|
+
t.column :category, :string
|
8
|
+
t.column :price, :string
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :electronics
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreatePosts < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :posts, :force => true do |t|
|
4
|
+
t.column :name, :string
|
5
|
+
t.column :reply_counter, :integer
|
6
|
+
t.column :posted_at, :datetime
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.down
|
11
|
+
drop_table :posts
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateDynamicAttributes < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :dynamic_attributes do |t|
|
4
|
+
t.integer :dynamicable_id
|
5
|
+
t.string :dynamicable_type
|
6
|
+
t.string :name
|
7
|
+
t.text :value
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
drop_table :dynamic_attributes
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateLocals < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :locals do |t|
|
4
|
+
t.integer :localizable_id
|
5
|
+
t.string :localizable_type
|
6
|
+
t.string :latitude
|
7
|
+
t.string :longitude
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
drop_table :locals
|
14
|
+
end
|
15
|
+
end
|
data/test/db/test.db
ADDED
Binary file
|
@@ -0,0 +1,9 @@
|
|
1
|
+
tom_clancy:
|
2
|
+
id: 1
|
3
|
+
name: Tom Clancy
|
4
|
+
biography: Tom Clancy (born 1947) writes novels of adventure and espionage in the international military-industrial complex that have earned him enormous popularity in the 1980s as a creator of the "techno-thriller" genre.
|
5
|
+
|
6
|
+
stephen_king:
|
7
|
+
id: 2
|
8
|
+
name: Stephen King
|
9
|
+
biography: Stephen King (born 1947) is a prolific and immensely popular author of horror fiction. In his works, King blends elements of the traditional gothic tale with those of the modern psychological thriller, detective, and science fiction genres.
|
@@ -0,0 +1,13 @@
|
|
1
|
+
splinter_cell:
|
2
|
+
id: 1
|
3
|
+
category_id: 1
|
4
|
+
name: Splinter Cell
|
5
|
+
author: Tom Clancy
|
6
|
+
published_on: <%= Date.today - 1.year %>
|
7
|
+
|
8
|
+
ruby:
|
9
|
+
id: 2
|
10
|
+
category_id: 2
|
11
|
+
name: Ruby for Dummies
|
12
|
+
author: Peter McPeterson
|
13
|
+
published_on: <%= Date.today - 2.years %>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
DROP DATABASE IF EXISTS `actsassolr_tests`;
|
2
|
+
CREATE DATABASE IF NOT EXISTS `actsassolr_tests`;
|
3
|
+
USE `actsassolr_tests`
|
4
|
+
|
5
|
+
CREATE TABLE `books` (
|
6
|
+
`id` int(11) NOT NULL auto_increment,
|
7
|
+
`category_id` int(11),
|
8
|
+
`name` varchar(200) default NULL,
|
9
|
+
`author` varchar(200) default NULL,
|
10
|
+
PRIMARY KEY (`id`)
|
11
|
+
);
|
12
|
+
|
13
|
+
CREATE TABLE `movies` (
|
14
|
+
`id` int(11) NOT NULL auto_increment,
|
15
|
+
`name` varchar(200) default NULL,
|
16
|
+
`description` varchar(255) default NULL,
|
17
|
+
PRIMARY KEY (`id`)
|
18
|
+
);
|
19
|
+
|
20
|
+
CREATE TABLE `categories` (
|
21
|
+
`id` int(11) NOT NULL auto_increment,
|
22
|
+
`name` varchar(200) default NULL,
|
23
|
+
PRIMARY KEY (`id`)
|
24
|
+
);
|
25
|
+
|
26
|
+
CREATE TABLE `electronics` (
|
27
|
+
`id` int(11) NOT NULL auto_increment,
|
28
|
+
`name` varchar(200) default NULL,
|
29
|
+
`manufacturer` varchar(255) default NULL,
|
30
|
+
`features` varchar(255) default NULL,
|
31
|
+
`category` varchar(255) default NULL,
|
32
|
+
`price` varchar(20) default NULL,
|
33
|
+
PRIMARY KEY (`id`)
|
34
|
+
);
|
35
|
+
|
36
|
+
CREATE TABLE `authors` (
|
37
|
+
`id` int(11) NOT NULL auto_increment,
|
38
|
+
`name` varchar(200) default NULL,
|
39
|
+
`biography` text default NULL,
|
40
|
+
PRIMARY KEY (`id`)
|
41
|
+
);
|
@@ -0,0 +1,49 @@
|
|
1
|
+
ipod_video:
|
2
|
+
id: 1
|
3
|
+
name: Apple 60 GB Memory iPod with Video Playback Black
|
4
|
+
manufacturer: Apple Computer Inc.
|
5
|
+
features: iTunes, Podcasts, Audiobooks
|
6
|
+
category: Electronics
|
7
|
+
price: 599.00
|
8
|
+
created_at: <%= (Time.now - 1.year).utc %>
|
9
|
+
updated_at: <%= (Time.now - 1.month).utc %>
|
10
|
+
|
11
|
+
dell_monitor:
|
12
|
+
id: 2
|
13
|
+
name: Dell Widescreen UltraSharp 3007WFP
|
14
|
+
manufacturer: Dell, Inc
|
15
|
+
features: 30" TFT active matrix LCD, 2560 x 1600, .25mm dot pitch, 700:1 contrast
|
16
|
+
category: Electronics
|
17
|
+
price: 750.00
|
18
|
+
created_at: <%= (Time.now - 1.year).utc %>
|
19
|
+
updated_at: <%= (Time.now - 1.month).utc %>
|
20
|
+
|
21
|
+
samsung_hd:
|
22
|
+
id: 3
|
23
|
+
name: Samsung SpinPoint P120 SP2514N - hard drive - 250 GB of Memory Storage - ATA-133
|
24
|
+
manufacturer: Samsung Electronics Co. Ltd.
|
25
|
+
features: 7200RPM, 8MB cache, IDE Ultra ATA-133
|
26
|
+
category: Hard Drive
|
27
|
+
price: 319.00
|
28
|
+
created_at: <%= (Time.now - 2.years).utc %>
|
29
|
+
updated_at: <%= (Time.now - 2.months).utc %>
|
30
|
+
|
31
|
+
corsair_ram:
|
32
|
+
id: 4
|
33
|
+
name: CORSAIR XMS 2GB (2 x 1GB) 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) Dual Channel Kit System Memory - Retail
|
34
|
+
manufacturer: Corsair Microsystems Inc.
|
35
|
+
features: CAS latency 2, 2-3-3-6 timing, 2.75v, unbuffered, heat-spreader
|
36
|
+
category: Memory
|
37
|
+
price: 155.00
|
38
|
+
created_at: <%= (Time.now - 6.years).utc %>
|
39
|
+
updated_at: <%= (Time.now - 3.months).utc %>
|
40
|
+
|
41
|
+
a_data_ram:
|
42
|
+
id: 5
|
43
|
+
name: A-DATA V-Series 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - OEM
|
44
|
+
manufacturer: A-DATA Technology Inc.
|
45
|
+
features: CAS latency 3, 2.7v
|
46
|
+
category: Memory
|
47
|
+
price: 65.79
|
48
|
+
created_at: <%= (Time.now - 9.years).utc %>
|
49
|
+
updated_at: <%= (Time.now - 4.months).utc %>
|
@@ -0,0 +1,463 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "#{File.dirname(File.expand_path(__FILE__))}/../test_helper"
|
3
|
+
|
4
|
+
class ActsAsSolrTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
fixtures :books, :movies, :electronics, :postings, :authors, :advertises
|
7
|
+
|
8
|
+
DynamicAttribute.delete_all
|
9
|
+
Advertise.first.dynamic_attributes.create! :name => 'Description', :value => 'A very cool bike'
|
10
|
+
Advertise.first.dynamic_attributes.create! :name => 'Price', :value => '1000'
|
11
|
+
|
12
|
+
Local.delete_all
|
13
|
+
Local.create! :localizable => Advertise.find(1), :longitude => '-77.4027', :latitude => '39.36'
|
14
|
+
Local.create! :localizable => Advertise.find(2), :longitude => '77.4027', :latitude => '-38.36'
|
15
|
+
|
16
|
+
# Inserting new data into Solr and making sure it's getting indexed
|
17
|
+
def test_insert_new_data
|
18
|
+
assert_equal 2, Book.count_by_solr('ruby OR splinter OR bob')
|
19
|
+
b = Book.create(:name => "Fuze in action", :author => "Bob Bobber", :category_id => 1)
|
20
|
+
assert b.valid?
|
21
|
+
assert_equal 3, Book.count_by_solr('ruby OR splinter OR bob')
|
22
|
+
end
|
23
|
+
|
24
|
+
# Check the type column stored in the index isn't stemmed by SOLR. If it is stemmed,
|
25
|
+
# then both Post and Posting will be stored as type:Post, so a query for Posts will
|
26
|
+
# return Postings and vice versa
|
27
|
+
|
28
|
+
def test_insert_new_data_doesnt_stem_type
|
29
|
+
assert_equal 0, Post.count_by_solr('aardvark')
|
30
|
+
p = Posting.new :name => 'aardvark', :description => "An interesting animal"
|
31
|
+
p.guid = '12AB'
|
32
|
+
p.save!
|
33
|
+
assert_equal 0, Post.count_by_solr('aardvark')
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_type_determined_from_database_if_not_explicitly_set
|
37
|
+
assert Post.configuration[:solr_fields][:posted_at][:type] == :date
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_search_includes_subclasses
|
41
|
+
Novel.create! :name => 'Wuthering Heights', :author => 'Emily Bronte'
|
42
|
+
Book.create! :name => 'Jane Eyre', :author => 'Charlotte Bronte'
|
43
|
+
assert_equal 1, Novel.find_by_solr('Bronte').total_hits
|
44
|
+
assert_equal 2, Book.find_by_solr('Bronte').total_hits
|
45
|
+
end
|
46
|
+
|
47
|
+
# Testing basic solr search:
|
48
|
+
# Model.find_by_solr 'term'
|
49
|
+
# Note that you're able to mix free-search with fields and boolean operators
|
50
|
+
def test_find_by_solr_ruby
|
51
|
+
['ruby', 'dummy', 'name:ruby', 'name:dummy', 'name:ruby AND author:peter',
|
52
|
+
'author:peter AND ruby', 'peter dummy'].each do |term|
|
53
|
+
records = Book.find_by_solr term
|
54
|
+
assert_equal 1, records.total
|
55
|
+
assert_equal "Peter McPeterson", records.docs.first.author
|
56
|
+
assert_equal "Ruby for Dummies", records.docs.first.name
|
57
|
+
assert_equal ({"id" => 2,
|
58
|
+
"category_id" => 2,
|
59
|
+
"name" => "Ruby for Dummies",
|
60
|
+
"author" => "Peter McPeterson", "published_on" => (Date.today - 2.years), "type" => nil}), records.docs.first.attributes
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Testing basic solr search:
|
65
|
+
# Model.find_by_solr 'term'
|
66
|
+
# Note that you're able to mix free-search with fields and boolean operators
|
67
|
+
def test_find_by_solr_splinter
|
68
|
+
['splinter', 'name:splinter', 'name:splinter AND author:clancy',
|
69
|
+
'author:clancy AND splinter', 'cell tom'].each do |term|
|
70
|
+
records = Book.find_by_solr term
|
71
|
+
assert_equal 1, records.total
|
72
|
+
assert_equal "Splinter Cell", records.docs.first.name
|
73
|
+
assert_equal "Tom Clancy", records.docs.first.author
|
74
|
+
assert_equal ({"id" => 1, "category_id" => 1, "name" => "Splinter Cell",
|
75
|
+
"author" => "Tom Clancy", "published_on" => (Date.today - 1.year), "type" => nil}), records.docs.first.attributes
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Testing basic solr search:
|
80
|
+
# Model.find_by_solr 'term'
|
81
|
+
# Note that you're able to mix free-search with fields and boolean operators
|
82
|
+
def test_find_by_solr_ruby_or_splinter
|
83
|
+
['ruby OR splinter', 'ruby OR author:tom', 'name:cell OR author:peter', 'dummy OR cell'].each do |term|
|
84
|
+
records = Book.find_by_solr term
|
85
|
+
assert_equal 2, records.total
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Testing search in indexed field methods:
|
90
|
+
#
|
91
|
+
# class Movie < ActiveRecord::Base
|
92
|
+
# acts_as_solr :fields => [:name, :description, :current_time]
|
93
|
+
#
|
94
|
+
# def current_time
|
95
|
+
# Time.now.to_s
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# The method current_time above gets indexed as being part of the
|
101
|
+
# Movie model and it's available for search as well
|
102
|
+
def test_find_with_dynamic_fields
|
103
|
+
date = Time.now.strftime('%b %d %Y')
|
104
|
+
["dynamite AND #{date}", "description:goofy AND #{date}", "goofy napoleon #{date}",
|
105
|
+
"goofiness #{date}"].each do |term|
|
106
|
+
records = Movie.find_by_solr term
|
107
|
+
assert_equal 1, records.total
|
108
|
+
assert_equal ({"id" => 1, "name" => "Napoleon Dynamite",
|
109
|
+
"description" => "Cool movie about a goofy guy"}), records.docs.first.attributes
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Testing basic solr search that returns just the ids instead of the objects:
|
114
|
+
# Model.find_id_by_solr 'term'
|
115
|
+
# Note that you're able to mix free-search with fields and boolean operators
|
116
|
+
def test_find_id_by_solr_ruby
|
117
|
+
['ruby', 'dummy', 'name:ruby', 'name:dummy', 'name:ruby AND author:peter',
|
118
|
+
'author:peter AND ruby'].each do |term|
|
119
|
+
records = Book.find_id_by_solr term
|
120
|
+
assert_equal 1, records.docs.size
|
121
|
+
assert_equal [2], records.docs
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Testing basic solr search that returns just the ids instead of the objects:
|
126
|
+
# Model.find_id_by_solr 'term'
|
127
|
+
# Note that you're able to mix free-search with fields and boolean operators
|
128
|
+
def test_find_id_by_solr_splinter
|
129
|
+
['splinter', 'name:splinter', 'name:splinter AND author:clancy',
|
130
|
+
'author:clancy AND splinter'].each do |term|
|
131
|
+
records = Book.find_id_by_solr term
|
132
|
+
assert_equal 1, records.docs.size
|
133
|
+
assert_equal [1], records.docs
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Testing basic solr search that returns just the ids instead of the objects:
|
138
|
+
# Model.find_id_by_solr 'term'
|
139
|
+
# Note that you're able to mix free-search with fields and boolean operators
|
140
|
+
def test_find_id_by_solr_ruby_or_splinter
|
141
|
+
['ruby OR splinter', 'ruby OR author:tom', 'name:cell OR author:peter',
|
142
|
+
'dummy OR cell'].each do |term|
|
143
|
+
records = Book.find_id_by_solr term
|
144
|
+
assert_equal 2, records.docs.size
|
145
|
+
assert_equal [1,2], records.docs
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Testing basic solr search that returns the total number of records found:
|
150
|
+
# Model.find_count_by_solr 'term'
|
151
|
+
# Note that you're able to mix free-search with fields and boolean operators
|
152
|
+
def test_count_by_solr
|
153
|
+
['ruby', 'dummy', 'name:ruby', 'name:dummy', 'name:ruby AND author:peter',
|
154
|
+
'author:peter AND ruby'].each do |term|
|
155
|
+
assert_equal 1, Book.count_by_solr(term), "there should only be 1 result for search: #{term}"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Testing basic solr search that returns the total number of records found:
|
160
|
+
# Model.find_count_by_solr 'term'
|
161
|
+
# Note that you're able to mix free-search with fields and boolean operators
|
162
|
+
def test_count_by_solr_splinter
|
163
|
+
['splinter', 'name:splinter', 'name:splinter AND author:clancy',
|
164
|
+
'author:clancy AND splinter', 'author:clancy cell'].each do |term|
|
165
|
+
assert_equal 1, Book.count_by_solr(term)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Testing basic solr search that returns the total number of records found:
|
170
|
+
# Model.find_count_by_solr 'term'
|
171
|
+
# Note that you're able to mix free-search with fields and boolean operators
|
172
|
+
def test_count_by_solr_ruby_or_splinter
|
173
|
+
['ruby OR splinter', 'ruby OR author:tom', 'name:cell OR author:peter', 'dummy OR cell'].each do |term|
|
174
|
+
assert_equal 2, Book.count_by_solr(term)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# Testing basic solr search with additional options:
|
179
|
+
# Model.find_count_by_solr 'term', :limit => 10, :offset => 0
|
180
|
+
def test_find_with_options
|
181
|
+
[1,2].each do |count|
|
182
|
+
records = Book.find_by_solr 'ruby OR splinter', :limit => count
|
183
|
+
assert_equal count, records.docs.size
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Testing self.rebuild_solr_index
|
188
|
+
# - It makes sure the index is rebuilt after a data has been lost
|
189
|
+
def test_rebuild_solr_index
|
190
|
+
assert_equal 1, Book.count_by_solr('splinter')
|
191
|
+
|
192
|
+
Book.find(:first).solr_destroy
|
193
|
+
assert_equal 0, Book.count_by_solr('splinter')
|
194
|
+
|
195
|
+
Book.rebuild_solr_index
|
196
|
+
assert_equal 1, Book.count_by_solr('splinter')
|
197
|
+
end
|
198
|
+
|
199
|
+
# Testing instance methods:
|
200
|
+
# - solr_save
|
201
|
+
# - solr_destroy
|
202
|
+
def test_solr_save_and_solr_destroy
|
203
|
+
assert_equal 1, Book.count_by_solr('splinter')
|
204
|
+
|
205
|
+
Book.find(:first).solr_destroy
|
206
|
+
assert_equal 0, Book.count_by_solr('splinter')
|
207
|
+
|
208
|
+
Book.find(:first).solr_save
|
209
|
+
assert_equal 1, Book.count_by_solr('splinter')
|
210
|
+
end
|
211
|
+
|
212
|
+
# Testing the order of results
|
213
|
+
def test_find_returns_records_in_order
|
214
|
+
records = Book.find_by_solr 'ruby^5 OR splinter'
|
215
|
+
# we boosted ruby so ruby should come first
|
216
|
+
|
217
|
+
assert_equal 2, records.total
|
218
|
+
assert_equal 'Ruby for Dummies', records.docs.first.name
|
219
|
+
assert_equal 'Splinter Cell', records.docs.last.name
|
220
|
+
end
|
221
|
+
|
222
|
+
# Testing solr search with optional :order argument
|
223
|
+
def _test_with_order_option
|
224
|
+
records = Movie.find_by_solr 'office^5 OR goofiness'
|
225
|
+
assert_equal 'Hypnotized dude loves fishing but not working', records.docs.first.description
|
226
|
+
assert_equal 'Cool movie about a goofy guy', records.docs.last.description
|
227
|
+
|
228
|
+
records = Movie.find_by_solr 'office^5 OR goofiness', :order => 'description asc'
|
229
|
+
assert_equal 'Cool movie about a goofy guy', records.docs.first.description
|
230
|
+
assert_equal 'Hypnotized dude loves fishing but not working', records.docs.last.description
|
231
|
+
end
|
232
|
+
|
233
|
+
# Testing search with omitted :field_types should
|
234
|
+
# return the same result set as if when we use it
|
235
|
+
def test_omit_field_types_in_search
|
236
|
+
records = Electronic.find_by_solr "price:[200 TO 599.99]"
|
237
|
+
assert_match(/599/, records.docs.first.price)
|
238
|
+
assert_match(/319/, records.docs.last.price)
|
239
|
+
|
240
|
+
records = Electronic.find_by_solr "price:[200 TO 599.99]", :order => 'price asc'
|
241
|
+
assert_match(/319/, records.docs.first.price)
|
242
|
+
assert_match(/599/, records.docs.last.price)
|
243
|
+
|
244
|
+
end
|
245
|
+
|
246
|
+
# Test to make sure the result returned when no matches
|
247
|
+
# are found has the same structure when there are results
|
248
|
+
def test_returns_no_matches
|
249
|
+
records = Book.find_by_solr 'rubyist'
|
250
|
+
assert_equal [], records.docs
|
251
|
+
assert_equal 0, records.total
|
252
|
+
|
253
|
+
records = Book.find_id_by_solr 'rubyist'
|
254
|
+
assert_equal [], records.docs
|
255
|
+
assert_equal 0, records.total
|
256
|
+
|
257
|
+
records = Book.find_by_solr 'rubyist', :facets => {}
|
258
|
+
assert_equal [], records.docs
|
259
|
+
assert_equal 0, records.total
|
260
|
+
assert_equal({"facet_fields"=>[]}, records.facets)
|
261
|
+
end
|
262
|
+
|
263
|
+
|
264
|
+
# Testing the :exclude_fields option when set in the
|
265
|
+
# model to make sure it doesn't get indexed
|
266
|
+
def test_exclude_fields_option
|
267
|
+
records = Electronic.find_by_solr 'audiobooks OR latency'
|
268
|
+
assert records.docs.empty?
|
269
|
+
assert_equal 0, records.total
|
270
|
+
|
271
|
+
assert_nothing_raised{
|
272
|
+
records = Electronic.find_by_solr 'features:audiobooks'
|
273
|
+
assert records.docs.empty?
|
274
|
+
assert_equal 0, records.total
|
275
|
+
}
|
276
|
+
end
|
277
|
+
|
278
|
+
# Testing the :auto_commit option set to false in the model
|
279
|
+
# should not send the commit command to Solr
|
280
|
+
def test_auto_commit_turned_off
|
281
|
+
assert_equal 0, Author.count_by_solr('raymond chandler')
|
282
|
+
|
283
|
+
original_count = Author.count
|
284
|
+
Author.create(:name => 'Raymond Chandler', :biography => 'Writes noirish detective stories')
|
285
|
+
|
286
|
+
assert_equal original_count + 1, Author.count
|
287
|
+
assert_equal 0, Author.count_by_solr('raymond chandler')
|
288
|
+
end
|
289
|
+
|
290
|
+
# Testing models that use a different key as the primary key
|
291
|
+
def test_search_on_model_with_string_id_field
|
292
|
+
records = Posting.find_by_solr 'first^5 OR second'
|
293
|
+
assert_equal 2, records.total
|
294
|
+
assert_equal 'ABC-123', records.docs.first.guid
|
295
|
+
assert_equal 'DEF-456', records.docs.last.guid
|
296
|
+
end
|
297
|
+
|
298
|
+
# Making sure the result set is ordered correctly even on
|
299
|
+
# models that use a different key as the primary key
|
300
|
+
def test_records_in_order_on_model_with_string_id_field
|
301
|
+
records = Posting.find_by_solr 'first OR second^5'
|
302
|
+
assert_equal 2, records.total
|
303
|
+
assert_equal 'DEF-456', records.docs.first.guid
|
304
|
+
assert_equal 'ABC-123', records.docs.last.guid
|
305
|
+
end
|
306
|
+
|
307
|
+
# Making sure the records are added when passing a batch size
|
308
|
+
# to rebuild_solr_index
|
309
|
+
def test_using_rebuild_solr_index_with_batch
|
310
|
+
assert_equal 2, Movie.count_by_solr('office OR napoleon')
|
311
|
+
Movie.find(:all).each(&:solr_destroy)
|
312
|
+
assert_equal 0, Movie.count_by_solr('office OR napoleon')
|
313
|
+
|
314
|
+
Movie.rebuild_solr_index 100
|
315
|
+
assert_equal 2, Movie.count_by_solr('office OR napoleon')
|
316
|
+
end
|
317
|
+
|
318
|
+
# Making sure find_by_solr with scores actually return the scores
|
319
|
+
# for each individual record
|
320
|
+
def test_find_by_solr_with_score
|
321
|
+
books = Book.find_by_solr 'ruby^10 OR splinter', :scores => true
|
322
|
+
|
323
|
+
assert_equal 2, books.total
|
324
|
+
assert (books.max_score >= 0.3 && books.max_score <= 0.6)
|
325
|
+
|
326
|
+
books.records.each { |book| assert_not_nil book.solr_score }
|
327
|
+
assert (books.docs.first.solr_score >= 0.3 && books.docs.first.solr_score <= 0.6)
|
328
|
+
assert (books.docs.last.solr_score < books.docs.first.solr_score)
|
329
|
+
end
|
330
|
+
|
331
|
+
# Making sure nothing breaks when html entities are inside
|
332
|
+
# the content to be indexed; and on the search as well.
|
333
|
+
def test_index_and_search_with_html_entities
|
334
|
+
description = "
|
335
|
+
inverted exclamation mark ¡ ¡
|
336
|
+
¤ currency ¤ ¤
|
337
|
+
¢ cent ¢ ¢
|
338
|
+
£ pound £ £
|
339
|
+
¥ yen ¥ ¥
|
340
|
+
¦ broken vertical bar ¦ ¦
|
341
|
+
§ section § §
|
342
|
+
¨ spacing diaeresis ¨ ¨
|
343
|
+
© copyright © ©
|
344
|
+
ª feminine ordinal indicator ª ª
|
345
|
+
« angle quotation mark (left) « «
|
346
|
+
¬ negation ¬ ¬
|
347
|
+
soft hyphen ­ ­
|
348
|
+
® registered trademark ® ®
|
349
|
+
™ trademark ™ ™
|
350
|
+
¯ spacing macron ¯ ¯
|
351
|
+
° degree ° °
|
352
|
+
± plus-or-minus ± ±
|
353
|
+
² superscript 2 ² ²
|
354
|
+
³ superscript 3 ³ ³
|
355
|
+
´ spacing acute ´ ´
|
356
|
+
µ micro µ µ
|
357
|
+
¶ paragraph ¶ ¶
|
358
|
+
· middle dot · ·
|
359
|
+
¸ spacing cedilla ¸ ¸
|
360
|
+
¹ superscript 1 ¹ ¹
|
361
|
+
º masculine ordinal indicator º º
|
362
|
+
» angle quotation mark (right) » »
|
363
|
+
¼ fraction 1/4 ¼ ¼
|
364
|
+
½ fraction 1/2 ½ ½
|
365
|
+
¾ fraction 3/4 ¾ ¾
|
366
|
+
¿ inverted question mark ¿ ¿
|
367
|
+
× multiplication × ×
|
368
|
+
÷ division ÷ ÷
|
369
|
+
♥ ♦ ♣ ♠"
|
370
|
+
|
371
|
+
author = Author.create(:name => "Test in Action™ - Copyright © Bob", :biography => description)
|
372
|
+
assert author.valid?
|
373
|
+
author.solr_commit
|
374
|
+
|
375
|
+
author = Author.find_by_solr 'trademark © ¾ ¡ £'
|
376
|
+
assert_equal 1, author.total
|
377
|
+
end
|
378
|
+
|
379
|
+
def test_operator_search_option
|
380
|
+
assert_nothing_raised {
|
381
|
+
books = Movie.find_by_solr "office napoleon", :operator => :or
|
382
|
+
assert_equal 2, books.total
|
383
|
+
|
384
|
+
books = Movie.find_by_solr "office napoleon", :operator => :and
|
385
|
+
assert_equal 0, books.total
|
386
|
+
}
|
387
|
+
|
388
|
+
assert_raise RuntimeError do
|
389
|
+
Movie.find_by_solr "office napoleon", :operator => :bad
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
# Making sure find_by_solr with scores actually return the scores
|
394
|
+
# for each individual record and orders them accordingly
|
395
|
+
def test_find_by_solr_order_by_score
|
396
|
+
books = Book.find_by_solr 'ruby^10 OR splinter', {:scores => true, :order => 'score asc' }
|
397
|
+
assert (books.docs.collect(&:solr_score).compact.size == books.docs.size), "Each book should have a score"
|
398
|
+
assert (books.docs.last.solr_score >= 0.3 && books.docs.last.solr_score <= 0.6)
|
399
|
+
|
400
|
+
books = Book.find_by_solr 'ruby^10 OR splinter', {:scores => true, :order => 'score desc' }
|
401
|
+
assert (books.docs.first.solr_score >= 0.3 && books.docs.first.solr_score <= 0.6)
|
402
|
+
assert (books.docs.last.solr_score < books.docs.first.solr_score)
|
403
|
+
end
|
404
|
+
|
405
|
+
# Search based on fields with the :date format
|
406
|
+
def test_indexed_date_field_format
|
407
|
+
movies = Movie.find_by_solr 'time_on_xml:[NOW-1DAY TO NOW]'
|
408
|
+
assert_equal 2, movies.total
|
409
|
+
end
|
410
|
+
|
411
|
+
def test_query_time_is_returned
|
412
|
+
results = Book.find_by_solr('ruby')
|
413
|
+
assert_not_nil(results.query_time)
|
414
|
+
assert_equal(results.query_time.class,Fixnum)
|
415
|
+
end
|
416
|
+
|
417
|
+
def test_should_not_index_the_record_when_offline_proc_returns_true
|
418
|
+
Gadget.search_disabled = true
|
419
|
+
gadget = Gadget.create(:name => "flipvideo mino")
|
420
|
+
assert_equal 0, Gadget.find_id_by_solr('flipvideo').total
|
421
|
+
end
|
422
|
+
|
423
|
+
def test_should_find_filtering_a_dynamic_attribute
|
424
|
+
records = Advertise.find_by_solr "description:bike"
|
425
|
+
assert_equal 1, records.total
|
426
|
+
end
|
427
|
+
|
428
|
+
def test_dynamic_attributes_are_faceted
|
429
|
+
records = Advertise.find_by_solr "Description:bike", :facets => { :fields => [:Description] }
|
430
|
+
expected = { "A very cool bike" => 1 }
|
431
|
+
assert_equal expected, records.facets['facet_fields']['Description_facet']
|
432
|
+
end
|
433
|
+
|
434
|
+
def test_search_is_an_alias_for_find_by_solr
|
435
|
+
assert_equal Advertise.find_by_solr("bike").docs, Advertise.search("bike").docs
|
436
|
+
end
|
437
|
+
|
438
|
+
def test_search_given_a_radius
|
439
|
+
records = Advertise.search "bike", :around => {:latitude => '-39.36',
|
440
|
+
:longitude => '77.4027',
|
441
|
+
:radius => 1}
|
442
|
+
assert_equal 0, records.total
|
443
|
+
end
|
444
|
+
|
445
|
+
def test_records_are_found_in_a_radius
|
446
|
+
records = Advertise.search "bike", :around => {:latitude => '39.36',
|
447
|
+
:longitude => '-77.4027',
|
448
|
+
:radius => 1}
|
449
|
+
assert_equal 1, records.total
|
450
|
+
end
|
451
|
+
|
452
|
+
def test_records_are_found_with_highlight
|
453
|
+
records = Book.find_by_solr "ruby", :highlight => { :fields => "name" }
|
454
|
+
assert_equal 1, records.total
|
455
|
+
end
|
456
|
+
|
457
|
+
def test_records_wiht_highlights_are_returned_properly
|
458
|
+
records = Book.find_by_solr "ruby", :highlight => { :fields => "name" }
|
459
|
+
expected = {"name"=>["<em>Ruby</em> for Dummies"]}
|
460
|
+
assert_equal expected, records.highlights.values.first
|
461
|
+
end
|
462
|
+
|
463
|
+
end
|