OData V4结合SAP Cloud SDK:仅在扩展属性达标时返回根实体
你的需求完全可以实现,核心问题是之前的查询逻辑搞反了,且错误地将过滤条件放在了$expand的子层级中(这只会过滤展开的子实体,不会影响根实体的返回)。
错误点拆解
第一次尝试的问题:
你把$filter=(BlockedForSalesOrder ne 'B')放在了$expand=toMaterialStatus(...)内部,这只会过滤展开出来的toMaterialStatus条目,但根实体(Product)的返回逻辑不受影响,所以即使子实体被过滤,根实体依然会显示。第二次尝试的问题:
你的过滤条件toProductSalesDelivery/any(d:d/toMaterialStatus/any(m:m/BlockedForSalesOrder eq 'B'))表示:只要存在一个toProductSalesDelivery下的toMaterialStatus满足BlockedForSalesOrder = 'B',就返回根实体。这和你的需求(不存在该情况时才返回)逻辑完全相反。另外注意实体集名称要保持一致(第一次用Product,第二次用Assortment_Product,需确认实际实体集名称)。
正确的OData查询写法
要实现“仅当所有关联的toMaterialStatus的BlockedForSalesOrder不等于'B'时返回根实体”,需要在根实体层级使用not any(...)来否定存在符合条件的子实体:
场景1:根实体是Product
Product?$select=Assortment,Product&$expand=toProductSalesDelivery($expand=toMaterialStatus)&$filter=Disabled eq false and not toProductSalesDelivery/any(d: d/toMaterialStatus/any(m: m/BlockedForSalesOrder eq 'B'))
场景2:根实体是Assortment_Product
Assortment_Product?$select=Assortment,Product&$expand=toProductSalesDelivery($expand=toMaterialStatus)&$filter=Disabled eq false and not toProductSalesDelivery/any(d: d/toMaterialStatus/any(m: m/BlockedForSalesOrder eq 'B'))
逻辑说明:
not toProductSalesDelivery/any(d: ...):表示不存在任何一个toProductSalesDelivery条目满足后续条件d/toMaterialStatus/any(m: m/BlockedForSalesOrder eq 'B'):该toProductSalesDelivery条目下存在BlockedForSalesOrder = 'B'的toMaterialStatus- 组合起来就是:根实体的
Disabled为false,且不存在任何一个关联的toMaterialStatus被标记为'B',才返回该根实体。
SAP Cloud SDK代码示例(Java)
如果用SAP Cloud SDK for Java构建查询,可以这样写:
// 假设Product是生成的实体类 ProductService service = new ProductService(); List<Product> result = service.getAllProduct() .select(Product.ASSORTMENT, Product.PRODUCT) .expand(Product.TO_PRODUCT_SALES_DELIVERY .expand(ProductSalesDelivery.TO_MATERIAL_STATUS)) .filter(Product.DISABLED.eq(false) .and(Product.TO_PRODUCT_SALES_DELIVERY.notAny(d -> d.toMaterialStatus().any(m -> m.blockedForSalesOrder().eq("B"))))) .executeRequest(destination);
这样就能精准过滤出符合要求的根实体,同时展开需要的关联数据。
内容的提问来源于stack exchange,提问作者Tobias

