Pull to refresh

Comments 43

Не понял ни-че-го.
Можно для просто толковых немножко на пальцах пояснить??
У меня есть таблица с полем id, artist
Запрос — 'coil'
Сфинкс выдает:
Lacuna Coil, This Mortal Coil, The_Coil_of_sin и так далее и тому подобное.
Где то в самом конце — встречаются записи в которых в поле artist тупо написано Coil…

Я как то по простоте душевной думал поставлю сфинкс — уж он то поля на 100% совпадающие с запросом сверху выведет…

Можно что-то подкрутить?
Полез на форум сфинкса. Чуть ли не каждый десятый запрос на форуме по низкой релевантности точных совпадений:

«Как сделать так, чтобы первым в результате было полное совпадение с полем?
Пример: soccer

из двух результатов:
dc soccer
soccer

Второй должен иметь больший вес.»

Ответы приводить не буду. Выглядят они мягко говоря дикими. Т.е. видимо не один я такой тупой. И этот вопрос волнует многих. Может быть автор пролшьет свет???
Щаз пролью…

Вот как раз логика работа ранкеров такая.
Проблема в том, что если запрос встретился в том поле полностью, уже получается максимальный вес фразы.
Безотносительно длины самого поля, и факта полного совпадения поля (!) с запросом.
Так исторически сложилось вот.

В версии 0.9.8 факт совпадения всего поля (!) вообще нельзя установить, не хватает данных в индексе.
Технически можно только факт совпадение-в-начале установить и забустить.
Но нужно приписать новый ранкер.

В версии 0.9.9 (текущая бета) добавилось еще всякое.
Ранкеров не добавилось, зато добавились модификаторы ^ и $, и соотв-но флажок «конец поля» в индексе.
Но все еще нужно приписать новый ранкер.

В версии 0.9.10 (текущий транк) добавился (барабанная) дробь как раз такой ранкер.
Называется sph04 (полностью SPH_RANK_SPH04), бустит совпадения в начале поля и в конце поля.
Возможно, бэкпортнем в 0.9.9 тоже.

Без ранкера сделать что-то непросто, но в определенной мере тоже можно.
Убирать ручками пунктуацию и верхний регистр из поля и запроса, посчитать crc32 поля, сохранить атрибутом.
Затем ранжировать по @weight+if(fieldcrc==querycrc,1000,0)
Криво, знаю, но может и пригодится таки кому.
Чего то не особо пролился свет… Можно по босяцки?

Скачать версию такую — то, тут то. В конфиге написать то-то. Если не поможет — то попробовать это.
Без барабанной дроби и фуршета.

Я правда хочу поставить, настроить и забыть. Если можно это сделать без изучения алгорима ранкера B52 c соответствующими модификаторами — то это было бы прекрасно.
Спасибо за ответ.
Как объяснить проще, чем «в версии 0.9.10 добавился как раз такой ранкер, называется sph04» я не знаю :(
Нужно, чтобы

Как объяснить проще, чем «в версии 0.9.10 добавился как раз такой ранкер, называется sph04» я не знаю :(
Нужно, чтобы кто-нибудь еще объяснил тогда.

> Если можно это сделать без изучения алгорима ранкера B52

:) Можно, наверное.
Статья таки скорее для тех, кому интересно изучить потроха.
1. Где взять эту волшебную версию? я смотрю тут www.sphinxsearch.com/downloads.html, никаких транков не вижу:

Current beta release Sphinx 0.9.9-rc2 (r1785; Apr 08, 2009)
Latest stable release Sphinx 0.9.8.1 (r1533; Oct 30, 2008)

Если она ещё не вышла — можно бэкпортнуть в 0.9.9?

2. Что написать в конфиге чтобы включился ранкер sph04, который бустит совпадения в начале и в конце фразы? В доке ничего нет про него.
Решил проблему релевантности самостоятельно. Отказался от сфинкса, заюзал майэскюэлевский поиск — для меня самое то оказалось. Краткий хау ту моих действий для ленивых.

1. Сначала был лайк, и был он медленен и нерелевантен:
SELECT * FROM `wharrgarbl_mp3s_copy2905` WHERE `artist` LIKE '%coil%' LIMIT 0, 30// 1.7538 сек

2. Нужен индекс. Добавляем:
ALTER TABLE wharrgarbl_mp3s_copy2905 ADD FULLTEXT (artist);//ждем пару минут (зависит от того сколько лямов в таблице)

3. Преобразуем запрос:
SELECT * ,MATCH artist AGAINST ('coil') AS relev FROM wharrgarbl_mp3s_copy2905 WHERE MATCH artist AGAINST ('coil')>0//0.0019 сек.

И всё. По запросу coil — coil выше recoil, а Ария выше Дискотека авария.
Быстро. Просто. Вкусно. Удобно.
Мне хватает вобщем.
Слово-запрос кстати надо подготовить ещё, вырезать спец символы, разбить по словам и т.п.
Читать тут: phpclub.ru/detail/article/mysql_search?printVersion=1
> заюзал майэскюэлевский поиск — для меня самое то оказалось.

:) Пока данные влазят в память, скорость не беспокоит, и поиск по уникальным словам — оно работает, да.
Осмелюсь добавить. Оно не просто работает. Оно охуительно работает.
1. Разобрался за пару часов.

2. Придал различные веса различным полям, причем довольно гибко
Например, есть поле артист/трек. индексы на обоих.

2.1 По запросу «coil» у группы койл с треком без слова coil — релевантность будет выше чем у группы lacuna coil даже если в названии трека будет слово coil.

2.2 По запросу coil — fire на первом месте будет coil — fire of the mind

2.3 По запросу Muse — bliss — будет соответствующий трек группы muse, а не говногруппа Bliss.

Не буду вас ругать, но по релевантности, в моем случае, мускул задвинул сфинкс на 100%
Ключевое слово «в моем случае» как раз.

Причем вполне понятно, что это за случай, и почему у Сфинкса «из коробки» не все гладко :)

Кстати, если статью читать внимательно, несложно добиться всего того же самого и на Сфинксе, в общем-то.

Другое дело, что на крохотных коллекциях это и не нужно, ага.
Поддержу Андрея. Мне приходилось работать с тремя полнотекстовыми движками: MySQL (ИМХО — ад кромешный: словоформ нет, работает медленно, в innodb не поддерживается), PostgreSQL (ИМХО — довольно хорош, однако сильно тормозит, в частности — при ранжировании, т.к. вначале делает всю выборку, а потом ее сортирует) и Sphinx. Последний лично мне больше всего нравится (особенно shebang-конфиги, это сказка), но у него есть большой недостаток: «без пол-литра не разберешься». В смысле, порог на вход очень высокий. Мне думается, что продукт можно значительно улучшить малой кровью, просто упростив работу с ним: добавить «коробочные» словоформы (всего-то в дистрибутив положить словарь и сделать в конфиге возможность указания относительного пути к файлам словаря), а также написать обертку для упрощения процесса инкрементного индексирования.

В общем, Андрей, — спасибо за отличную штуку!
>shebang-конфиги,
Напишите пример, как вы их пользуете? Очень нужно, но честно не совсем понял из вики, что оно такое и как его заюзать в связке с сфинкс…

Разве что делать php "/path/to_config/sphinx.conf " — но это невероятный костыль и я честно не совсем понимаю, чему тут радоваться.

Буду очень благодарен за ответ — нужно в реальном проекте и «вчера».
Про «Muse — bliss» наврал. Придать бОльший вес первому слову не получилось. Точнее средствами пхп это разрулил
Спасибо, shodan, все вполне понятно.
Для остальных могу посоветовать вернуться к этой статье, когда появится такая необходимость и базовые возможности sphinx исчерпаются себя для вас.
Андрей, а есть ли надежда на ручное указание веса терма а) в документе при индексации и б) в запросе при поиске?

