Статьи

Полнотекстовый поиск в Rails

Конечный продукт
Что вы будете создавать

Поиск записей является распространенным требованием в веб-приложениях. Обычно требуется, чтобы пользователи могли быстро получать доступ к нужным им данным из больших записей. Хотя это можно сделать с помощью простых запросов SQL, иногда эффективнее использовать поисковую систему.

Solr — популярная поисковая платформа из проекта Apache Lucene. Его основные функции включают мощный полнотекстовый поиск, выделение совпадений, многогранный поиск, индексацию практически в реальном времени, динамическую кластеризацию, интеграцию с базой данных, расширенную обработку документов и геопространственный поиск. В этом руководстве мы рассмотрим выполнение полнотекстового поиска с использованием Sunspot, библиотеки, которая позволяет интегрировать Solr в приложения ruby.

Я создал простое приложение на Github, которое я буду использовать здесь вместо того, чтобы начинать с нового проекта. Приложение показывает список продуктов с их названием, изображением, ценой и описанием. Я включил некоторые начальные данные, чтобы вы могли запустить rake db:seed если вы не хотите вводить данные самостоятельно. Приложение использует Paperclip для прикрепления изображений, и, поскольку я использую изменение размера изображений, ImageMagick необходимо будет установить в вашей системе. Вам также потребуется среда выполнения Java, установленная на вашем компьютере, для продолжения обучения.

Изображение ниже показывает приложение. Форма поиска в верхней части на данный момент ничего не делает, но мы дадим пользователю возможность осуществлять поиск по продуктам и получать результаты, основываясь не только на названии продукта, но и на его описании.

Мы начнем с включения драгоценных камней Sunspot и Solr в наш Gemfile. Для разработки мы будем использовать гем sunspot_solr который поставляется с предварительно упакованным дистрибутивом Solr, поэтому нам не нужно устанавливать его отдельно.

1
2
3
4
5
gem ‘sunspot_rails’
 
group :development do
    gem ‘sunspot_solr’
end

Запустите bundle install а затем выполните следующую команду, чтобы создать файл конфигурации Sunspot.

1
rails generate sunspot_rails:install

Это создает файл /config/sunspot.yml который позволяет вашему приложению узнать, где найти сервер Solr.

Чтобы настроить объекты, которые вы хотите проиндексировать, добавьте в них блок с возможностью поиска. В стартовом проекте у нас есть модель продукта с полями названия, цены, описания и фотографии. Мы позволим выполнять полнотекстовый поиск в полях имени и описания. В /models/product.rb добавьте:

1
2
3
searchable do
    text :name, :description
end

Запустите сервер Solr, выполнив:

1
rake sunspot:solr:start

Sunspot индексирует новые записи, которые вы создаете, но если у вас уже есть некоторые записи в базе данных, запустите rake sunspot:reindex чтобы их проиндексировать.

Затем мы добавляем код в контроллер Products, который будет принимать ввод пользователя и передавать его поисковой системе. В приведенном ниже коде мы вызываем search по модели продукта и передаем блок. Мы вызываем fulltext метод в блоке и передаем строку запроса, которую мы хотим найти. Есть несколько методов, которые мы можем использовать здесь, чтобы указать результаты поиска, которые мы хотим. Результаты поиска затем присваиваются @products которые будут доступны для нашего просмотра.

1
2
3
4
5
6
def index
    @query = Product.search do
        fulltext params[:search]
    end
    @products = @query.results
end

Запустите приложение, и теперь вы сможете искать доступные продукты.

Solr выполнит поиск без учета регистра по названиям и описаниям продуктов, используя ввод слов или фраз. Вы можете сделать одно поле более весомым, чем другое, чтобы повысить релевантность результатов поиска. Это делается с помощью метода boost которому передается значение, определяющее приоритет, назначенный различным полям. Поле с наибольшим значением будет иметь большее значение.

В нашем приложении мы можем указать продукты, в названии которых есть искомая строка, которая будет оценена выше. Мы делаем это путем внесения следующих изменений в /models/product.rb .

1
2
3
4
searchable do
    text :name, :boost => 2
    text :description
end

Переиндексируйте записи с помощью rake sunspot:reindex и теперь результаты с rake sunspot:reindex термином в названии продукта будут размещены выше, чем у тех, которые rake sunspot:reindex в описании. Вы можете добавить больше записей, чтобы проверить это.

Фасетный просмотр — это способ навигации по поисковым данным с помощью различных наборов связанных атрибутов. Например, в нашем приложении мы можем классифицировать поиск товаров по ценовому диапазону и подсчитывать количество каждого диапазона.

Сначала добавьте цену searchable метода searchable в /models/product.rb

1
2
3
4
5
searchable do
    text :name, :boost => 2
    text :description
    double :price
end

Затем вызовите facet в контроллере. Продукты будут ограничены диапазоном их цены с интервалом в 100 долларов. Здесь мы предполагаем, что все продукты стоят менее 500 долларов.

01
02
03
04
05
06
07
08
09
10
def index
    @query = Product.search do
        fulltext params[:search]
 
        facet :price, :range => 0..500, :range_interval => 100
        with(:price, Range.new(*params[:price_range].split(«..»).map(&:to_i))) if params[:price_range].present?
 
    end
    @products = @query.results
end

В файле представления вставьте следующее в место, где вы хотите увидеть побочные результаты.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<div class=»row»>
    <h3>Search Results</h3>
    <ul>
        <% for row in @query.facet(:price).rows %>
            <li>
                <% if params[:price_range].blank?
                    <%= link_to row.value, :price_range => row.value, :search => params[:search] %> (<%= row.count %>)
                <% else %>
                    <%= row.value %> (<%= link_to «X», :price_range => nil %>)
                <% end %>
            </li>
        <% end %>
    </ul>
</div>

Теперь, когда вы ищете термин, будет список аспектов, показывающих, сколько результатов в каждом ценовом диапазоне. В нашем примере приложения, если вы ищете слово «камера», вы увидите следующий список.

1
2
3
100.0..200.0 (2)
200.0..300.0 (1)
300.0..400.0 (1)

Каждый элемент является ссылкой, и при нажатии на него вы получите список продуктов, которые соответствуют вашему поисковому запросу и также попадают в диапазон цен, по которому вы щелкнули.

Ссылка передает исходный поисковый запрос и выбранный диапазон в действие индекса. Поскольку он передает диапазон в виде строки, мы используем Range.new(*params[:price_range].split("..").map(&:to_i)) чтобы преобразовать его обратно в диапазон. Вы можете использовать условные операторы для вывода более удобных для пользователя ссылок, таких как $100 - $199 (2) вместо 100.0..200.0 (2) но мы не будем 100.0..200.0 (2) в 100.0..200.0 (2) .

Есть несколько дополнительных настроек, которые вы можете сделать в Solr, чтобы настроить его работу. По умолчанию Sunspot выполняет полнотекстовый поиск, разделяя строку поиска на токены на основе пробелов и других символов-разделителей, используя интеллектуальный токенизатор, называемый StandardTokenizer . Затем токены записываются в нижнем регистре и ищутся точные слова.

Иногда это может быть хорошо, но вы также можете настроить поисковую систему так, чтобы она допускала человеческие ошибки или позволяла выполнять запросы, которые не слишком строги. Например, вы можете захотеть предоставить некоторые синонимы движку, чтобы, когда пользователь не вводит точный текст, который содержится в ваших записях, он все равно может найти похожие результаты. Примером этого является то, что у вас может быть элемент, помеченный «ipod» в ваших записях. Вы можете предоставить синонимы, такие как «iPod», «i-pod» и «i pod», чтобы увеличить шансы пользователей найти данные.

Еще одна полезная функциональность, которую вы можете добавить — это stemming, которая позволит Solr сопоставлять разные слова с одинаковым корнем. Например, если пользователь введет «run», он получит результаты с «run» и «running». Или, если они искали «прогулка», результаты будут включать данные, содержащие «прогулку», «прогулку», «прогулку» и т. Д.

Настройки Solr находятся в solr/conf/schema.xml и это файл, который нужно изменить, чтобы изменить конфигурацию сервера. Это выходит за рамки данного руководства, но для получения дополнительной информации ознакомьтесь с расширенной публикацией по полнотекстовой конфигурации и вики Solr .

Теперь, чтобы закончить, остановите сервер Solr, выполнив:

1
rake sunspot:solr:stop

Мы рассмотрели, как использовать гем Sunspot для использования поисковой системы Solr в приложении Rails. Помимо настроек, которые мы использовали, есть еще много других, которые вы можете использовать для настройки результатов поиска. Не забудьте проверить файл Readme для получения дополнительных параметров.

Solr предоставляет вам возможности поиска, которых нелегко достичь с помощью обычных запросов SQL. Для простых приложений с небольшим количеством записей в базе данных запросы SQL обходятся без значительного снижения производительности. Но если вы хотите что-то масштабируемое, то стоит поискать Solr или другие доступные поисковые системы.