基于M-M关系的OData过滤器

基于M-M关系的OData过滤器,odata,odata-v4,Odata,Odata V4,是否可以通过M-M关系中的链接实体在odata中进行过滤,其中必须包含所有第二个实体,但允许附加实体 假设我有: 学生 学生班 等级 我想找到所有学生,他们的注册包括课程(101、102、103)是的,OData v4提供了2个对集合中的布尔表达式求值的函数。它们是Any和All,其中Any如果至少有一个子条目符合条件,则返回记录,All要求所有子记录都匹配 在您的情况下,我们可以使用任何: 5.1.1.10.1任何 any运算符将布尔表达式应用于集合的每个成员,如果表达式对于集合的任何成员为t

是否可以通过M-M关系中的链接实体在odata中进行过滤,其中必须包含所有第二个实体,但允许附加实体

假设我有: 学生 学生班 等级 我想找到所有学生,他们的注册包括课程(101、102、103)

是的,OData v4提供了2个对集合中的布尔表达式求值的函数。它们是
Any
All
,其中
Any
如果至少有一个子条目符合条件,则返回记录,
All
要求所有子记录都匹配

在您的情况下,我们可以使用
任何

5.1.1.10.1任何
any
运算符将布尔表达式应用于集合的每个成员,如果表达式对于集合的任何成员为true,则返回true,否则返回false。如果集合不是空的,则不带参数的
any
运算符返回true

示例79:包含数量大于100的任何项目的所有订单

http://host/service/Orders?$filter=项目/任何(d:d/数量gt 100)

但是,我们无法通过数组或值列表进行比较,因此我们必须将此查询分解为每个值的
Any
表达式以及
表达式。
这听起来有悖常理,但以下简单的查询(我们在单个
Any
中使用
)会导致匹配,其中学生有一个或多个类(101102103),但不一定是所有类:

如果他们必须至少在所有101102103中注册,那么我们必须
每个类的一个单独的
任何
操作符的结果,下面是每个类的3个单独查询,以及一个将
组合在一起的最终查询:

http://host/service/Students?$filter=Enrollments/Any(e:e/Class/Code eq '101')
http://host/service/Students?$filter=Enrollments/Any(e:e/Class/Code eq '102')
http://host/service/Students?$filter=Enrollments/Any(e:e/Class/Code eq '103')

http://host/service/Students?$filter=Enrollments/Any(e:e/Class/Code eq '101') AND Enrollments/Any(e:e/Class/Code eq '102') AND Enrollments/Any(e:e/Class/Code eq '103')
这些查询假定:
Student
记录上有一个名为
Enrollments
的导航属性,它将
Student
链接到
StudentClass
记录的集合,
StudentClass
有一个名为“Class”的导航属性,该属性将其链接到单个
Class
记录,
类代码(101102103)存储在名为
code

注意:不同的提供程序在不同程度上支持这些Lambda运算符,如果您有复杂的需求,如支持使用
Any
All
嵌套表达式,或者如果最简单的查询没有如您所期望的那样解决,则应与您的供应商/开发人员联系

此查询并不特别要求在结果中包含
注册
记录,它只应返回
学生
的列表,除非默认情况下有服务器端配置或逻辑来扩展这些导航属性


虽然OP不需要,但如果您正在扩展这些相同的对象图(筛选依据),请务必指出,在根
$filter
查询选项中使用
Any
运算符将不会对扩展的子集合应用筛选。如果只想返回与表达式匹配的子记录,除了根
$filter
查询选项中的
Any
操作符外,还需要在
$expand
查询选项中实现
$filter
表达式

反之亦然,仅在
$expand
查询选项中使用
$filter
不会阻止顶级
学生返回,如果他们只注册了其他课程,则不会返回任何课程,因为他们不符合条件,但它仍然会返回
学生
记录


因此,当使用嵌套在
$expand
中的
$filter
时,在
$filter
查询选项中包含
Any
All
操作符是很常见的。您应该包括URL或调用语法,以吸引您能够轻松使用的答案。利用这些信息,我们能做的最好的事情就是假设URL路由您的API使用,并提供理论上的响应。非常感谢您的详细解释,Chris。我在网上搜索了很长时间,以证明你表达得非常好的想法。关于将多个
any/
子句与
组合(如果需要将实体集合与值数组匹配)。OData v4的文档对于此类示例来说是缺乏的。在针对OData服务编写前端几年之后,现在@eugenezakarov,我发现自己越来越少地使用这些操作符。很好,OData具有这种灵活性,我的前端人员可以根据有效的开放API快速原型化,但大多数面向生产的代码都优化为自定义操作和函数。因此,虽然文档有点缺乏,但我觉得这是因为社区缺乏填补空白的需求和领导力。继续在SO中发布查询请求,我们会为您找到答案!我应该更新这篇文章,OData现在对IN操作符有了广泛的支持,这进一步简化了这种比较
http://host/service/Students?$filter=Enrollments/Any(e:e/Class/Code eq '101')
http://host/service/Students?$filter=Enrollments/Any(e:e/Class/Code eq '102')
http://host/service/Students?$filter=Enrollments/Any(e:e/Class/Code eq '103')

http://host/service/Students?$filter=Enrollments/Any(e:e/Class/Code eq '101') AND Enrollments/Any(e:e/Class/Code eq '102') AND Enrollments/Any(e:e/Class/Code eq '103')