c# - Azure Cosmos DB - Where 查询中的动态 OR 子句
问题描述
在我的 cosmos 存储中,我的项目有一组关键字。我想做一个查询,它可以过滤列表中至少有一个关键字的项目。
我尝试了 Intersect 方法:
query = query.Where(x => x.Keywords.Intersect(research.Kewords).Any())
但我得到了例外“不支持方法'相交'”
所以我尝试了 PredicateBuilder 方法:
var pred = PredicateBuilder.False<Item>();
foreach (var k in research.Keywords)
pred = pred.Or(x => x.Keywords.Contains(k));
query = query.Where(pred);
但我得到了异常“不支持使用 NodeType 'Invoke' 的表达式”
这是我的 predicateBuilder :
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
有没有办法在 Cosmos 中实现这一点?或者我必须在查询结果后过滤?
解决方案
我过去使用过类似的 PredicateBuilder 类,其实现与您展示的有所不同。我无法解释它,因为它可能是从 SO 中抄袭的,我忽略了记录 :)。
有了它,您应该能够使用您显示的表格:
expression = PredicateBuilder.Or(expression, x.Keywords.Contains(k));
执行
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]);
return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, secondBody), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
if (expr2 != null)
{
var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]);
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, secondBody), expr1.Parameters);
}
else
{
return expr1;
}
}
public static Expression Replace(this Expression expression, Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
}
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
推荐阅读
- function - 在 PowerShell 中通过管道传递开关参数
- python - 由于预热超时,Azure 应用服务启动缓慢(如果有)
- python - 根据值列表作为条件从数据框中删除一行
- sql - 创建指向 S3 的外部表
- mysql - MySql 错误 - 优先删除重复行
- c++ - 如何通过 LLVM C++ API 在没有基本块的函数中创建指令?
- c# - 使用 Json.net 更改 json 查询分隔符
- digital-ocean - 如何从数字海洋空间对象存储中删除多个密钥?
- python - Selenium python使用EC.visibility_of_all_elements_located在层次标签中抓取文本对象
- r - R: 在 geom_bar(position = 'fill') 中显示值