谓词构建器组和/或带有内部外部的查询

Posted

技术标签:

【中文标题】谓词构建器组和/或带有内部外部的查询【英文标题】:Predicatebuilder group and or queries with inner outer 【发布时间】:2013-04-05 12:53:52 【问题描述】:

我有一个非常简单的谓词构建器查询,效果很好。我们有一个要搜索的关键字列表,然后我们遍历这些关键字以查看我们的任何对象属性是否匹配。

var predicateSearchText = PredicateBuilder.False<Asset>();
List<string> separatedKeywords = keywords.Split(',').ToList();

foreach (string s in separatedKeywords)

   if (s.Length > 0)
   
      string temp = s;
      predicateSearchText = predicateSearchText.Or(m => m.Notes.Contains(temp));
      predicateSearchText = predicateSearchText.Or(m => m.Description.Contains(temp));
      predicateSearchText = predicateSearchText.Or(m => m.DetailedDescription.Contains(temp));
      predicateSearchText = predicateSearchText.Or(asset => asset.Keywords.Contains(temp));
      predicateSearchText = predicateSearchText.Or(a => a.AssetFiles.Any(x => x.FileName.Contains(temp)));
   

...我做的更进一步:

var query = (from a in masterQuery.Where(predicateSearchText);

我得到了我需要的东西 - 只过滤那些我搜索过的关键字。

我需要更改它,以便在我的实体的某个属性中查找所有关键字。所以“notes”字段必须包含正在搜索的每个关键字,或者“description”字段必须包含正在搜索的所有关键字。我认为这涉及内部/外部谓词,但我无法想出它。我尝试过的结果太多了,它应该只给我一个……其他实体不符合标准。我的问题明显吗?我的关键字(其中 6 个)非常独特,我得到了 600 多个项目而不是 1 个...

var predicateSearchText = PredicateBuilder.False<Asset>();
var notesPred = PredicateBuilder.True<Asset>();
var descPred = PredicateBuilder.True<Asset>();
var detdescPred = PredicateBuilder.True<Asset>();
var keywordPred = PredicateBuilder.True<Asset>();
var filesPred = PredicateBuilder.True<Asset>();

foreach (string s in separatedKeywords.Where(xx=>xx.Length > 0))
   descPred.And(m => m.Description.Contains(s));

foreach (string s in separatedKeywords.Where(xx => xx.Length > 0))
   notesPred.And(m => m.Notes.Contains(s));

foreach (string s in separatedKeywords.Where(xx => xx.Length > 0))
   detdescPred.And(m => m.DetailedDescription.Contains(s));

foreach (string s in separatedKeywords.Where(xx => xx.Length > 0))
   keywordPred.And(m => m.Keywords.Contains(s));

foreach (string s in separatedKeywords.Where(xx => xx.Length > 0))
   filesPred.And(a => a.AssetFiles.Any(x => x.FileName.Contains(s)));

predicateSearchText = predicateSearchText.Or(notesPred.Expand());
predicateSearchText = predicateSearchText.Or(descPred.Expand());
predicateSearchText = predicateSearchText.Or(detdescPred.Expand());
predicateSearchText = predicateSearchText.Or(keywordPred.Expand());
predicateSearchText = predicateSearchText.Or(filesPred.Expand());

然后我做我的:

var query = (from a in masterQuery.Where(predicateSearchText);

而且我得到的结果太多,谓词不正确。

【问题讨论】:

【参考方案1】:

我今天也遇到了同样的问题。将 PredicateBuilder 实例化和 Where() 函数移到循环内,它将有效地与单独的关键字谓词进行 AND。

var predicateSearchText;
List<string> separatedKeywords = keywords.Split(',').ToList();

foreach (string s in separatedKeywords)

   if (s.Length > 0)
   
      predicateSearchText = PredicateBuilder.False<Asset>();

      string temp = s;
      predicateSearchText = predicateSearchText.Or(m => m.Notes.Contains(temp));
      predicateSearchText = predicateSearchText.Or(m => m.Description.Contains(temp));
      predicateSearchText = predicateSearchText.Or(m => m.DetailedDescription.Contains(temp));
      predicateSearchText = predicateSearchText.Or(asset => asset.Keywords.Contains(temp));
      predicateSearchText = predicateSearchText.Or(a => a.AssetFiles.Any(x => x.FileName.Contains(temp)));

      Query = Query.AsExpandable().Where(predicateSearchText);
   

【讨论】:

以上是关于谓词构建器组和/或带有内部外部的查询的主要内容,如果未能解决你的问题,请参考以下文章

Oracle查询转换之连接谓词推入

将带有变量的闭包传递给 Laravel 查询构建器中的 where 方法

使用 NET Core 和 EF Core 构建谓词

我如何从两个已经训练好的分类器中构建一个分类器?

TestFlight 无法将构建添加到内部测试组

带有 Querydsl 的 JPA 谓词