ODataプロトコルガイド

1. 前書き

このチュートリアルでは、RESTFul APIを使用してデータセットに簡単にアクセスできる標準プロトコルである* https://www.odata.org [OData]を調べます。*

2. ODataとは何ですか?

ODataは、RESTful APIを使用してデータにアクセスするためのOASISおよびISO / IEC標準です。 そのため、消費者は標準のHTTP呼び出しを使用してデータセットを検出し、ナビゲートできます。
*たとえば、単純な__curl __one-liner *を使用してhttps://www.odata.org/odata-services/ [公開されているODataサービス]のいずれかにアクセスできます*:
curl -s https://services.odata.org/V2/Northwind/Northwind.svc/Regions
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xml:base="https://services.odata.org/V2/Northwind/Northwind.svc/"
  xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
  xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
  xmlns="http://www.w3.org/2005/Atom">
    <title type="text">Regions</title>
    <id>https://services.odata.org/V2/Northwind/Northwind.svc/Regions</id>
... rest of xml response omitted
この記事の執筆時点では、ODataプロトコルは4番目のバージョン(より正確には4.01)です。 OData V4は2014年にOASIS標準レベルに達しましたが、長い歴史があります。 そのルーツは、Astoriaと呼ばれるMicrosoftプロジェクト(https://devblogs.microsoft.com/odata/ado-net-data-services-project-astoria/[2007年にADO.Net Data Servicesに名前が変更されました])にたどることができます。 このプロジェクトを発表するhttps://devblogs.microsoft.com/odata/welcome/ [元のブログエントリ]は、MicrosoftのODataブログで引き続き利用できます。
*データセットにアクセスするための標準ベースのプロトコルを使用すると、JDBCやODBCなどの標準APIよりもいくつかの利点があります*エンドユーザーレベルの消費者として、Excelなどの一般的なツールを使用して、互換性のあるプロバイダーからデータを取得できます。 プログラミングは、利用可能な多数のRESTクライアントライブラリによっても促進されます。
プロバイダーとして、ODataの採用には利点もあります。互換性のあるサービスを作成したら、エンドユーザーが選択したツールを使用して消費できる貴重なデータセットの提供に集中できます。 HTTPベースのプロトコルであるため、セキュリティメカニズム、監視、ロギングなどの側面も活用できます。
https://pragmatiqa.com/xodata/odatadir.html [このディレクトリを見る]で確認できるように、これらの特性により、公共データサービスを実装する際に政府機関がODataを人気のある選択肢にしました。

3. ODataの概念

ODataプロトコルの中核となるのは、エンティティデータモデル(略してEDM)の概念です。 EDMは、多数のメタエンティティを含むメタデータドキュメントを通じてODataプロバイダーによって公開されるデータを記述します。
  • エンティティタイプとそのプロパティ(例: Person _、 Customer Order_、
    など)およびキー

  • エンティティ間の関係

  • エンティティに埋め込まれた構造型を記述するために使用される複雑な型
    (たとえば、_Customer_タイプの一部である住所タイプ)

  • エンティティセット。特定のタイプのエンティティを集約します

    仕様では、このメタデータドキュメントは、サービスへのアクセスに使用されるルートURLの標準の場所_ $ metadata_で利用可能である必要があります。 たとえば、_http://example.org/odata.svc/_で利用可能なODataサービスがある場合、そのメタデータドキュメントは_http://example.org/odata.svc/$metadata_で利用できます。
    返されたドキュメントには、このサーバーでサポートされているスキーマを説明する一連のXMLが含まれています。
<?xml version="1.0"?>
<edmx:Edmx
  xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx"
  Version="1.0">
    <edmx:DataServices
      xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
      m:DataServiceVersion="1.0">
    ... schema elements omitted
    </edmx:DataServices>
</edmx:Edmx>
このドキュメントを主要なセクションに分解しましょう。
トップレベルの要素__ <edmx:Edmx> __は、_ <edmx:DataServices> _ element__の子を1つだけ持つことができます。* * __ *ここで重要なのは、どのODataサーバーが使用するバージョン。 この場合、名前空間は、Microsoftの識別子を使用するOData V2サーバーがあることを示しています。*
A__DataServices_要素には、使用可能なデータセットをそれぞれ記述する1つ以上の__Schema __elementsを含めることができます。 _Schema_で使用可能な要素の完全な説明はこの記事の範囲を超えているため、最も重要なものに焦点を当てます:_EntityTypes、Associations、_、および_EntitySets_。

3.1. _EntityType_要素

この要素は、主キーを含む、特定のエンティティの使用可能なプロパティを定義します。 また、他のスキーマタイプとの関係に関する情報が含まれている場合があります。例を参照することで– a _CarMaker –_ JPAなどの他のORMテクノロジーで見られる説明とそれほど変わらないことがわかります。
<EntityType Name="CarMaker">
    <Key>
        <PropertyRef Name="Id"/>
    </Key>
    <Property Name="Id" Type="Edm.Int64"
      Nullable="false"/>
    <Property Name="Name" Type="Edm.String"
      Nullable="true"
      MaxLength="255"/>
    <NavigationProperty Name="CarModelDetails"
      Relationship="default.CarModel_CarMaker_Many_One0"
      FromRole="CarMaker"
      ToRole="CarModel"/>
</EntityType>
ここでは、_CarMaker_には2つのプロパティ(__Id ___and _Name_)と、もう1つの_EntityType_への関連付けのみがあります。 __Key s__ub-elementは、エンティティのプライマリキーをその__Id ___propertyに定義し、各_Property_要素には、その名前、タイプ、nullabilityなどのエンティティのプロパティに関するデータが含まれます。
_NavigationProperty_は、関連するエンティティへの「アクセスポイント」を記述する特別な種類のプロパティです。

3.2。 Association Element

__Association __elementは、2つのエンティティ間の関連付けを記述します。これには、各端の多重度と、オプションで参照整合性制約が含まれます。
<Association Name="CarModel_CarMaker_Many_One0">
    <End Type="default.CarModel" Multiplicity="*" Role="CarModel"/>
    <End Type="default.CarMaker" Multiplicity="1" Role="CarMaker"/>
    <ReferentialConstraint>
        <Principal Role="CarMaker">
            <PropertyRef Name="Id"/>
        </Principal>
        <Dependent Role="CarModel">
            <PropertyRef Name="Maker"/>
        </Dependent>
    </ReferentialConstraint>
</Association>
ここで、_Association_要素は、_CarModel_エンティティと_CarMaker_エンティティの間の1対多の関係を定義します。前者は依存パーティとして機能します。

3.3. _EntitySet_要素

最後に検討するスキーマの概念は、_EntitySet_要素です。これは、特定のタイプのエンティティのコレクションを表します。 テーブルに似ていると考えるのは簡単ですが、多くの場合、それはまさにそれです。 その理由は、同じ_EntityType_ *に対して複数の_EntitySet_要素を使用でき、それぞれが利用可能なデータの異なるサブセットを表すことができるからです。
最上位のスキーマ要素である_EntityContainer_要素は、利用可能なすべての__EntitySet__sをグループ化します。
<EntityContainer Name="defaultContainer"
  m:IsDefaultEntityContainer="true">
    <EntitySet Name="CarModels"
      EntityType="default.CarModel"/>
    <EntitySet Name="CarMakers"
      EntityType="default.CarMaker"/>
</EntityContainer>
単純な例では、__ EntitySet__sが2つだけですが、_ForeignCarMakers_や_HistoricCarMakers_などのビューを追加することもできます。

4. OData URLおよびメソッド

ODataサービスによって公開されるデータにアクセスするために、通常のHTTP動詞を使用します。
  • GETは1つ以上のエンティティを返します

  • POSTは、既存の_Entity Set_に新しいエンティティを追加します

  • PUTは指定されたエンティティを置き換えます

  • PATCHは、特定のエンティティの特定のプロパティを置き換えます

  • DELETEは、指定されたエンティティを削除します

    これらのすべての操作には、アクションを実行するためのリソースパスが必要です。 リソースパスは、エンティティセット、エンティティ、またはエンティティ内のプロパティを定義する場合があります。
    以前のODataサービスにアクセスするために使用されるURLの例を見てみましょう。
http://example.org/odata/CarMakers
このURLの最初の部分は、_odata / _パスセグメントまでのプロトコルから始まり、_serviceルートURL_と呼ばれ、このサービスのすべてのリソースパスで同じです。 *サービスルートは常に同じであるため、次のURLサンプルでは、​​サービスルートを省略記号(「…」)に置き換えます*。
この場合、_CarMakers_は、サービスメタデータで宣言された_EntitySets_のいずれかを指します。 通常のブラウザを使用してこのURLにアクセスすると、このタイプの既存のエンティティをすべて含むドキュメントが返されます。
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"
  xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
  xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
  xml:base="http://localhost:8080/odata/">
    <id>http://localhost:8080/odata/CarMakers</id>
    <title type="text">CarMakers</title>
    <updated>2019-04-06T17:51:33.588-03:00</updated>
    <author>
        <name/>
    </author>
    <link href="CarMakers" rel="self" title="CarMakers"/>
    <entry>
      <id>http://localhost:8080/odata/CarMakers(1L)</id>
      <title type="text">CarMakers</title>
      <updated>2019-04-06T17:51:33.589-03:00</updated>
      <category term="default.CarMaker"
        scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
      <link href="CarMakers(1L)" rel="edit" title="CarMaker"/>
      <link href="CarMakers(1L)/CarModelDetails"
        rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/CarModelDetails"
        title="CarModelDetails"
        type="application/atom+xml;type=feed"/>
        <content type="application/xml">
            <m:properties>
                <d:Id>1</d:Id>
                <d:Name>Special Motors</d:Name>
            </m:properties>
        </content>
    </entry>
  ... other entries omitted
</feed>
返されるドキュメントには、各_CarMaker_インスタンスの_entry_要素が含まれます。
入手可能な情報を詳しく見てみましょう。
  • id:この特定のエンティティへのリンク

  • title / author / updated:このエントリに関するメタデータ

  • _link_要素:編集に使用されるリソースを指すために使用されるリンク
    エンティティ(_rel =” edit” _)または関連するエンティティ。 この場合、この特定の_CarMaker_に関連付けられた_CarModel_エンティティのセットへのリンクがあります。

  • content:_CarModel_エンティティのプロパティ値

    ここで注意すべき重要な点は、キーと値のペアを使用して、エンティティセット内の特定のエンティティを識別することです。 この例では、キーは数値であるため、_CarMaker(1L)_などのリソースパスは、1に等しいプライマリキー値を持つエンティティを参照します。ここでの「_L_」は、単に_long_値を示し、省略できます。

5. クエリオプション

返されるセットのサイズや順序を制限するなど、返されるデータのさまざまな側面を変更するために、クエリオプションをリソースURLに渡すことができます。 OData仕様は豊富なオプションセットを定義していますが、ここでは最も一般的なオプションに焦点を当てます。
一般的なルールとして、クエリオプションは互いに組み合わせることができるため、クライアントはページング、フィルタリング、結果リストの順序付けなどの一般的な機能を簡単に実装できます。

5.1. _ $ top_および_ $ skip_

_ $ top_および_ $ skip_クエリオプションを使用して、大きなデータセットをナビゲートできます。*
.../CarMakers?$top=10&$skip=10
_ $ top_は、_CarMakers_エンティティセットの最初の10レコードのみが必要であることをサービスに伝えます。 _ $ top、_の前に適用されるA、_ $ skip、_は、最初の10レコードをスキップするようにサーバーに指示します。
通常、特定の_Entity Set_のサイズを知っていると便利です。このために、_ $ count_サブリソースを使用できます。
.../CarMakers/$count
このリソースは、対応するセットのサイズを含む_text / plain_ドキュメントを生成します。 ここでは、プロバイダーがサポートする特定のODataバージョンに注意する必要があります。 OData V2は_ $ count_をコレクションのサブリソースとしてサポートしますが、V4ではそれをクエリパラメーターとして使用できます。 この場合、_ $ count_はブール値なので、それに応じてURLを変更する必要があります。
.../CarMakers?$count=true

5.2. _ $ filter_

_ $ filter_クエリオプションを使用して、特定の_Entity Set_ *から返されるエンティティを特定の条件に一致するものに制限します。 _ $ filter_の値は、基本的な演算子、グループ化、多数の便利な機能をサポートする論理式です。 たとえば、__ Name __attributeが文字「B」で始まるすべての_CarMaker_インスタンスを返すクエリを作成しましょう。
.../CarMakers?$filter=startswith(Name,'B')
ここで、いくつかの論理演算子を組み合わせて、特定の_Year_と_Maker_の__CarModels __を検索します。
.../CarModels?$filter=Year eq 2008 and CarMakerDetails/Name eq 'BWM'
ここでは、等値演算子_eq_を使用して、プロパティの値を指定しました。 式で関連するエンティティのプロパティを使用する方法も確認できます。

5.3. _ $ expand_

*デフォルトでは、ODataクエリは関連エンティティのデータを返しません*。通常は問題ありません。 _ $ expand_クエリオプションを使用して、特定の関連エンティティからのデータをメインコンテンツにインラインで含めるように要求できます。
サンプルドメインを使用して、特定のモデルからデータを返すURLを作成し、メーカーへの追加の往復を回避します。
.../CarModels(1L)?$expand=CarMakerDetails
返されたドキュメントには、関連エンティティの一部として_CarMaker_データが含まれています。
<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
  xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
  xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
  xml:base="http://localhost:8080/odata/">
    <id>http://example.org/odata/CarModels(1L)</id>
    <title type="text">CarModels</title>
    <updated>2019-04-07T11:33:38.467-03:00</updated>
    <category term="default.CarModel"
      scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
    <link href="CarModels(1L)" rel="edit" title="CarModel"/>
    <link href="CarModels(1L)/CarMakerDetails"
      rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/CarMakerDetails"
      title="CarMakerDetails"
      type="application/atom+xml;type=entry">
        <m:inline>
            <entry xml:base="http://localhost:8080/odata/">
                <id>http://example.org/odata/CarMakers(1L)</id>
                <title type="text">CarMakers</title>
                <updated>2019-04-07T11:33:38.492-03:00</updated>
                <category term="default.CarMaker"
                  scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
                <link href="CarMakers(1L)" rel="edit" title="CarMaker"/>
                <link href="CarMakers(1L)/CarModelDetails"
                  rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/CarModelDetails"
                  title="CarModelDetails"
                  type="application/atom+xml;type=feed"/>
                <content type="application/xml">
                    <m:properties>
                        <d:Id>1</d:Id>
                        <d:Name>Special Motors</d:Name>
                    </m:properties>
                </content>
            </entry>
        </m:inline>
    </link>
    <content type="application/xml">
        <m:properties>
            <d:Id>1</d:Id>
            <d:Maker>1</d:Maker>
            <d:Name>Muze</d:Name>
            <d:Sku>SM001</d:Sku>
            <d:Year>2018</d:Year>
        </m:properties>
    </content>
</entry>

5.4. _ $ select_

$ selectクエリオプションを使用して、指定されたプロパティの値のみを返す必要があることをODataサービスに通知します。 これは、エンティティに多数のプロパティがあるシナリオで役立ちますが、それらの一部にのみ関心があります。
_Name_および__Sku __propertiesのみを返すクエリでこのオプションを使用してみましょう。
.../CarModels(1L)?$select=Name,Sku
結果のドキュメントには、要求されたプロパティのみが含まれるようになりました。
... xml omitted
    <content type="application/xml">
        <m:properties>
            <d:Name>Muze</d:Name>
            <d:Sku>SM001</d:Sku>
        </m:properties>
    </content>
... xml omitted
また、関連するエンティティでさえ省略されていることがわかります。 それらを含めるには、_ $ select_オプションにリレーションの名前を含める必要があります。

5.5. _ $ orderBy_

_ $ orderBy_オプションは、対応するSQLのオプションとほとんど同じように機能します。 これを使用して、サーバーが特定のエンティティのセットを返す順序を指定します。より単純な形式では、値は選択したエンティティからのプロパティ名のリストであり、オプションで順序の方向を通知します。
.../CarModels?$orderBy=Name asc,Sku desc
このクエリは、名前とSKUで並べ替えられた__CarModels ___のリストを、それぞれ昇順と降順で返します。
ここで重要な詳細は、特定のプロパティの方向部分で使用されるケースです:仕様では、サーバーがキーワード_asc_および_desc_の大文字と小文字の組み合わせをサポートする必要がある一方で、クライアントが使用することも義務付けられています小文字のみ** __.__

5.6. _ $ format_

このオプションは、サーバーが使用するデータ表現形式を定義します。これは、_Accept_などのHTTPコンテンツネゴシエーションヘッダーよりも優先されます。 その値は、完全なMIMEタイプまたは形式固有の短い形式である必要があります。
たとえば、* _ application / json_の省略形として__json __を使用できます:*
.../CarModels?$format=json
このURLは、前に見たように、XMLではなくJSON形式を使用してデータを返すようにサービスに指示します。 このオプションが存在しない場合、サーバーは_Accept_ヘッダーの値を使用します(存在する場合)。 どちらも使用できない場合、サーバーは任意の表現(通常はXMLまたはJSON)を自由に選択できます。
特にJSONに関しては、基本的にスキーマレスです。 ただし、OData 4.01はhttp://docs.oasis-open.org/odata/odata-csdl-json/v4.01/odata-csdl-json-v4.01.html [メタデータエンドポイントのJSONスキーマ]も定義しています。 つまり、XML処理を完全になくすことができるクライアントを作成できるようになりました。

6. 結論

このODataの簡単な紹介では、その基本的なセマンティクスと、簡単なデータセットナビゲーションの実行方法について説明しました。 私たちのフォローアップ記事は、私たちが去ったところから続き、Olingoライブラリに直行します。 次に、このライブラリを使用してサンプルサービスを実装する方法を説明します。
コード例は、いつものように、https://github.com/eugenp/tutorials/tree/master/apache-olingo [GitHubで]で入手できます。