【问题标题】:LINQ - Sort by StartsWith and then Contains (AutoComplete)LINQ - 按 StartsWith 排序,然后包含(自动完成)
【发布时间】:2021-07-12 17:19:56
【问题描述】:

我正在实现一个autocomplete 功能,我需要根据用户输入过滤 SQL 表。

因此,要求是过滤应该开始的记录(sort)结果是StartsWith,然后是Contains

样本数据:

Dotnet 开发人员
Azure 管理员
微软 Azure
Azure 开发运维
用户体验开发人员
物联网 Azure

如果我开始输入 Azu,那么它应该按以下顺序显示结果。

Azure 管理员
Azure DevOps
Microsoft Azu重新
物联网Azu重新

这意味着,我们正在寻找 startswith 逻辑然后是 contains 逻辑的结果。

目前,我尝试了两种方法,但都不起作用。

第一种方法:

dbContext.dbTable.Select(h => h.FieldName.ToLowerInvariant()).Where(e => e.Contains(text)).OrderBy(s => s).Distinct().Take(count).ToList();  

第二种方法:

dbContext.dbTable.Where(e => e.FieldName.Contains(text)).OrderBy(h => h.FieldName.IndexOf(text)).ThenBy(c => c.FieldName.Length).Select(p => p.FieldName).Distinct().Take(count).ToList();  

如果可以的话,谁能指导我?

【问题讨论】:

  • 仅供参考,这个模式被命名为 type ahead。可以帮助您找到其他解决方案:)。但是请您详细说明“没有用”。这是什么意思?

标签: c# .net entity-framework linq


【解决方案1】:

您的主要问题是需求或对需求的理解。

过滤操作:
根据布尔表达式减少(=过滤)结果,其中:
true ==> 显示结果
false ==> 显示。
它是在 linq 中通过 Where(...) 子句实现的。

在您的情况下,要求是按包含text 的结果过滤

.Where(e => e.Contains(text))

排序操作:
给定一个结果列表,决定它们的顺序。 您的要求是首先查看以text 开头的值。
换句话说,就是按照这个规则排序

String.StartsWith 返回一个布尔值。
在布尔值上运行 linq 的 OrderBy,按 false 排序,然后按 true 排序。 这是因为 OrderBy 默认排序是升序,falsetrue 算“小”。 (合理的决定)

所以,知道了这一点,你就可以通过运行来实现你想要的

.OrderByDescending(s => s.StartsWith(text))

全逻辑:

dbContext.dbTable
         .Select(h => h.FieldName.ToLowerInvariant())
         .Where(e => e.Contains(text)) // filter
         .Distinct() // more filtering
         .OrderByDescending(s => s.StartsWith(text)) // sort 
         .Take(count)
         .ToList();  

【讨论】:

    【解决方案2】:
    dbContext
      .dbTable
      .Where(x => x.FieldName.Contains(text))
      .Distinct()
      .OrderByDescending(x => x.FieldName.StartsWith(text))
      .Take(count);
    
    1. 仅过滤包含搜索条件的记录 (.Where(x => x.FieldName.Contains(text)))
    2. 对这些内容进行排序,以便以搜索条件开头的内容在前 (.OrderByDescending(x => x.FieldName.StartsWith(text)))

    【讨论】:

    • 你有它,但 OrderBy 是错误的方式。 .OrderBy(x => x.FieldName.StartsWith(text) ? 0 : 1).OrderByDescending(...) 都可以。赞成,因为这是一个简洁的解释。 (必须试一试才能看到)最后一个考虑因素是这假设数据库正在使用 CI(不区分大小写)排序规则。如果是 CS,添加 ToLower/ToUpper 进行比较。
    • 很好,史蒂夫。已编辑
    【解决方案3】:

    像下面这样试试

        dbContext.dbTable.Where(e => e.FieldName.Contains(text)).OrderBy(h => h.FieldName.ToLower().StartsWith(searchString.ToLower()) ? 0 : 1)
    .ThenBy(c => c.FieldName.ToLower().Contains("order")).Select(p => p.FieldName).Distinct().Take(count).ToList();  
    

    【讨论】:

      猜你喜欢
      • 2021-09-22
      • 1970-01-01
      • 2020-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-10
      • 1970-01-01
      相关资源
      最近更新 更多