【问题标题】:OData request that returns items not matching the filter返回与过滤器不匹配的项目的 OData 请求
【发布时间】:2014-01-24 09:51:47
【问题描述】:

我正在尝试编写一个 OData URL,该 URL 将从具有一对多关系的相关集合上的过滤器的集合中进行选择。过滤器要求相关的集合项都具有某些属性的特定值。

为了说明这个问题,我为 Northwind 示例 OData 服务编写了一个类似的 URL。此查询应选择所有订单已由同一员工处理的所有客户。 http://services.odata.org/V3/Northwind/Northwind.svc/Customers?$expand=Orders&$filter=Orders/all(o: o/EmployeeID eq 4)&$select=CustomerID,Orders/OrderID,Orders/EmployeeID

这给出了:

{"odata.metadata":"http://services.odata.org/V3/Northwind/Northwind.svc/$metadata#Customers&$select=CustomerID,Orders/OrderID,Orders/EmployeeID","value":
[{"Orders":[{"OrderID":10259,"EmployeeID":4}],"CustomerID":"CENTC"}
,{"Orders":[],"CustomerID":"FISSA"}
,{"Orders":[],"CustomerID":"PARIS"}]}

第一个项目确实包含员工 4 处理的所有(在本例中,只有一个)订单。对于第二个和第三个,结果集中没有订单项目。进一步检查,http://services.odata.org/V3/Northwind/Northwind.svc/Customers?$expand=Orders&$filter=(CustomerID eq 'FISSA')&$select=CustomerID,Orders/OrderID,Orders/EmployeeID 显示“FISSA”确实没有任何订单(“PARIS”也是如此)。

也许有人会认为,由于“FISSA”没有任何命令不服从过滤谓词,所以谓词成立。事实上,这可能是这个查询在 SQL 中的解析方式:

select c.CustomerID
from Customers c
where c.CustomerID not in (select CustomerID from Orders o where o.EmployeeID != 4)

返回相同的 3 个客户,但加入 Orders 表可以解决这个问题:

select c.CustomerID, o.OrderID, o.EmployeeID
from Customers c
join Orders o
on c.CustomerID = o.CustomerID
where c.CustomerID not in (select CustomerID from Orders o where o.EmployeeID != 4) 

只返回“CENTC”。

我认为“FISSA”的过滤谓词未确定,并且按照三值逻辑规则,“FISSA”和“PARIS”不应出现在结果集中。所以,我认为这是这个 OData 实现中的一个错误。

有人知道正确的 OData 请求查询以排除没有订单的客户吗?

【问题讨论】:

    标签: odata northwind three-valued-logic


    【解决方案1】:

    将 any 添加到 $filter 您可以删除任何空匹配项:Orders/any(o:o/EmployeeID ne null)

    http://services.odata.org/V3/Northwind/Northwind.svc/Customers?$expand=Orders&$select=CustomerID,Orders/OrderID,Orders/EmployeeID&$filter=Orders/all(o: o/EmployeeID eq 4) 和 Orders/any(o:o/EmployeeID ne null)

    【讨论】:

    • 这个查询将返回正确的结果集,所以我接受了答案,但对我来说,它看起来像是一种解决方法。
    • @R.Schreurs 很抱歉回复晚了,这是设计使然。 $expand 路径有效地单独评估到顶级 $filter,它只影响结果图的 投影,而不影响返回哪些记录。仅仅因为我们排除了 someall 的子项(直到查询执行后才能知道)并不总是意味着我们无论如何都想要排除父项。
    猜你喜欢
    • 2022-09-12
    • 1970-01-01
    • 1970-01-01
    • 2019-04-01
    • 2023-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多