使用LINQ进行宽容/模糊搜索

Jam*_*ill 9 c# linq

我正在尝试对我继承的数据库实施搜索.该要求规定用户必须能够按名称搜索对象.不幸的是,一个对象可能有多个与之关联的名称.例如:

ID    Name
1     John and Jane Doe
2     Foo McFoo
3     Boo McBoo
Run Code Online (Sandbox Code Playgroud)

当每个记录中存在单个名称时,很容易实现搜索:

var objects =  from x in db.Foo
               where x.Name.Contains("Foo McFoo")
               select x;
Run Code Online (Sandbox Code Playgroud)

但是,当存在多个名称时,该方法不起作用.

问:是否可以写一个搜索方法,将返回一个记录(John和Jane Doe的),当有人使用的搜索词John DoeJane Doe

Vla*_*mir 7

这会影响性能,但是如何快速实现呢?

string[] filters = "John Doe".Split(new[] {' '});
var objects =  from x in db.Foo
               where filters.All(f => x.Name.Contains(f))
               select x;
Run Code Online (Sandbox Code Playgroud)

它似乎返回了您期望的结果。现在,当您同时有“ John Doe”和“ John and Jane Doe”唱片时,您可以对其进行调整以使其表现良好。

这对您有用吗?


JDB*_*JDB 7

您可以创建名为"ContainsFuzzy"的自定义扩展方法:

public static bool ContainsFuzzy(this string target, string text){
    // do the cheap stuff first
    if ( target == text ) return true;
    if ( target.Contains( text ) ) return true;
    // if the above don't return true, then do the more expensive stuff
    // such as splitting up the string or using a regex
}
Run Code Online (Sandbox Code Playgroud)

然后你的LINQ至少会更容易阅读:

var objects =  from x in db.Foo
               where x.Name.ContainsFuzzy("Foo McFoo")
               select x;
Run Code Online (Sandbox Code Playgroud)

明显的缺点是每次调用ContainsFuzzy意味着重新创建拆分列表等,因此涉及一些开销.你可以创建一个名为FuzzySearch的类,它至少可以提高你的效率:

class FuzzySearch{

    private string _searchTerm;
    private string[] _searchTerms;
    private Regex _searchPattern;

    public FuzzySearch( string searchTerm ){
        _searchTerm = searchTerm;
        _searchTerms = searchTerm.Split( new Char[] { ' ' } );
        _searchPattern = new Regex(
            "(?i)(?=.*" + String.Join(")(?=.*", _searchTerms) + ")");
    }

    public bool IsMatch( string value ){
        // do the cheap stuff first
        if ( _searchTerm == value ) return true;
        if ( value.Contains( _searchTerm ) ) return true;
        // if the above don't return true, then do the more expensive stuff
        if ( _searchPattern.IsMatch( value ) ) return true;
        // etc.
    }

}
Run Code Online (Sandbox Code Playgroud)

您的LINQ:

FuzzySearch _fuzz = new FuzzySearch( "Foo McFoo" );

var objects =  from x in db.Foo
               where _fuzz.IsMatch( x.Name )
               select x;
Run Code Online (Sandbox Code Playgroud)