Поиск имен с помощью Apache Solr - PullRequest
15 голосов
/ 01 апреля 2011

Я только что попал в, казалось бы, простой, но чрезвычайно сложный мир поиска. Для приложения мне необходимо создать механизм поиска для поиска пользователей по их именам.

После прочтения многочисленных постов и статей, в том числе:

Как я могу использовать Lucene для поиска личного имени (имени, фамилии)?
http://dublincore.org/documents/1998/02/03/name-representation/
Каков наилучший способ поиска в социальной сети, установив приоритеты отношений с пользователями в первую очередь?
http://www.gossamer -threads.com / списки / Lucene / Java-пользователь / 120417
Вопрос по Lucene Index и Query Design - Поиск людей
Lucene Fuzzy Поиск имен клиентов и частичных адресов

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

1) Иметь поле имени, второго и третьего имени и индексировать поля с помощью Solr
2) Используйте edismax в качестве requestParser для поиска по нескольким столбцам
3) Используйте комбинацию фильтров нормализации, таких как: транслитерация, перевод с латыни на ascii и т. Д.
4) Наконец используйте нечеткий поиск

Очевидно, что, будучи новичком в этом, я не уверен, что вышесказанное является лучшим способом сделать это, и хотел бы услышать от опытных пользователей, которые имеют лучшую идею, чем я, в этой области.

Мне нужно иметь возможность сопоставлять имена следующими способами:

1) Сгибание акцента: Йорн совпадает с Йорном и наоборот
2) Альтернативные варианты написания: Карл соответствует Карлу и наоборот
3) Сокращенные представления (я полагаю, что я делаю это с помощью SynonymFilterFactory): Сью соответствует Сюзанне и т. Д.
4) Сопоставление Левенштейна: Джонн соответствует Джону и т. Д.
5) Соответствие эхолота: Элин и Эллен

Любые указания, критика или комментарии приветствуются. Пожалуйста, дайте мне знать, если это возможно ... или, возможно, я просто мечтаю. :)


EDIT

Я также должен добавить, что у меня также есть поле с полным именем на случай, если у некоторых людей есть длинные имена, например, из одного из постов: Джон Пол или Дель Кармен должны также соответствовать Джону Полу Дель Кармен

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

Ответы [ 5 ]

9 голосов
/ 05 апреля 2011

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

Если вы делаете это, вы захотите выбрать свои поля и установить различные повышения для ранжирования результатов.

Поэтому в solr есть отдельные «скопированные» поля:

  • одно поле для точного полного имени (с фильтрами)
  • многозначное поле с фильтрами ASCIIFolding, Lowercase ...
  • многозначное поле с фабрикой SynonymFilterFactory ASCIIFolding, в нижнем регистре ...
  • PhoneticFilterFactory (с Caverphone или Double-Metaphone )

См. Также: более неанглийское обсуждение Soundex

Синонимы для имен, я не знаю, доступен ли общедоступный синоним db.

Нечеткий поискЯ не нашел это полезным, он использует расстояние Левенштейна.

Другие фильтры и индексирование получают более качественные результаты поиска.

Символы Юникода в именах могут обрабатываться с помощью ASCIIFoldingFilterFactory

Вы описываетеРешения заранее для ожидаемых вариантов использования.

Если вы хотите получить качественные результаты, запланируйте настройку Поиск релевантности

Эта настройка будет особенно полезна при попытке сопоставления насинонимы, такие как Макдональд и Макдональд (у которого расстояние Левенштейна больше, чем у Карла и Карла).

3 голосов
/ 20 сентября 2012

Нашел псевдоним db, не уверен, насколько хорош: http://www.peacockdata2.com/products/pdnickname/

Обратите внимание, что это не бесплатно.

1 голос
/ 07 апреля 2016

Для фонетического поиска имен вы также можете попробовать Beider-Morse Filter , который работает очень хорошо, если у вас есть смесь имен из разных стран.

Если вы хотите использовать его сфункция typeahead, объедините ее с EdgeNGramFilter:

<fieldType name="phoneticNames" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
  <analyzer type="index">
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.BeiderMorseFilterFactory" nameType="GENERIC" ruleType="APPROX" concat="true" languageSet="auto"/>
    <filter class="solr.EdgeNGramFilterFactory" minGramSize="3" maxGramSize="15"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.BeiderMorseFilterFactory" nameType="GENERIC" ruleType="APPROX" concat="true" languageSet="auto"/>
  </analyzer>
</fieldType>
1 голос
/ 03 марта 2016

Ответ в другом посте довольно хорош: Обучение Solr для распознавания ников или вариантов имен

<fieldType name="name_en" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
  <analyzer type="index">
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.ASCIIFoldingFilterFactory"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.ASCIIFoldingFilterFactory"/>
    <filter class="solr.SynonymFilterFactory" synonyms="english_names.txt" ignoreCase="true" expand="true"/>
  </analyzer>
</fieldType>
0 голосов
/ 23 марта 2015

Мы создали простой тип поля «name», который позволяет смешивать как ключевые (например, SOUNDEX), так и «парные» части ответов выше.

Вот обзор:

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

Вот суть его реализации ...

List<IndexableField> createFields(SchemaField field, String name) {
        Collection<FieldSpec> nameFields = deriveFieldsForName(name);
        List<IndexableField> docFields = new ArrayList<>();
        for (FieldSpec fs : nameFields) {
            docFields.add(new Field(fs.getName(), fs.getStringValue(),
                         fs.getLuceneField()));
        }
        docFields.add(createDocValues(field.getName(), new Name(name)));
        return docFields;
}

В основе этого лежит производноеFieldsForName (имя), в которое можно включать «ключи» из PhoneticFilters, LowerCaseFolding и т. Д.

  1. во время запроса сначала создается пользовательский запрос Lucene, который был настроен для отзыва и использует те же поля, что и время индекса

Вот ядро ​​его реализации ...

public Query getFieldQuery(QParser parser, SchemaField field, String val) {
        Name name = parseNameString(externalVal, parser.getParams());
        QuerySpec querySpec = buildQuery(name);
        return querySpec.accept(new SolrQueryVisitor(field.getName())); 
}

В основе этого лежит метод buildQuery (name), который должен генерировать запрос, который осведомлен о приведенном выше производномFieldsForName (name), поэтому для заданного имени запроса он найдет подходящие имена кандидатов.

  1. затем, во-вторых, функция Solr's Rerank используется для применения высокоточного алгоритма переоценки для изменения порядка результатов

Вот как это выглядит в вашем запросе ...

&rq={!myRerank reRankQuery=$rrq} &rrq={!func}myMatch(fieldName, "John Doe")

Содержимое myMatch может иметь парную реализацию Левенштейна или Яро-Винклера.

N.B. Наша собственная полная реализация использует проприетарный код для DerveFieldsForName, buildQuery и myMatch (см. http://www.basistech.com/text-analytics/rosette/name-indexer/) для обработки большего количества разновидностей, чем упомянутые выше (например, пропуски пробелов, кросс-язык).

...