For one of my pet project based on Ruby on Rails, I’ve decided to implement Apache Solr as full-text search engine.
You can find a lot of tutorials with 5 min install and run, but:
None from Google first page results worked for me, so I’ve decided to write my own tutorial.
I’m using Rails 5.2.0.rc1 at this tutorial.
So first problem was about specifying github at Gemfile, because otherwise installer script fails:
gem 'sunspot_rails', github: 'sunspot/sunspot'
Let’s add another gems too:
group :test, :development do
gem 'sunspot_solr'
end
Great, now let’s run installer. This creates sunspot.yml file and config directory.
rails generate sunspot_rails:install
Let’s modify this file:
development:
solr:
hostname: localhost
port: 8983
log_level: INFO
Of course, you can run local solar instance with this command, like described in tutorials:
bundle exec rake sunspot:solr:start
But I prefer isolate Solr installation from my development environment, and use Docker for that stuff.
You can find Solr Docker images here.
So, let’s install and run Apache Solr as a Docker container:
$ docker run --name local_solr -d -p 8983:8983 -t solr
Unable to find image 'solr:latest' locally
latest: Pulling from library/solr
3e731ddb7fc9: Pull complete
47cafa6a79d0: Pull complete
79fcf5a213c7: Pull complete
fd532571c5d3: Pull complete
31600c9f9b48: Pull complete
78e8e9b5d10e: Pull complete
0710e619e883: Pull complete
e511da65ffab: Pull complete
bb09302d2063: Pull complete
b7f78fe84562: Pull complete
20ffa28013e1: Pull complete
2a11637a962c: Pull complete
f7027328bc49: Pull complete
5430f4c15186: Pull complete
Digest: sha256:54af530565af50f786b5d2a8c672b433eb4fafd6afac781a1c01f1c8753dd4c9
Status: Downloaded newer image for solr:latest
8b73acdca474b4343d7b12fa83f87f7268bed4089253438c560a845250e20280
Excellent! Let’s move ahead and add new core
$ docker exec -it --user=solr local_solr bin/solr create_core -c default
WARNING: Using _default configset. Data driven schema functionality is enabled by default, which is
NOT RECOMMENDED for production use.
To turn it off:
curl http://localhost:8983/solr/default/config -d '{"set-user-property": {"update.autoCreateFields":"false"}}'
Created new core 'default'
Now, you can open http://localhost:8983 in your browser, and control Apache Solr via Web UI:
Now let’s make our post model searchable:
class Post < ApplicationRecord
searchable do
text :title
text :body
end
end
Time to add some seeds:
100.times do |i|
Post.create(title: Faker::Book.title, body: Faker::Lorem.paragraph)
end
Good, let’s reindex our data:
marat at Marats-MacBook-Pro-2 in ~/Projects/smartapps/web/solaris (master●)
$ rake sunspot:reindex
[############################################################################################################################] [100/100] [100%] [00:00] [00:00] [710.90/s]
Now we can perform some search requests to our Solr instance:
irb(main):008:0> @search = Post.search { keywords 'Kill' }.results
D, [2018-02-23T17:12:19.412596 #57915] DEBUG -- : SOLR Request (9.4ms) [ path=select parameters={fq: ["type:Post"], q: "Kill", fl: "* score", qf: "title_text^2 body_text", defType: "edismax", start: 0, rows: 30} ]
Post Load (1.9ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" IN ($1, $2) [["id", 30], ["id", 40]]
=> [#<Post id: 30, title: "A Time to Kill", body: "Possimus atque corporis maxime veritatis provident...", created_at: "2018-02-23 08:52:14", updated_at: "2018-02-23 08:52:14">, #<Post id: 40, title: "A Time to Kill", body: "Et qui ipsam dolores delectus. Rem fuga perferendi...", created_at: "2018-02-23 08:52:14", updated_at: "2018-02-23 08:52:14">]
Great, last step - add controller action, which get param from request and perform search:
def search
@posts = Post.search do
keywords params[:q]
end.results
render "index"
end
Our posts page:
And search results page: