【问题标题】:Azure Cosmos DB - Dynamic OR clause in Where queryAzure Cosmos DB - Where 查询中的动态 OR 子句
【发布时间】:2020-12-01 01:01:10
【问题描述】:

在我的 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' 的表达式”

这是我的谓词生成器:

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 中实现这一点?或者我必须在查询结果之后进行过滤?

【问题讨论】:

    标签: c# azure-cosmosdb


    【解决方案1】:

    我过去使用过一个类似的 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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-03
      相关资源
      最近更新 更多