操作odata滤波器
如何在后端操作筛选器,并希望筛选查询参数的键值对?
表达式如下
?$filter=((命名为eq 'John‘或名称eq 'Grace Paul')和(部门eq’财务和会计‘)
因为有两个过滤器连接在一起&我如何获得以下值
Filter 1:
Key: Name
Operator: eq
Value: Name
Operator: or
Filter 2:
Key: Name
Operator: eq
Value: Grace Paul
Operator: and
Filter 3:
Key: Department
Operator: eq
Value: Finance and Accounting我试过
我使用ASP.NET Core2.1WebAPI和OData v4集成
有什么办法可以做到这一点吗?
发布于 2020-02-12 12:46:21
您可能需要考虑定义自己的解析器,然后遍历天冬氨酸以获得所需的值。有很多工具可以做到这一点(参见flex )。但是在.net世界中,反讽可能是一个可行的选择:它在.net standard 2.0中是可用的,我在.net core 2.1控制台测试项目中没有问题。
首先,通常需要定义语法。幸运的是,微软一直对向我们提供EBNF参考资料很好,所以我们所要做的就是让它适应讽刺。最后,我实现了上面语法的一个子集,它似乎满足了您的示例语句的需要(稍微超出了一点,可以随意地减少它)。
using Irony.Parsing;
namespace irony_playground
{
[Language("OData", "1.0", "OData Filter")]
public class OData: Grammar
{
public OData()
{
// first we define some terms
var identifier = new RegexBasedTerminal("identifier", "[a-zA-Z_][a-zA-Z_0-9]*");
var string_literal = new StringLiteral("string_literal", "'");
var integer_literal = new NumberLiteral("integer_literal", NumberOptions.IntOnly);
var float_literal = new NumberLiteral("float_literal", NumberOptions.AllowSign|NumberOptions.AllowSign)
| new RegexBasedTerminal("float_literal", "(NaN)|-?(INF)");
var boolean_literal = new RegexBasedTerminal("boolean_literal", "(true)|(false)");
var filter_expression = new NonTerminal("filter_expression");
var boolean_expression = new NonTerminal("boolean_expression");
var collection_filter_expression = new NonTerminal("collection_filter_expression");
var logical_expression = new NonTerminal("logical_expression");
var comparison_expression = new NonTerminal("comparison_expression");
var variable = new NonTerminal("variable");
var field_path = new NonTerminal("field_path");
var lambda_expression = new NonTerminal("lambda_expression");
var comparison_operator = new NonTerminal("comparison_operator");
var constant = new NonTerminal("constant");
Root = filter_expression; // this is where our entry point will be.
// and from here on we expand on all terms and their relationships
filter_expression.Rule = boolean_expression;
boolean_expression.Rule = collection_filter_expression
| logical_expression
| comparison_expression
| boolean_literal
| "(" + boolean_expression + ")"
| variable;
variable.Rule = identifier | field_path;
field_path.Rule = MakeStarRule(field_path, ToTerm("/"), identifier);
collection_filter_expression.Rule =
field_path + "/all(" + lambda_expression + ")"
| field_path + "/any(" + lambda_expression + ")"
| field_path + "/any()";
lambda_expression.Rule = identifier + ":" + boolean_expression;
logical_expression.Rule =
boolean_expression + (ToTerm("and", "and") | ToTerm("or", "or")) + boolean_expression
| ToTerm("not", "not") + boolean_expression;
comparison_expression.Rule =
variable + comparison_operator + constant |
constant + comparison_operator + variable;
constant.Rule =
string_literal
| integer_literal
| float_literal
| boolean_literal
| ToTerm("null");
comparison_operator.Rule = ToTerm("gt") | "lt" | "ge" | "le" | "eq" | "ne";
RegisterBracePair("(", ")");
}
}
}一点提示:带有讽刺意味的语法资源管理器工具允许您加载语法dll并使用它们进行调试,因此我建议您将类放在自己的项目中。然后,您就可以更容易地将您的头围绕在这些概念上:

在您满意语法之后,您需要从您的项目中引用它并解析输入字符串:
class Program
{
static void Main(string[] args)
{
var g = new OData();
var l = new LanguageData(g);
var r = new Parser(l);
var p = r.Parse("((Name eq 'John' or Name eq 'Grace Paul') and (Department eq 'Finance and Accounting'))"); // here's your tree
// this is where you walk it and extract whatever data you desire
}
}然后,您所要做的就是遍历生成的树,并根据sytax类型应用您的自定义逻辑。在这就是答案中可以找到一个如何做到这一点的例子。
根据您的需求,您可能会发现这对您的目的来说是完全过度的,或者实际上可能会发现它所提供的控制级别是完全正确的。
发布于 2019-02-07 08:04:04
我知道这不是解决办法,但与你分享,以防万一以后对你有帮助。这将匹配“:”右侧的所有值。
/(?<=: )[\w ]+/gmhttps://stackoverflow.com/questions/51173380
复制相似问题