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

Скажу сразу, что мне очень хочется реализовать поиск независимо от движка БД. Поэтому вещи типа встроенного поиска MySQL, Sphinx или TSearch2 отпали. Пока, по крайней мере... И я обратился к поиску отдельных библиотек, реализующих индексированный поиск по произвольным документам.

Слово "PyLucene" чаще всего встречается, когда ищешь что-то, посвященное индексированному поиску под Питон. Оно представляет собой обертку для Java-библиотеки Lucene. Библиотека быстрая (по заявлениям) и очень способная: развитый язык запросов, нечеткий поиск, морфология (включая русскую).

Первый минус — типичный (уж извините) для многих Java-софтин монструозный интерфейс. Даже самые простые вещи делаются с помощью создания трех-четырех промежуточных объектов, реализующих абстракции, которые будут нужны потомкам. Когда-нибудь... Вот для примера поиск строки в индексе:

store = PyLucene.FSDirectory.getDirectory(settings.SEARCH_INDEX_ROOT, False)
analyzer = PyLucene.RussianAnalyzer()
searcher = PyLucene.IndexSearcher(store)
try:
  query = PyLucene.QueryParser('text', analyzer).parse(text)
  hits = searcher.search(query)
  for i, doc in hits:
    print doc.get('topic_id')
finally:
  searcher.close()

Но ладно, я не буду сильно зубоскалить — проблема неудобного интерфейса оказалась самой невинной из всех. Убили же идею совсем другие вещи:

Другими словами, PyLucene не смог. Реальное его использование для джанговского приложения я вижу только в виде отдельного внешнего сервера, написанного на их PythonThread'ах. А это совсем не то, чего мне хочется. Теперь буду пробовать Xapian.

