2010-12-15 2 views
1

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

UserId | FirstName | LastName

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

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

Случай 1:

Вход: Jo

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

Случай 2:

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

Образец M «John Doe», «Jane Doe»

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

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

ответ

1

Внедрив эту особенность с критериями, я должен сказать, что самый простой способ - генерировать последовательность ICriterion LIKE «на лету» после того, как разделил вход, используя пробел в качестве разделителя. Производительность не очень плохая, даже на db, которая имела что-то вокруг записей с отметкой в ​​миллион, но поскольку запросы LIKE не используют преимущества индексов, их естественным является то, что по мере расширения набора данных запрос будет менее результативным.

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

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

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

EDIT, комментарий Ответ

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

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

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

0

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

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

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

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

+0

Спасибо за предложение; хотя это похоже на простой подход, я думаю, что я буду беспокоиться о многократных поездках, необходимых для работы с точки зрения производительности ... – DanP 2010-12-15 20:19:26

+0

, так как это так просто, нечего терять, реализуя его и видя. Я думаю, вы обнаружите, что он не является тормозно медленным, тем более, что первые поисковые запросы вычисляются менее дорогостоящим, чем более поздние, или один свернутый поиск, который каким-то образом делает все сразу. В конечном итоге пользователи будут тратить меньше времени на ожидание, потому что большинство случаев должны иметь высокую специфичность, и только меньшинство будет использовать расширенные примеры соответствия. 80/20. – Alain 2010-12-15 21:42:24

Смежные вопросы