Поиск по ключевым словам с использованием LINQ - PullRequest
3 голосов
/ 21 июля 2010

Если у меня есть текстовое поле, содержащее, например, заголовок, и у меня есть список ключевых слов, как я могу выполнить поиск по названию, проверяя (n) количество ключевых слов в заголовке?

Так что, если мой заголовок «Выпечка пирога с курицей, беконом и луком-пореем» и пользователь ищет «репу с куриным беконом», я бы хотел вернуть вышеуказанный рецепт.

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

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

1010 * редактировать *

Я должен упомянуть, что мне бы хотелось, чтобы это были нативные .net и c #.

Ответы [ 4 ]

4 голосов
/ 21 июля 2010

Хорошо, я знаю, что вы сказали «делай это в Линке». Поскольку, если вы говорите о том, чтобы взять нативную строку .Net и сделать это с помощью Linq to Objects, то, я думаю, наиболее очевидным решением будет разбиение текста с помощью регулярного выражения, работающего с границами слова; а затем выполнить итерацию каждого результата поиска по входным фразам.

Однако ...

Судя по вашей идее для 'v2', я думаю, вам, вероятно, стоит взглянуть на что-то более мощное и ориентированное на поиск текста - так как насчет использования Lucene.Net текстового индекса?

Он предлагает очень мощный и очень быстрый полнотекстовый поиск - и имеет возможность обрабатывать логические правила; псевдонимы, stemming, все такое прочее.

Это действительно рок.

ОБНОВЛЕНИЕ - Так как вы упомянули Linq to Sql в ваших комментариях

Вы также можете использовать полнотекстовые индексы SQL для своей таблицы, однако есть одна загвоздка: нет собственного перевода Linq To Sql в предложения CONTAINSTABLE и др.

Таким образом, вместо этого вы можете использовать динамическую генерацию запроса через строку, а затем передать ее в член DataContext.ExecuteQuery<TResult>. Если метод select возвращает столбцы, необходимые для создания нужного вам типа объекта, он будет работать как шарм.

Или, конечно, вы можете просто обернуть хранимую процедуру, которая делает это вместо этого;)

1 голос
/ 21 июля 2010

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

var entries = new[] { new Entry{ ID = 1,  Title = "Baking a chicken, bacon and leek pie"} }.AsQueryable();
var search = "chicken bacon turnip";
var q = entries.Select(GetSelector(search));
var matches = q.Where(e => e.MatchCount > 1);

public Expression<Func<Entry, EntryMatchCount>> GetSelector(string search)
{
    var searchWords = search.Split(new[] {' '});
    // Rather than creating the selector explicitly as below, you'll want to
    // write code to generate this expression tree.
    Expression<Func<Entry, EntryMatchCount>> selector = e =>
            new EntryMatchCount
            {
                ID = e.ID,
                MatchCount = (e.Title.Contains(searchWords[0]) ? 1 : 0) +
                            (e.Title.Contains(searchWords[1]) ? 1 : 0) +
                            (e.Title.Contains(searchWords[2]) ? 1 : 0)
            };
    return selector;
}
0 голосов
/ 21 июля 2010

AODBDataContext db = новый AODBDataContext ();

        var fItems = from item in db.Items
                     where SqlMethods.Like(item.Name, l)
                     where cats.Contains(item.ItemType)
                     where item.QL >= minQL
                     where item.QL <= maxQL
                     select item;
0 голосов
/ 21 июля 2010

если бы это был я, я бы просто сделал что-то вроде этого ...

Создать вспомогательный класс, который выполняет 2 действия, разделяет заголовок и возвращает оценку на основе соответствия ключевого слова ....

public static class Helper
{

  public static int GetScore(string Title, params string[] keywords)
  {
    // your routine that calcs a score based on the matchs against the Title.
  }
}

then you can use a linq statement like....

var matches = from t in GetYourTitles
              let score = Helper.GetScore(t, keywordlist)
              where score >= 2
              orderby score
              select t;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...