ODATA用法小记
简介
开放数据协议(Open Data Protocol,简称OData)是一种描述如何创建和访问Restful服务的OASIS标准。该标准由微软发起 ,前三个版本1.0、2.0、3.0都是微软开放标准,遵循微软开放规范承诺书(Microsoft Open Specification Promise).第四个版本4.0于2014年3月17日在OASIS投票通过成为开放工业标准 .
对于使用OData的开发人员而言,可以将OData服务简化理解为一个URI(Uniform Resource Identifier)统一资源标识符,它是一种满足RESTful设计风格的Web服务有关OData的的协议的详细介绍,可以访问www.odata.org
组成
ODATA由“格式”和“协议”这两部分组成。格式定义了如何描述数据,协议定义了如何操作数据,所以我们可以及那个ODATA理解为接口协议,因为它规定了数据格式和数据操作标准。
通用格式定义语言(CSDL)
OData服务的数据模型是通过EDM(实体数据模型)来定义的。通用格式定义语言(Common Schema Definition Language (CSDL))定义了OData服务的EDM模型的一种XML格式的表现形式。
它的内容包括:
- CSDL的命名空间
- 实体模型的封装
- 实体模型的普通特性
- 具体的XML元素和属性介绍
核心协议及URL规范
核心协议主要定义了开放数据协议的核心语义和行为。它们包括:
URL规范主要定义了一系列推荐(非强制)采用的构建用于访问OData服务中的数据和模型的URL的规则。它们包括:
- URL的组成部分
- 服务的根URL
- 资源路径
- 查询语句
URL的形式如下:

可以知道,通过OData这种方式,我们可以将一个数据源、服务发布成一个public的URI,因此对于服务的使用者(Consumer)而言, 其并不需要关系OData背后的具体开发语言或技术,其只需要满足HTTP通信协议即可。
服务结构
OData的服务结构包括:
1)服务文档(Service Document):描述了OData Service中可用的数据的概览信息,也即OData中所含的Entity Set信息。
2)服务元结构文档(Service Metadata Document):在元结构文档中,描述了OData服务中的数据类型及其相关的属性,也即Entity Type和Property。
在以上两种文档中包含了:
实体集合(Entity Set):等同于RSS中的Feed节点,是某一种信息的集合
实体(Entity):等同于RSS中的Entry节点,描述了具体某一条目信息的内容
实体类型(Entity Type):表明实体的类型,每一个实体都对应一个Entity Type
属性(Property): 实体具体的属性
导航属性(Navigation Property):用于描述层级关系,例如Category - Sub-category这种关系
关联(Association):描述关联关系
示例访问ODATA文件:
# 访问OData的Service Document:
https://services.odata.org/V3/Northwind/Northwind.svc/

在OData的service document中可以看到所有的Entity Set
#访问ODATA的Medata Document:
https://services.odata.org/V3/Northwind/Northwind.svc/$metadata

在OData的metadata document中可找到Entity Type和Property
# 访问OData中具体的某一个Entity Set实体集合:
https://services.odata.org/V3/Northwind/Northwind.svc/Products
Products为实体集合名称,前面的为网站根目录

# 访问OData中具体的某一个Entiry实体:
https://services.odata.org/V3/Northwind/Northwind.svc/Product(1)
OData采用圆括号作为表示单独实体的键值的字段(key segment)

# 访问OData服务中,某一Entity实体的属性:
https://services.odata.org/V3/Northwind/Northwind.svc/Product(1)/productID
product(1)为实体,productID为 实体中的某一属性

如果想查看某一具体的实体,则直接在OData Service Document的URL后直接append上具体的实体名称即可,例如上例中的实体集合Customers;在实体集合中,每一条entry也即对应着一条数据的Entity。
#访问Odata服务中,某一属性的原始值:
https://services.odata.org/V3/Northwind/Northwind.svc/product(1)/productID/$value
ODATA常用操作
下表列举了一些常用的Odata操作:

查询语句
选择查询($select)
$select用于选择实体的哪些属性被包含在返回的数据中。
1 | 查询格式:GET ~/实体类型?$select=实体属性1,实体属性2 |
示例:
返回Category属性在包含的数据中
1 | https://services.odata.org/V3/Northwind/Northwind.svc/Products?$select=Category |

展开查询($expand)
$expand的查询帮助将实体类型的导航属性的值加入请求的返回数据中,查询获取实体集合下的其他实体子集。
OData中的实体类型之间有关系(relationship)。比如顾客(Customer)类型可以有一系列的订单(Orders)。这样一来,顾客类型与订单类型相关。顾客类型上可以定义导航属性(navigation property)用于描述这种关系(如上例中Customer类型的Orders属性)。
1 | 查询格式: GET ~/实体类型集合?$expand=其他实体类型 |
示例:
返回Customers类型中Orders的子集
1 | https://services.odata.org/V3/Northwind/Northwind.svc/Customers?$expand=Orders |

过滤查询($filter)
OData内置了一系列如上面例子中”gt”的过滤操作符(filter operations)和一些查询函数(query functions)用来支持不同的过滤查询需求。
1 | 查询语句: GET ~/实体?$filter=实体属性操作语句 |
1 | https://services.odata.org/V3/Northwind/Northwind.svc/Customers('ALFKI')?$filter=Country%20eq%20%27Germany%27 |
返回Customers(‘ALFKI’)中Country属性为Germany的数据

过滤查询设置表达式需要内置过滤操作符
参考文档如下;
OData Version 4.0 Part 1: Protocol Plus Errata 02 (oasis-open.org)
统计总数($count)
$count用来统计实体集合中实体数量
1 | 统计命令: https://services.odata.org/V3/Northwind/Northwind.svc/实体集合/$count |
1 | https://services.odata.org/V3/Northwind/Northwind.svc/Products/$count |
统计Product类型实体的总数为77

限定范围($top和$skip)
$top返回查询结果中的前n条记录,$skip越过查询结果中的n条记录,这两个参数都常用来分页
1 | 查询命令 : https://services.odata.org/V3/Northwind/Northwind.svc/实体集合?$top=n&$skip=n |
查询Products实体集合前2条记录
1 | https://services.odata.org/V3/Northwind/Northwind.svc/Products?$top=2 |

查询Products实体集合中不包含前两条记录
1 | https://services.odata.org/V3/Northwind/Northwind.svc/Products?$skip=2 |

查询获取第3和第4个实体集合的记录
1 | https://services.odata.org/V3/Northwind/Northwind.svc/Products?$top=2&$skip=2 |

格式化输出($format)
将查询返回的数据JSON格式化。Service document和metadata document只能以XML格式展示
1 | 格式化命令:https://services.odata.org/V3/Northwind/Northwind.svc/实体集合?$format=json |
将查询结果输出为json格式

排序输出($orderby)
根据结果中的属性字段进行排序(AES升序,DESC降序)
1 | 命令:https://services.odata.org/V3/Northwind/Northwind.svc/实体集合?$orderby=实体属性%20desc/aes |
将前两条记录中的UnitPrice属性降序处理
1 | 命令:https://services.odata.org/V3/Northwind/Northwind.svc/Products?$top=2&$orderby=UnitPrice%20desc&$format=json |

获取资源总数($inlinecount)
分页取数据的时候,同时统计总记录数
1 | 命令:https://services.odata.org/V3/Northwind/Northwind.svc/实体集合?$inlinecount=allpages |
获取Products实体集合中符合条件的资源总数
1 | https://services.odata.org/V3/Northwind/Northwind.svc/Products?$inlinecount=allpages&$format=json |
