【问题标题】:LINQ Query to search for users with partial nameLINQ 查询以搜索具有部分名称的用户
【发布时间】:2017-11-14 12:26:30
【问题描述】:

我有这个 SQL 查询:

SELECT 
    *
FROM
    employeeTable
WHERE 
    (
    concat(first_name, ' ', last_name) like concat('%', replace(@MatchString, ' ', '%'), '%')
        or
    concat(last_name, ' ', first_name) like concat('%', replace(@MatchString, ' ', '%'), '%')
    )

通过使用部分值搜索姓名和姓氏,它可以完美地工作。通过使用部分字符串搜索用户。比如:

“ric jon”将查找 Rick Jones、Richard Jonesy 和 Jonathan Prichter。

我有以下 Linq 查询,使用实体框架:

from employee in context.Employee
                    where employee.first_name.Contains(matchString)
                    || employee.last_name.Contains(matchString)
                    select employee

但是字符串“ric jon”什么也没找到。

我似乎无法让 linq 查询与 SQL 查询一样工作。

【问题讨论】:

  • where (employee.first_name + " " + employee.last_name).Contains(matchString)(反之亦然)?
  • 同样的问题。它与预期的一样部分匹配名字,但是当在字符串中放置一个空格时,它会完全停止查找。
  • 尽可能使用Like function

标签: sql entity-framework linq


【解决方案1】:

该 SQL 实际上不会找到您使用给定“ric jon”采样的那些记录。您要求的是一个特殊的过滤器,恕我直言,它需要一个后端不支持的功能(您没有指定您的后端,但无论如何至少我不知道一个支持本机的后端)。这样的事情会起作用(请注意,您正在将员工记录获取到本地,这不是在后端级别完成的):

Func<Employee, string[], bool> match = (emp, _parts) => {
     return 
     ((emp.FirstName.IndexOf(_parts[0],StringComparison.CurrentCultureIgnoreCase  ) != -1) &&
     (_parts.Length == 1 || emp.LastName.IndexOf(_parts[1], StringComparison.CurrentCultureIgnoreCase) != -1)) ||
     ((_parts.Length == 1 || emp.FirstName.IndexOf(_parts[1], StringComparison.CurrentCultureIgnoreCase) != -1) &&
     (emp.LastName.IndexOf(_parts[0], StringComparison.CurrentCultureIgnoreCase) != -1));
};

string search = "ric jon";
var result = context.Employee.AsEnumerable()
              .Where(n => match(n, search.Split()));  

更新:

您可以使用许多后端都支持的这个:

string search = "ric jon";
string[] parts = search.ToLowerInvariant().Split();
string p1 = parts.Length < 1 ? "" :parts[0];
string p2 = parts.Length < 2 ? "" :parts[1];

var result = context.Employee.Where(n => 
    ((n.FirstName.ToLowerInvariant().Contains(p1) &&
     n.LastName.ToLowerInvariant().Contains(p2))) ||
     ((n.FirstName.ToLowerInvariant().Contains(p2) &&
     n.LastName.ToLowerInvariant().Contains(p1))));

【讨论】:

  • 在客户端拉入所有记录进行过滤,将搜索词限制为两个词不是一个好的解决方案。
  • @CodeCaster,2 个词的搜索词是 OP 的想法,不是我的。我还提供了不需要获取记录客户端的代码。我认为这是您遗漏的第二段代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-21
  • 1970-01-01
  • 2014-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
相关资源
最近更新 更多