1

我正在尝试编写一个 OData 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 /员工ID

这给出了:

{"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 请求查询以排除没有订单的客户吗?

4

1 回答 1

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)

于 2014-01-27T09:56:53.570 回答