本文涉及的模块: Integration Flow Helper
SAP CPI OData 接收方:正确编写 $select、$filter、$expand 和 $orderby
编写 SAP CPI OData 接收方的查询选项:$select、$filter、$expand、$orderby 和 $top 的示例,V2 与 V4 的差异,以及导致 HTTP 400 的常见错误。

SAP CPI 的 OData 接收方适配器会把 Resource Path 和一行查询选项转换成对 OData 服务(例如 SAP S/4HANA API)的调用。查询选项决定返回哪些字段、哪些行以及哪些关联实体,而只要一个属性名拼错,服务就会拒绝这次调用。
本文通过一个示例逐一讲解 $select、$filter、$expand 和 $orderby,介绍容易让人出错的 OData V2 与 V4 差异,以及如何保持名称正确。
查询选项在 OData 接收方中的位置
在适配器的 Processing 选项卡中,先选择操作,再设置 Resource Path(即你调用的实体集或实体)和 Query Options(即 URL 中 ? 之后的全部内容)。适配器的查询向导可以根据服务元数据生成这两者,并把元数据(EDMX 文件)保存在 iFlow 的资源中。
查询选项可以包含 Simple 表达式,因此值可以来自消息,例如 $filter=SoldToParty eq '${property.customerId}'。下面的示例从 OData V2 服务 API_SALES_ORDER_SRV 读取销售订单及其行项目:
Resource Path: A_SalesOrder
Query Options: $select=SalesOrder,SoldToParty,CreationDate,to_Item/SalesOrderItem,to_Item/Material
&$expand=to_Item
&$filter=SoldToParty eq '${property.customerId}' and CreationDate ge datetime'2026-01-01T00:00:00'
&$orderby=CreationDate desc
&$top=50在适配器中,查询选项写在一行里;这里拆开只是为了便于阅读。
逐一了解这四个选项
| 选项 | 作用 | 示例 |
|---|---|---|
$select | 只返回指定的属性,让响应保持精简 | $select=SalesOrder,SoldToParty |
$filter | 只返回满足条件的行 | $filter=SalesOrderType eq 'OR' |
$expand | 通过导航属性包含关联实体 | $expand=to_Item |
$orderby | 对行排序,默认升序 | $orderby=CreationDate desc |
$top 和 $skip 用于限制结果数量和分页。在 OData V2 中,展开实体的属性用路径来选择,例如 to_Item/Material,并且该导航属性也必须出现在 $expand 中。
$filter 有自己的运算符:eq、ne、gt、ge、lt、le,可用 and、or 和 not 组合。文本值放在单引号中,日期则需要使用服务版本所要求的字面量形式。
OData V2 和 V4 的写法不同
OData 适配器同时支持两个版本,许多 SAP API 也同时提供两个版本。把一个版本的查询复制到另一个版本,是常见的出错来源:
OData V2: $inlinecount=allpages
$filter=substringof('Smith',CustomerName)
$filter=CreationDate ge datetime'2026-01-01T00:00:00'
OData V4: $count=true
$filter=contains(CustomerName,'Smith')
$filter=CreatedAt ge 2026-01-01T00:00:00Z
$expand=_Item($select=Product,Quantity)- 统计行数:V2 用
$inlinecount=allpages,V4 用$count=true。 - 在文本中搜索:V2 用
substringof('Smith',CustomerName),V4 用contains(CustomerName,'Smith')。注意参数顺序是相反的。 - 日期:V2 写作
datetime'2026-01-01T00:00:00';V4 写值时不带前缀。 - 展开的属性:V2 用路径选择;V4 把选项嵌套在 expand 内,例如
$expand=_Item($select=Product,Quantity)。
导致 HTTP 400 的拼写错误
当查询选项有误时,服务通常返回 HTTP 400,并指出它无法解析的部分。背后的错误几乎总是同样几种:
- 大小写错误:OData 名称区分大小写,因此
soldToParty不等于SoldToParty。 - 在应写导航属性的地方写了实体集:写成
$expand=A_SalesOrderItem,而不是$expand=to_Item。 - 属性存在于另一个实体中,或只存在于服务的另一个版本中。
- 文本值两侧缺少引号,或者把 V2 的日期字面量发送给了 V4 服务。
- 分隔符问题:各选项用
&连接,每个选项名都以$开头。
表达式也会带来风险:如果 ${property.customerId} 为空,过滤条件就会变成 SoldToParty eq '',悄无声息地返回零行,而不是报错。Simple 表达式文章介绍了这些值是如何读取的。
让查询与服务保持同步
- 以 iFlow 资源中的 EDMX 作为名称的唯一依据,并在服务变更时更新它。
- 只选择你要映射的字段;响应越小越快,在 Trace 中也越容易阅读。
- 对于大量读取,请使用适配器的分页处理选项,而不是一次返回一个巨大的响应。
- 用真实消息会填入的确切值测试一次查询。
要调用的是 REST API 而不是 OData 服务?关于 Postman 和 OpenAPI 的文章介绍了 HTTP 接收方。
Kitegra 如何帮你
浏览器扩展 Kitegra 会读取你的 iFlow 中已有的 OData 接收方通道 EDMX。它在设计器中根据该 EDMX 提示 Resource Path,以及用于 $select、$filter、$expand 和 $orderby 的属性名和导航名,让你从中选择名称,而不必手动输入。
它的 Lint 面板会标出 EDMX 中不存在的 OData 名称,以及未闭合的 ${ 和没有任何地方设置的 header 或属性。如果某个通道没有得到提示,请检查它的 EDMX 是否在 iFlow 的资源中。它从不保存、部署或编辑 iFlow 的内容;只有在你点击四个指定操作之一时,tenant 才会发生变化,而且这些操作可以关闭。
要核实 OData 服务实际返回了什么,请逐步跟踪消息,查看调用之后的消息体。
没有 Kitegra 账户时,每个模块可用于 5 个 iFlow。Free 套餐涵盖 50 个,Starter 100 个,Pro 300 个;Business 不限。比较各套餐。
在下一个 iFlow 中试试
了解 Kitegra 在 SAP Integration Suite 设计器中能做什么,或在 Kitegra 的其他 Chrome 扩展旁查看它。
常见问题
在 SAP CPI 的 OData 适配器中,$filter 应该写在哪里?
写在接收方通道 Processing 选项卡的 Query Options 字段中,与其他选项放在一起,例如 $select=SalesOrder&$filter=SalesOrderType eq 'OR'。
可以在 OData 过滤条件中使用 header 或属性吗?
可以。查询选项接受 Simple 表达式,例如 $filter=SoldToParty eq '${property.customerId}'。如果值为空,过滤条件将不返回任何行,因此请先检查它。
$inlinecount 和 $count 有什么区别?
$inlinecount=allpages 属于 OData V2;$count=true 是 OData V4 的写法。两者都会在结果之外返回满足条件的总行数。
为什么 substringof 在我的服务上失败?
substringof 只存在于 OData V2 中。OData V4 服务使用 contains(Property,'text'),参数顺序相反。
为什么服务返回 HTTP 400?
通常是因为查询中的某个名称在该实体上不存在,原因往往是大小写错误、把导航属性和实体集搞混,或者使用了另一个 OData 版本的语法。
SAP CPI 把 OData 元数据保存在哪里?
查询向导会把服务的 EDMX 文件保存在 iFlow 的资源中。请在服务变更时更新它,让名称保持正确。