Поиск имен с Apache Solr

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

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

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

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

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

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

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

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

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


ИЗМЕНИТЬ

Я также должен добавить, что у меня также есть поле fullname в случае, если у некоторых людей есть длинные имена, в качестве примера из одного из сообщений: Jon Paul или Del Carmen также должны соответствовать Jon Paul Del Carmen

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

Ответы

Ответ 1

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

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

Итак, у нас есть отдельные "скопированные" поля в файле solr:

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

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

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

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

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

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

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

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

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

Ответ 3

Ответ в другом сообщении довольно хорош: Обучение 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>

Ответ 4

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

Вот обзор:

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

Здесь ядро ​​его реализации...

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;
}

Сердцем этого является deriveFieldsForName (имя), в которое вы можете включить "ключи" из 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), который должен вызывать запрос, который знает о deriveFieldsForName (имя) выше, поэтому для данного имени запроса он найдет хорошие имена кандидатов.

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

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

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

Содержимое myMatch может иметь парную реализацию Levenstein или Jaro-Winkler.

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

Ответ 5

Для поиска фонетического имени вы также можете попробовать 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>