а) Есть в транке (смотреть payloads)
б) В длинных планах есть, в коротких нет. Если надо спешно, welcome to sphinxsearch.com/consulting.html
Андрей, добрый день
ситуация по ручному указанию веса терма в запросе при поиске я так понимаю не изменилась?
Скажем так, сделать стало куда проще :)
расскажите по многопоточность запросов. сейчас возникла проблема что при большом количестве одновременных запросов, сфинкс стал выдавать через раз, нулевой результат.
Я вот как для себя решил проблему многозапросности, код на пхп для phpapi:

foreach ($aPriceGroup as $aValue) {

$oSphinxClient->SetFilter('id_price_group', array($aValue['id']));
$iQuery = $oSphinxClient->AddQuery($sSphinxKeyword, 'price_group');
$oSphinxClient->ResetFilters();
$bAddedUnrunQuery=true;

$aPriceGroupAssoc[$iQuery+(32*$i)]=$aValue;

if ($iQuery && !($iQuery % 31) ) {
$aResultQuery=$oSphinxClient->RunQueries();
$aResultAll=array_merge($aResultAll,$aResultQuery);

$sLastError=$oSphinxClient->GetLastError();
$i++;
$bAddedUnrunQuery=false;
}
}
if ($bAddedUnrunQuery) {
$aResultQuery=$oSphinxClient->RunQueries();
$aResultAll=array_merge($aResultAll,$aResultQuery);
}



Костыль, признаю: пока полностью не разобрался в синтаксисе запросов — для моего случае рабоатет безотказно. На винде правда при девелоперском режиме почему-то приходится иногда перестраивать индекс, так как сервис не запускается. Но лечится удалением процесса, перестройкой индекса и рестартом сервиса после ошибки винды.
Отличная статья!
Без разбора потрахов, честно не хотел использовать сфинкс. Подумывал о создании своих весов и индексов тупо на соседнем сервере. (Полнотекстовый поиск по мускулу — это для амерекосов, может и пойдет. А так для нашего брата — без словоформ полная туфта).

Не отправляйте в ГУГЛ (пользоваться умеею) и в документацию (много букв). Посоветуйте хорошие статьи (если есть) на:
— как устроен индекс внутри;
— как устроены словоформы, и можно ли их тюнить;
— что-то хорошее про инкрементальный индекс, и его ньюансы (про то что это зло — понятно, но когда новых данных вагон, то инкрементальный это то что нужно, чтобы дожить до ночи);
— практика хорошего применения, или какие ошибки не стоит делать.
Я, конечно, поздновато, но все же.

Есть ли возможность задать какой-то список документов, по которому можно выводить в самый верх документы по определенным запросам?

Поясню.

Есть документы:
1. «Приказ о вступлении в силу гражданского кодекса российской федерации».
2. «Комментарии к гражданскому кодексу российской федерации».
3. «Гражданский кодекс российской федерации».
4.… еще порядка пары тысяч документов, в названии которых встречается фраза «Гражданский кодекс российской федерации».

Так вот, при поисковом запросе «Гражданский кодекс российской федерации», собственно, самый важный документ (в списке под номером 3) появляется где-то очень-очень далеко, а должен идти первой же строкой.

Поэтому вопрос: есть ли какой-то способ, по которому для некоторых конкретных документов при некоторых конкретных запросах можно задать связи, благодаря которым документ с указанным таким поисковым запросом всегда будет на первом месте?
Дефолтная ранжировалка различий между разными точными совпадениями фразы не делает.

Ранжировалка SPH04 из транка занимается примерно таким.
Ну, т.е. в 9.9.9-rc2 средствами сфинкса мне такого добиться не получится?

А на когда планируется 9.9.10?
> Ну, т.е. в 9.9.9-rc2 средствами сфинкса мне такого добиться не получится?

С определенными трюками разве (ручками считать и бустить точное совпадения поля).

> А на когда планируется 9.9.10?

Ряд клиентов уже использует в продакшне.

