【问题标题】:Search Keywords using LINQ使用 LINQ 搜索关键字
【发布时间】:2010-07-20 22:16:25
【问题描述】:

如果我有一个包含标题的文本字段并且我有一个关键字列表,我如何搜索标题以检查标题中的 (n) 个关键字?

因此,如果我的标题是“烤鸡肉、培根和韭菜派”并且用户搜索“鸡肉培根萝卜”,我想返回上述食谱。

基本上我想说的是,如果标题包含 2 个或更多搜索词,则它被视为有效并且应该返回。但如果它只包含 1 则忽略它。

理想情况下,我希望它们加权,以便出现的术语越多,列表中的位置就越高,但这可能是第 2 版。:)

编辑

我应该在这一点上提到,我希望这是原生的 .net 和 c#。

【问题讨论】:

  • 这是 LINQ to SQL、LINQ to Entities 还是 LINQ to Objects?

标签: c# linq search


【解决方案1】:

好的,我知道您说过“在 Linq 中执行”。假设您正在谈论采用 .Net 原生字符串并使用 Linq to Objects 进行处理,那么我想最明显的解决方案是通过处理单词边界的正则表达式来分解文本;然后遍历与输入短语匹配的每个结果。

不过……

从您对“v2”的想法来看,我认为您可能应该寻找更强大且更适合文本搜索的东西 - 那么使用 Lucene.Net 文本索引怎么样?

它提供了非常强大且非常快速的全文搜索 - 并且能够处理布尔规则;别名,词干,所有这些东西。

真的很摇滚。

更新 - 由于您在 cmets 中提到了 Linq to Sql

您也可以在表上使用 SQL 全文索引,但是有一个问题:没有本地 Linq To Sql 转换为 CONTAINSTABLE 等子句。

因此,您可以通过字符串使用动态查询生成,然后将其输入DataContext.ExecuteQuery<TResult> 成员。如果选择返回构造所需实体类型所需的列,它将像魅力一样工作。

或者,当然,您可以只包装一个存储过程来代替它;)

【讨论】:

  • 我有点希望有一个原生的 .net 解决方案并避免使用 java。我知道我没有在问题中规定。对此表示歉意
  • @griegs:Lucene.Net 是一个完整的 .Net Lucene 原生端口。不需要java。还根据您提到的 Linq to Sql 更新了我的答案
  • 啊,是的,我现在明白了。我想我看到了羽毛和 java 这个词,我的大脑忽略了其余的文字。
  • @griegs - 是的,我也有这种心理障碍;)
  • +1 哇,这看起来真的很酷。我可以将 1000 条热门记录存储在引擎中,以便更快地搜索它们。
【解决方案2】:

像 Andras 建议的那样做一个文本索引可能是你最好的选择。但要回答这个问题:您可以编写一个方法来自定义构建一个表达式树来表示一个选择器,该选择器为每个匹配的搜索关键字的属性添加 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;
}

【讨论】:

    【解决方案3】:

    如果是我,我只会做这样的事情......

    创建一个辅助类,它做两件事,拆分标题并根据关键字匹配返回一个分数......

    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;
    

    【讨论】:

      【解决方案4】:

      AODBDataContext db = new 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;
      

      【讨论】:

        猜你喜欢
        • 2012-09-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-09
        • 1970-01-01
        • 1970-01-01
        • 2022-01-14
        • 2012-10-06
        相关资源
        最近更新 更多