Поиск полного имени с одним полем ввода - PullRequest
1 голос
/ 15 декабря 2010

Допустим, у меня есть таблица, которая содержит следующие поля:

UserId |FirstName |LastName

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

В идеалеЯ бы хотел, чтобы семантика поиска была несколько разумной;привести несколько примеров:

Случай 1:

Ввод: Джо

Примеры соответствий: "Джон Доу", "Джейн Джонсон"

Случай 2:

Ввод: JD (обратите внимание на пробел между 'J' и 'D')

Примеры соответствий: "Джон Доу", "ДжейнDoe "

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

Я использую NHibernate 2.1.2 GA, поддерживаемую базой данных SQL Server 2008 R2 для справки, и не испытываю проблем с использованием hql, критериев или даже необработанного SQL, если это соответствует требованиям.Использование полнотекстового поиска также вариант, если это то, что мне нужно для приличных показателей производительности в этом.Я не уверен, что NHibernate Search стоит хлопот в этом случае (поскольку мои потребности настолько сфокусированы), поэтому давайте предположим, что я не хочу идти по этому пути.

Ответы [ 2 ]

1 голос
/ 16 декабря 2010

Реализовав эту особенность с помощью критериев, я должен сказать, что наиболее простым способом является создание серии LIKE ICriterion на лету после разделения ввода, используя пробел в качестве разделителя. Производительность на самом деле не плохая, даже на БД, у которой было что-то около миллиона записей, но поскольку запросы LIKE не используют индексы, вполне естественно, что при расширении набора данных запрос будет менее производительным.

Предположения, которые могут быть сделаны с целью преимущественного увеличения производительности, должны трактовать токены (части, разделенные пробелом) только как начало, что приведет к .. LIKE 'JO%' , что быстрее, чем .. LIKE '% JO%' или даже для обработки односимвольных токенов по-разному (как во втором примере). В моем случае, поскольку я использовал это в полях ввода с автозаполнением, я их проигнорировал: пользователь должен признать, что ищет Джона в JO, а Jane в JA, J ничего не возвращает (или, если быть более точным, запрос не выполнялся).

Впоследствии я реализовал это, используя полный текст Sql Server, и разница в производительности была, по меньшей мере, впечатляющей. Как всегда, это зависит от размера набора данных, и у полнотекстовых индексов есть накладные расходы на обслуживание, по крайней мере в 2005 году, который я использовал.

Опция lucene также неплохая, она быстрая и не сложная для реализации, и она открывает опцию для интеллектуальных наборов результатов, таких как «Вы имели в виду Джона» при вводе «Джона». Также он более управляем, чем полный текст Sql Server.

РЕДАКТИРОВАТЬ, комментарий комментарий

Я просто говорю, что я выполнил все 3 варианта выше ... базовый подход LIKE работал хорошо, но после первоначальной реализации я искал усовершенствования perf и изменил LIKE с опцией FullText Sql Server (CONTAINS) ... оба хорошо работали на производстве ...

Для части генерации запроса, если я правильно помню, я все еще динамически генерировал фрагменты запроса для каждого токена, для каждого столбца (FirstName, LastName), но полнотекстовые лучше, чем LIKE в фактическом времени выполнения запроса

в разработке я изменил FullText с Lucene, и хотя характеристики perf похожи на fulltext, другие аспекты (разработка, сопровождение, расширения) намного лучше с Lucene / NHibernate.Search. У меня не было возможности работать с реализацией Sql Server 2008 FullText, которая, как утверждается, лучше, чем

2005 года.

В качестве примечания к загрузке, если вы не идете по пути LIKE и хотите переместить приложение в другое хранилище данных, чем Sql Server, то лучше отделить полнотекстовые запросы с помощью Lucene / NHibernate. Лучшим решением является поиск.

0 голосов
/ 15 декабря 2010

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

Итак, сначала выполните точный поиск, где строка поиска соответствует как имени, так и фамилии, а затем выполните поиск по шаблону, где имя или фамилия соответствуют строке поиска с % с каждой стороны.

После этого вы можете попробовать более интересные варианты. Разбейте строку поиска по пробелу и попробуйте firstName = split (0) & "%", lastName = split (1) & "%". Затем попробуйте имя или второе имя = replace (searchString, "", "%") (превратив все пробелы в символы подстановки).

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

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