[英]Azure Cosmos DB - Dynamic OR clause in Where query
在我的 cosmos 存儲中,我的項目有一組關鍵字。 我想做一個查詢,它可以過濾列表中至少有一個關鍵字的項目。
我嘗試了相交方法:
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 中實現這一點? 或者我必須在查詢結果之后進行過濾?
我過去使用過類似的 PredicateBuilder class ,其實現與您展示的有所不同。 我無法對 go 進行很遠的解釋,因為它可能是從 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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.