Реализовать поиск по рецептам/продуктам на Sphinx и php
Разработку выполнять в github.
Используем: Sphinx 2.1, SphinxQL, RT index.
Разработку и тестирование производить на виртуальной машине «1C-Битрикс: Виртуальная машина 5.1» (vmware)!
На ней установлен php, Sphinx. Т.е. все, что нужно для реализации данной задачи. Скачать ее можно здесь http://repos.1c-bitrix.ru/vm/VMBitrix5.1.2-vmware.zip
Поиск будет осуществляться по двум базам продуктов:
- Общая база продуктов и рецептов. id_source = 0
- База продуктов и рецептов пользователей. id_source = 1
При необходимости формат тестовых данных может быть изменен, для целей удобства реализации функций поиска.
Функции заполнения Sphinx данными.
->addFood($nIdSource, $arFields) - добавляет в заданную базу продукт. Если продукт уже существует в базе, то будет обновлен.
$nIdSource - в какую базу будет добавляться продукт. 0 - Общая база, 1 - база пользователей.
$arFields - ассоциативный массив полей для добавления в поиск.
Пример полей можно увидеть в файлах с тестовыми данными.
->deleteFood($nIdSource, $nId) - удаляет продукт из соответствующей базы.
->loadFromFile($nIdSource, $sPathToFile) - заполняет Sphinx тестовыми данными из предоставленных файлов. Будет использоваться в основном для тестирование поиска.
Функции установки фильтра.
->filterAccount($nIdAccount) - устанавливает фильтр по полю "id_account"
->limit($nRowCount, $nOffset = 0) - устанавливаем лимит выборки.
->filterSource($nIdSource) - устанавливает индекс, по которому будет осуществляться поиск. 0 - Общая база, 1 - база пользователей. Если не установлен, то поиск будет идти по общей базе и базе пользователей. Данная функция влияет на From.
->filterPublished($nIsPubleshed) - фильтр по полю is_published.
->filterGroupId($GroupId) - фильтр по полю group_id. Может быть задан в виде массива.
->filterGroupName($GroupName) - фильтр по полю group. Может быть задан в виде массива.
->filterNutrients($arNutrients) - фильтр по полю nutrients. Где nutrients содержит JSON данные.
$arNutrients- это ассоциативный массив, который содержит ids nutrients для фильтрации.
Например:
array(
В итоге будет фильтр: ingredients.1 > 100 and ingredients.4 < 100 and (ingredients.5 > 1 and ingredients.5 < 200)
->filterSourceOfComposition($nSourceOfComposition) - фильтр по полю source_of_composition. Может быть задан в виде массива.
->filterTypeOfFood($nTypeOfFood) - фильтр по полю type_of_food.
Функции группировки.
->groupByGroupName() - группировка по полю group.
->groupByGroupId() - группировка по полю group_id.
Вопрос. Можно ли дополнительно сортировать группы в результате?
Функции сортировки.
->sortBy($sColName, $SortType="DESC") - устанавливаем сортировку по полю. Может быть вызвана несколько раз, в этом случае будет сортировка будет по нескольким полям.
Функции поиска.
->search($sQuery = "") - поиск продуктов по строке.
$sQuery - строка поиска. Может быть вида "Яблоко", "Яблоко салат", "Ябл".
Поиск осуществляется по полю "name".
Поиск с учетом морфологии. Например, "Яблоко" должно найти "Яблоки".
Может быть задано слово не полностью, а только его начало. Минимально 3 символа. Например, "ябл", "карто"
Чем ближе искомая фраза к началу, тем выше результат в поиске. Например, есть "Яблоки салат" и "салат из яблок". Выше должна быть первая строка.
На результат поиска не должно влиять количество вхождений искомой фразы в поле "name".
Если $sQuery задано в виде пустой строки, то значит мы хотим найти все продукты удовлетворяющие заданным фильтрам.
Например, $foodSearch->filterSource(0)->filterTypeOfFood(0)->limit(50)->search("яблоко"),
$foodSearch->filterNutrients(array("1"=> array("from"=>100)))->limit(50)->search()
->searchInIngredients($arIngredients) - поиск рецептов по ингредиентам. Т.е. ищем рецепты, в составе которых есть заданные ингредиенты
$arIngredients - массив ингредиентов, который должен содержать рецепт. Например, array("яблоки", "огурец")
Поиск осуществляется по полю "ingredients".
Поиск с учетом морфологии.
Например, $foodSearch->filterTypeOfFood(1)->sortBy("rating","DESC")->limit(50)->filterPublished(1)->searchInIngredients(array("яблоки", "огурец"))
Также в репозитарий положить конфиг настроек sphinx.
Общие замечания
Написать тесты на PHPUnit
Все функции должны быть chainable.
Вначале вызываем функции установки фильтра, сортировок, группировки, а затем функции поиска.
Например, $foodSearch->filterSource(0)->filterTypeOfFood(0)->limit(50)->search("яблоко")
Формат результата поиска - ассоциативный массив.
array(