Публичную альфу скорее всего выкатим в декабре.
Понимаю, что несколько не в тему, то все же хочу задать вопрос.

У документа есть разные свойства. Например "№ документа". "№ документа"- это не число, а строка. Например «ФЗ-1244» или «Приказ №33». Каждый документ может иметь несколько номеров. Соответственно, у нас связь «один-ко-многим».

По идее можно было бы использовать sql_attr_multi, но он работает только с числами. А тут строки. При этом нужно искать как по точному совпадению, так и по части строки, а также и по началу вхождения (например, «ФЗ-12%»).

Такое в текущем релизе на сфинксе можно сделать? Если нет, то планируется в каком-нибудь последующем релизе и, если да, то в каком?

Спасибо.
А можно сделать так, чтобы найденные слова большей длины получали больший итоговый вес?
serious necro :)

больший вес «и так» получают более редкие слова.
К сожалению по моим наблюдениям очень часто портят выдачу записи с разного рода короткими предлогами и словами.

Например, по запросу «мини трактор» сначала идут записи со словами «мини», «мин» и где то уже в конце со словом трактор. Хотя по логике более длинное слово найденное должно быть выше. Аналогично со всякого рода предлогами типа «для», «под» и т.п.
Длина не имеет значения. При прочих равных ранжироваться выше должны более редкие слова. Если слово «мини» в коллекции реже, чем «трактор», оно победит.
Ну вот в том то и дело что почему-то не срабатывает это. Слово мини, вместе со своими стемами более частое чем трактор, которое более редкое. Использую SPH_MATCH_ANY с заданными весами полей через SetFieldWeights.
> Использую SPH_MATCH_ANY

ыыыааа.

который вообще не смотрит на частоты слов — это вроде умеренно подробно как раз расписано в посте. нет?

(one | two | three) + extended2 + sph_rank_proximity_bm25 и вперед.
Спасибо. Раньше пробовал, но без разбиения по | слов запроса, а строгий поиск по всем словам не подходил, поэтому и пришлось вернуться к ANY.
можно еще «one two three»/1, оно эквивалентно. (Именно так внутри эмулируется ANY.)
Да, так еще лучше, спасибо!

Возник еще вопрос. При использовании морфологии почему-то имеют одинаковый вес слова полностью совпадающие и слова похожие (обрезанные). Например, если ищем «лом», то в выдаче будут записи со словами «лом»,«ломаем»,«ломать» и т.п. При этом записи с полным совпадением оказываются иногда (и даже часто) ниже записей с похожими словами.

Можно ли это как-то еще подстроить? Так чтобы слова полностью совпадающие имели более высокий вес, чем морфологически близкие?
При включении «просто» морфологии оно все слова приводит к одному и тому же стему внутри и более не отличает.

Можно попробовать index_exact_words=1 + expand_keywords=1. Первое сохранит исходные точные формы в индекс. Второе автоматом расширит запрос и заменит каждое слово на (=слово|слово). Что, теоретически, приведет к бусту веса точных совпадений.
К сожалению не помогло. (
В тесте помогает.

— Query 1 (mode=extended2,ranker=(default),index=) — Query 'dog run': retrieved 4 of 4 matches in 0.001 sec.
Word stats:
'=dog' found 2 times in 2 documents
'dog' found 4 times in 4 documents
'=run' found 2 times in 2 documents
'run' found 4 times in 4 documents

Matches:
1. doc_id=4, weight=4430 body=«dog run»
2. doc_id=1, weight=3416 body=«dog runs»
3. doc_id=2, weight=3416 body=«dogs run»
4. doc_id=3, weight=2402 body=«dogs running»
Да, пардон. Для включения этих новых опций обновлял сфинкс до последней беты, и видимо после переиндексирования забыл демона перезапустить. Теперь действительно работает. Большое спасибо за помошь.
Все примеры кода к статье разъехались, — везде вылезает html-разметка… Просьба к автору исправить, если это возможно. Заранее благодарен.
Sign up to leave a comment.