这个问题有两个部分。如何动态过滤,如何高效过滤。
动态标准
对于第一个问题,使用 LINQ 时无需进行全面查询。 Catch-all queries result in inefficient execution plans,所以最好避开它们。
虽然 LINQ 不是 SQL。您可以逐部分构建查询。只有当您尝试枚举最终查询时,它才会被转换为 SQL。这意味着你可以写:
if(!String.IsNullOrEmpty(searchCriteria1))
{
query=query=.Where(p=>p.Field1.Contains(searchCriteria1);
}
您可以链接多个Where 调用以获得多个AND 条件的等效项。
要使用例如OR 生成更复杂的查询,您必须构造正确的Expression<Func<...,bool>> 对象,或者使用LINQKit 之类的库来使这个可以忍受。
效率
能否编写高效的查询取决于搜索条件。子句field LIKE '%potato%' 不能使用任何索引,最终会扫描整个表。
另一方面,field LIKE 'potato% 可以利用覆盖field 的索引,因为它将转换为像field >='potato' and field<='potatp 这样的范围搜索。
如果您想实现自动完成或拼写检查,您通常希望找到与标准差异最小的文本。
全文搜索
您可以使用Full-Text Search 索引和FTS 函数(如CONTAINS 或FREETEXT)有效地搜索单词、单词变体甚至完整短语。
FTS 类似于 Google 或 ... StackOverflow 搜索单词或句子的方式。
引用文档:
CONTAINS 可以搜索:
- 一个词或短语。
- 单词或短语的前缀。
- 一个词靠近另一个词。
- 从另一个词屈折产生的词(例如,单词 drive 是drives、driven、driving 和driven 的屈折词干)。
- 使用同义词库作为另一个词的同义词的词(例如,“金属”一词可以有“铝”和“钢”等同义词)。
另一方面,FREETEXT 更接近 Google/SO 的工作方式,通过搜索整个短语,返回紧密匹配,而不仅仅是精确匹配。
通过DbFunctions.Contains 和DbFunctions.FreeText 函数,EF Core 5 及更高版本中都可以使用 CONTAINS 和 FREETEXT。
这意味着如果你想搜索一个词或短语,你可以构造一个适当的 FTS 参数并使用:
var searchCriteria1="' Mountain OR Road '";
if(!String.IsNullOrEmpty(searchCriteria1))
{
query=query=.Where(p=>DbFunctions.Contains(p.Field1.Contains(searchCriteria1));
}
这比使用 LINQKit 容易得多。
或搜索ride, ride, ridded with :
var searchCriteria1="' FORMSOF (INFLECTIONAL, ride) '";