在值中用逗号搜索

Search with a comma in the value

我有一个用户输入字符串的搜索。例如 "Smith, George" 在数据库中搜索名称。此名称在数据库中的格式为 "LastName" 和 "FirstName",因此记录如下: "Smith" "George".

在模型中,我连接了姓氏和名字字段,这样它们就会像这样出现在视图中 "Smith, George"

我需要做的是解析逗号并分别搜索姓氏和名字字段。

这是我的控制器代码。当两个字段都只输入一个或另一个时,它不会完成搜索。

        [HttpGet]
    public ActionResult Index()
    {
        return View(_db.Owners.ToList());
    }

    [HttpPost]
    public ActionResult Index(string searchString)
    {
        var owners = from o in _db.Owners select o;

        if (!String.IsNullOrEmpty(searchString))
        {
            owners = owners.Where(o => o.LastName.Contains(searchString) || o.FirstName.Contains(searchString));
        }

        return View(owners);
    }

强烈推荐大家阅读这篇经典文章:https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/

您连接的 "{Last}, {First}" 字符串是 视图 级别的问题,不应在您的数据库代码中执行。您的数据库和内部模型 object 应该以某种规范格式存储人名(例如可能有单独的字段(但所有字段都应该是可选的!),用于标题、名字、中间名、姓氏、后缀和任何其他适当的格式满足您所在地区或业务领域需求的文化习俗。

然后使用支持某种 field-based 搜索语法的单个搜索框,允许用户通过 free-text 搜索找到人,如果他们知道他们正在寻找,也可以通过确切的字段找到人对于使用 "John" 作为其 given-name 而不是 "Johnson" 作为其姓氏的人。

别忘了拆分条款。我推荐这样的东西:

  1. 给定 String input = "O'Brien firstname:John";:
  2. 过滤掉 non-word 个字符(标点符号等)。规范化值(例如 O'Brien -> OBrien),也许规范化为 SOUNDEX too (SQL Server has SOUNDEX support built-in: https://docs.microsoft.com/en-us/sql/t-sql/functions/soundex-transact-sql?view=sql-server-2017)
  3. 拆分为术语:[ any: "OBrien", firstname: "John" ](可以使用简单的 regular-expression)
  4. 为每个术语构建一个 Linq 查询(即添加新的 .Where 表达式,请注意连接 .Where 等同于 AND 运算符。如果要使用多个 .Where 作为 OR 操作,您需要 PredicateBuilder,请参阅此处:How to dynamically add OR operator to WHERE clause in LINQ

类似于:

class Term {
    String Field;
    String Value;
}

String input = "O'Brien firstname:John";
Term[] terms = GetTerms( input ); // returns the array from step 3

IQueryable<Owner> query = db.Owners;
foreach( Term term in terms ) {

    switch( term.Field.ToUpperInvariant() ) {
        case null:
        case "ANY":
            query = query.Where( o => o.LastName.Contains( term.Value ) || o.FirstName.Contains( term.Value ) || o.Title.Contains( term.Value ) || o.Suffix.Contains( term.Value ) );
            break;
        case "FIRST":
            query = query.Where( o => o.FirstName.Cotains( term.Value ) );
            break;
        case "LAST":
            query = query.Where( o => o.LastName.Contains( term.Value ) );
            break;
        case "TITLE":
            // et cetera...
    }
}

List<Owner> results = query.ToList();
[HttpGet]
public ActionResult Index()
{
    return View(_db.Owners.ToList());
}

[HttpPost]
public ActionResult Index(string searchString)
{
    var owners = from o in _db.Owners select o;
    var lastName = searchString.Split(',')[0];
    var firstName = searchString.Split(',')[1].TrimStart();

    if (!String.IsNullOrEmpty(searchString))
    {
        owners = owners.Where(o => o.LastName.Contains(lastName) || o.FirstName.Contains(firstName));
    }

    return View(owners);
}