简体   繁体   English

Azure Cosmos DB - Where 查询中的动态 OR 子句

[英]Azure Cosmos DB - Dynamic OR clause in Where query

In my cosmos storage, my items have a collection of keywords.在我的 cosmos 存储中,我的项目有一组关键字。 I would like to make a query which can filter the items which have at least one keyword of a list.我想做一个查询,它可以过滤列表中至少有一个关键字的项目。

I tried the Intersect method:我尝试了相交方法:

query = query.Where(x => x.Keywords.Intersect(research.Kewords).Any())

But I got the exception "Method 'Intersect' is not supported"但我得到了例外“不支持方法'相交'”

So I tried the PredicateBuilder Method:所以我尝试了 PredicateBuilder 方法:

var pred = PredicateBuilder.False<Item>();
foreach (var k in research.Keywords)
   pred = pred.Or(x => x.Keywords.Contains(k));
 query = query.Where(pred);

But I got the exception "Expression with NodeType 'Invoke' is not supported"但我得到了异常“不支持使用 NodeType 'Invoke' 的表达式”

Here my 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);
}

Is there a way to achieve this inside Cosmos?有没有办法在 Cosmos 中实现这一点? Or I have to filter after the query result?或者我必须在查询结果之后进行过滤?

I've used a similar PredicateBuilder class in the past with a somewhat different implementation than you show.我过去使用过类似的 PredicateBuilder class ,其实现与您展示的有所不同。 I can't go very far explaining it, as it was probably cribbed from SO and I neglected to document:).我无法对 go 进行很远的解释,因为它可能是从 SO 中抄袭的,我忽略了记录:)。

With it, you should be able to use the form you show:有了它,您应该能够使用您显示的表格:

expression = PredicateBuilder.Or(expression, x.Keywords.Contains(k));

Implementation执行

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM