Живой поиск по нескольким полям базы данных с использованием linq

Я в основном ищу поиск типа "Google" в моей базе данных.

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

Конечно, простое разделение игр, книг и поисков фильмов не составляет проблем, хотя я действительно был бы замечателен, если бы у меня было 1 поле поиска для всего, главным образом потому, что я иногда путаю книги с фильмами xD

Сначала я подумал, что это будет хороший способ (просто поиск книг):

List<Book> books = (from b in le.Book
                    where (b.Title + " " + b.Author.FirstName + " " +
                    b.Author.Surname).Contains(search)
                    select b).OrderBy(b => b.Title).ToList();

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

The fault in our stars John Green

но если кто-то наберет:

John Green The fault in our stars
The fault in our stars - John Green

или какой бы вариант вы ни придумали, он потерпит неудачу.

Я нашел довольно хороший пример для запроса SQL здесь: метод поиска полей MYSQL, но он в SQL, и я не знаю, как переписать это в linq. Поскольку база данных (собирается) содержит тысячи записей, поэтому я не могу просто сделать:

var total = (from b in le.Book
             select new { b.ID, FullDescription = (b.Title + " " +
             b.Author.FirstName + " " + b.Author.Surname) });
string[] searchArr = search.split(' ');
List<int> ids = new List<int>();
foreach(string s in searchArr)
{
    ids.addRange((from t in total
                  where t.FullDescription.Contains(s).ToList());
}

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

Но да var total станет огромным.

Затем, конечно, есть часть сделать поиск в реальном времени, поэтому он обновляет представление списка каждый раз, когда вводится символ, поэтому, если я наберу: "jo" Я хотел бы получить список с результатами, а затем я могу определить его, набрав "joh" но было бы лучше запросить список результатов, которые я получил от последнего запроса, или повторно запросить всю базу данных?

Также мне нужно учитывать Backspace, так что если кто-то набрал "jo" но хотел "ja" В любом случае мне нужно повторно запросить всю базу данных?

Итак, какова лучшая практика для этого? Я нашел довольно много примеров, подобных упомянутому, но я ищу самое быстрое и "пользовательское доказательство" (то есть, независимо от того, насколько странным является поиск, чтобы получить правильный результат)

Моя модель базы данных (только книги, авторы)

Модель моей базы данных

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

1 ответ

Решение

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

По сути, вы пытаетесь сделать следующее:

  1. Учитывая конкретную строку запроса, вы хотите определить порядок в строке данных R
  2. Этот порядок должен быть детерминированным
  3. Этот порядок должен быть легко рассчитать
  4. Этот порядок должен отражать сходство или релевантность между строкой поиска и членами R

Сначала вы должны принять, что, если мы не определим проблему лучше, это скорее искусство, чем наука. "Актуальность" здесь не очень четко определена. Тем не менее, мы можем сделать некоторые предположения здравого смысла о том, что может быть актуальным. Например, мы можем сказать, что соответствующий результат имеет следующие качества:

  1. Строка поиска включена в члены R
  2. Больше членов R с помощью строки поиска указывает более релевантный результат
  3. Некоторые члены R важнее других
  4. Мы должны допустить опечатки / ошибки - то есть частичное совпадение чего-то стоит

Тогда мы можем определить "счет" для R строка следующим образом:

  1. Каждый член R получает "вес" с минимальным значением 1 и нет максимального значения
  2. Счет за R равно сумме веса каждого члена, деленной на "расстояние" между членом и строкой запроса
  3. Расстояние определяется с помощью хорошо известной метрики расстояния строки, такой как Левеншетин или SoundEx.

Например, если ваш R имеет членов Name, Description, а также URLвы можете взвесить эти 100, 10, а также 1соответственно и применяем метрику Левенштейна.

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

Но скоринг - это верный способ свести проблему к более легкому изложению.

Другие вопросы по тегам