Комментарии: 29 (особо ценных: 1)

  1. cDima

    Гм. А мне интерфейс Lucene (под Java и .Net) понравился настолько, что я называю его лучшим интерфейсом, который я когда-либо видел.

    Я его использовал в поисковике http://lan-crawler.sourceforge.net. Имхо он гибкий и легко расширяемый. В книге Lucene In Action все примеры красивые и элегантные. По-моему интерфейс сделан с умом!

    Привести, плиз, интерфейс поисковика, который был бы по-твоему более адекватен. При этом нужно поддерживать русский анализатор, указывать местоположение индекса, и парсер запросов.

    Это, так, для моего профессионального роста. :)

  2. Василий Половнёв

    Иван, а как вы вообще относитесь к Java, как к языку и как к платформе?
    Есть ли перспективы или вообще шансы у j2ee и web-фреймворков на java в свете Django, RoR, TurboGears и прочих?

  3. Alexander Solovyov

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

    Но когда над проектом работает больше 100 человек, то все эти недостатки превращаются в достоинства и помогают поддерживать красоту проекта на достойном уровне.

  4. Иван Сагалаев

    Не соглашусь. Большое количество лишних сущностей исходит чаще от увлеченности архитектора дизайном, как процессом, с терянием из виду целей. И с ростом числа участников этот over-engineering сказывается все хуже.

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

  5. buriy

    Ну так делай PyLucene отдельным процессом, к которому твое приложение будет обращаться многопоточно. Быстро делается, хорошо работает. Например, мой товарищ как-то запинал для внешнего процесса pyro. А можно и обычный tcp-сервер организовать было, как для базы данных.

  6. buriy

    Иван Сагалаев
    Не соглашусь. Большое количество лишних сущностей
    исходит чаще от увлеченности архитектора
    дизайном, как процессом, с терянием из виду
    целей. И с ростом числа участников этот
    over-engineering сказывается все хуже.

    На Java это самый удобный способ программировать. Просто пока у тебя нет API, работать с сущностями в Java неудобно. Добавим к этому низкую переиспользуемость классов. В результате объем кода в Java возрастает суперлинейно. Но это позволяет добиться того, что изменяя код одного класса (но сохраняя API) остальные классы будут работать, как раньше. А в python я бы не рискнул посадить на один проект даже 10 человек.

    Alexander Solovyov
    Но когда над проектом работает больше 100
    человек, то все эти недостатки превращаются в
    достоинства и помогают поддерживать красоту
    проекта на достойном уровне.

    О, как романтично))) На мой взгляд, красоту проекта помогает поддерживать соответствующая организация труда, а не язык программирования.

  7. Айк

    Может проще Яндекс.Сервер ;-)

  8. Василий Ставенко

    buriy
    Но это позволяет добиться того, что изменяя код одного класса (но сохраняя API) остальные классы будут работать, как раньше. А в python я бы не рискнул посадить на один проект даже 10 человек.

    Не совсем понимаю, а что мешает в python? Если API не меняется..? Я периодически использую одни python-объекты, имитирующие поведение других python-объектов. Они могут быть абсолютно одинаковы по интерфейсу, но абсолютно разные внутри.

    Команда из 10 питонистов не сможет поддерживать API? Но это вопрос организации труда...

  9. Nick

    2cDima:
    Возможно, Lucene (под Java и .Net) интегрируется достаточно просто, но тут я согласен с Иваном, нечего усложнять форум внешними обвесами, тем более что использование в пайтоне реализовано через явные костыли. Надо все-таки постараться поиск интегрировать в форум.

    2buriy:
    ну к чему тут, на этом блоге холи-варс? Здесь люди сознательно выбрали python имея на это свои основания. Для меня в программировании на Java совсем отсутствует fun, ну совершенно!
    А ентерпрайз можно и на вижуал бейсике лепить, главное чтобы в это вкладывали деньги (почитайте http://worsethanfailure.com/ там еще и не такие перлы в ентерпрайзе описывают)...

  10. Deepwalker

    Я тоже пытался использовать PyLucene, и также ушел к Xapian. Вот только не решил проблему стемминга. Теперь будет хороший шанс увидеть как же она все таки решается, ибо поддержки русского в xapian я не нашел.

  11. Max Ischenko

    А почему бы не использовать отдельный процесс для lucene и IPC? Тогда можно вообще найтивный C/Java сервер использовать.

  12. ph

    а advas пробовал? (http://advas.sourceforge.net/)
    у меня вот всю руки не доходят посмотреть..

    java вообще совсем из другой оперы. сравнивать её с питоном всё равно что сравнивать жигули с белазом.
    области применения такие же разные

  13. Alexander Solovyov

    О, как романтично))) На мой взгляд, красоту проекта помогает поддерживать соответствующая организация труда, а не язык программирования.

    :P Естественно, естественно. Но, программируя на PHP, добиться этого на порядок сложнее.

  14. zgoda

    Been there, done that. In our project we had to develop separate search/indexing server as a Twisted application plugin (twisted.web, to be precise) with REST interface. I saw similar servers, but using XML-RPC interface, so I think we are not alone here. So far, this is only viable solution if you are bound to mod_python.
    The big advantage of PyLucene is that the Lucene itself is widely used, stable and good documented package. Thanks to native compilation it beats even original Java lucene in speed. The drawback is, as you pointed it, unpythonic interface and hackish nature...

  15. Иван Сагалаев
        <p>Ответы оптом многим людям:</p>
    

    Привести, плиз, интерфейс поисковика, который был бы по-твоему более адекватен. При этом нужно поддерживать русский анализатор, указывать местоположение индекса, и парсер запросов.

    Я не возьмусь вот так "на коленке" спроектировать некий идеальный интерфейс. Однако конкретно мне, как пользователю, приведенный мой кусочек хотелось бы видеть таким:

    index = Index(settings.SEARCH_INDEX_ROOT)
    for doc in index.search(u'some query'):
      print doc['topic_id'], doc.id
    

    То есть:

    • Мне хочется иметь единый обслуживающий объект Index, а не выбирать, хочу ли я IndexWriter, IndexReader, IndexSearcher. Абстрагировать создание нужной стратегии локинга можно прямо внутри него по факту использования соответствующих функций (то есть search не будет лочить его на запись).

    • Выбор анализатора запроса должно иметь дефолтное поведение. Например, если индекс создан с русским анализатором, то логично и запрос формировать им же. Крайне редко нужна возможность делать по-другому, и для этого можно придумать что-то типа Index.analyzer = ....

    • Решение о типе парсинга запроса должно иметь, опять же, дефолт, который поддержан в функции search. Другие извращения можно сделать отдельной функцией типа index.search_with(SpecialQuery())

    Другими словами, есть золотое правило: простые вещи должны быть простыми, а сложные — возможными.

    Иван, а как вы вообще относитесь к Java, как к языку и как к платформе?
    Есть ли перспективы или вообще шансы у j2ee и web-фреймворков на java в свете Django, RoR, TurboGears и прочих?

    Java мне не близка своей негибкостью и принятой в сообществе практикой решать эту негибкость введением огромного числа абстракций "на всякий случай". Хотя я и понимаю ее ценность для большого количества промышленных программистов. Собственно, и про перспективы не могу сказать — не очень в курсе. Знаю только, что Sun не собирается ее покидать, а поэтому проживет она еще долго.

    (про отдельный процесс для поисковика)

    Are you nuts, guys? :-)

    Нет, серьезно, добавлять лишние действия при развертывании, лишний недетерминизм в runtime, лишнюю точку отказа — это все сильно необосновано, по-моему, если есть возможность сделать поиск in-process.

    Может проще Яндекс.Сервер ;-)

    Я хочу что-нибудь более встроенное. С моим шаблоном, возможностью сделать ajax-выдачу. Кроме того, халявный вариант не умеет внутренность СУБД индексировать.

  16. Максим Деркачев

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

    Проблема с тредами - да, я тоже про это думал и тоже прихожу к варианту внешнего сервера. We are not nuts :) Наоборот, думаю, выделить такого монстра в отдельный процесс - выгоднее, тем более, что т.к. он использует явские треды, то скорее всего там нет GIL (нужно изучить), так что этот процесс может работать в тредах без ограничений. Сложный развитый поисковик в любом случае добавит тебе несколько мегабайт на процесс, независимо от используемого механизма.

    И хотя это - лишнее действие при развертывании, на больших проектах выделение в отдельное приложение может сказаться хорошо с точки зрения масштабируемости. Для небольшого локального форума, конечно, это - перебор. Я бы копал в сторону FTS MySQL/PgSQL в этом случае.

    Кстати, с Lucene есть еще некоторые странности, например такая : http://semanticvoid.com/blog/2006/01/13/range-search-in-lucene/

  17. ph

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

    недетерминизм в runtime

    это на каком языке?)

    недетерминизм в runtime, лишнюю точку отказа

    всё с точностью наоборот. так у тебя в случае отказа отвалится поиск(ненадолго, ругнется в логи и рестартанет). если всё в одной куче - отвалится всё. вместе с пользователями которые что-то в этот момент делают.
    ну и на закуску добавление дыр поисковика в основное приложение, никакая мастштабируемость и отсутствия контроля над ресурсами(даже мониторинга).
    так что всё очень обоснованно.

    но в данном случае имхо можно обойтись возможностями поиска, интегрированными бд. или тем что имеется в http://cheeseshop.python.org/pypi

    или какими-нить внешними средставми.

  18. Andrew Aksyonoff

    Особо ценный комментарий

    Чисто для справки, Sphinx таки НЕ привязан к той или иной БД.

    Формально, ему все равно, из какого источника поступают данные.

    См. xmlpipe, хотя этот механизм (пока) и недостаточно гибкий.

  19. Traut

    а как насчет Solr? Отдельный сервер, основанный на Lucene. Все запросы и добавления в индекс идут через HTTP - по моему, мега удобная вещь

  20. EntropyHacker

    PyLucene портирован очень витиевато:
    Java-библиотека компилируется компилятором gcj в бинарник с Сишным интерфейсом, который уже потом может использовать Питон.

    IMHO, выяснив это на PyLucene сразу можно было ставить крест.

  21. dark-demon

    можно глупый вопрос? а почему бы самому не написать поисковик?

    сразу предупреждаю, что на ответ "развитый язык запросов, нечеткий поиск, морфологию (включая русскую) задолбаешься реализовывать." последует вопрос "а очень надо?" :)

  22. Григорий

    Кстати, внутри Django вроде бы ведётся работа в направлении интеграции в движок внешних индексаторов:
    http://code.djangoproject.com/wiki/TextIndexingAbstractionLayer

  23. КНИГАлюб

    Выбирая между PyLucene и Xapian я склоняюсь к PyLucene. Если я правильно понял, Иван затеял это дело ради собственного удовольствия, поэтому думаю лучше писать на том к чему больше лежит душа. А спорить На чем лучше, это ... каждому свое.

  24. H3llB0y

    Григорий, она как бы ведётся, но и как бы полгода уже никаких изменений там не наблюдается.
    А вообще в винде под apache PyLucene нормально не работает из-за своей кривой реализации.
    Solr, кстати, очень даже хорошо работает.

  25. Александр

    Эээ, товарисчи... а сколько в PyLucene течек памяти — ужос. Но простых вещах незаметно, но как только начнете юзать к примеру SortField (и не только) — намучаетесь. Отказались мы от неё. Полгода юзаем SOLR и довольны.

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

  26. Александр Локшин

    У нас были тоже проблемы с интеграцией Lucene (правда, в PHP-проект), решилось это довольно просто — связкой Lucene и Solr, который отдает веб-приложению данные в JSON-формате.

  27. Lispnik

    Странно, что PyLucene так странно сделанно. Ведь есть же порты Lucene на другие языки — Ruby и Common Lisp. Странно, что авторы PyLucene пошли таким извращённым путём.

  28. Иван Сагалаев

    А кстати говорят, что они сейчас все уже по-другому переделали, и этот wart пропал.

  29. Иван Сагалаев пишет:

Добавить комментарий