Help us understand the problem. What is going on with this article?

情報銀行のプラットフォームとして利用できるかもしれないPersonium(PDS) を検証してみる 8 <APIでODataを触ってみる>

<APIでWebDavを触ってみる>で WebDav についての理解は深められたので、次は当然 OData に進めましょう。

ODataとは正式名称は”Open Data Protocol”で「RESTfulなWebAPI(Webサービス)プロトコル」のことで、Microsoft主導で策定されたようです。
Personium でのDBエンジンは Elasticsearch を採用しており、インターフェスは OData という構図になっています。

インターフェースがRESTfulなWebAPIである点と、通常RDBとして採用されるOracleやMySQLなどとも若干差異がある部分もあり、その辺についても把握できることを目指したいと思います。

1.環境の確認

セルやボックスは、<APIでWebDavを触ってみる>で利用したものをそのまま使うこととし、以下のような環境で試してみましょう。

項目 備考
ユニット https://personium.takky.org
セル usercell
ボックス userbox
アカウント user
ロール userrole
コレクション(ACL) ODataContents (read,write) RDBでのデータベース
エンティティタイプ profile RDBでのテーブル

2.管理者権限でのODataのCollection(データベース)の作成

まずは恒例の… unitadmin のトークンを取得しましょう。

$ curl "https://personium.takky.org/unitadmin/__token" \
-X POST -i \
-d "grant_type=password&username={{unitAdminUser}}&password={{unitAdminPassword}}&p_target=https://personium.takky.org/" \
-H "Content-Type: application/x-www-form-urlencoded"

HTTP/1.1 200 
Date: Wed, 20 Mar 2019 05:28:50 GMT
Content-Type: application/json
Content-Length: 4378
Connection: keep-alive
Location: https://personium.takky.org/__token
X-Personium-Version: 1.7.4
Server: Personium

{
 "access_token":"{{unitAdminToken}}",
 "refresh_token_expires_in":86400,
 "refresh_token":"{{refreshToken}}",
 "p_target":"https:\/\/personium.takky.org\/",
 "token_type":"Bearer",
 "expires_in":3600
}

次は、コレクション(データベース)の作成です。
uriはWebDavと同様に、curl "https://personium.takky.org/{{cell}}/{{box}}/{{collection}}" のようにしましょう。

bodyには以下のようなXMLを記載する必要があるのですが、コレクションを作成する場合はこのままで良いようなので、そのまま利用します。
(リソースタイプは"odata"の"collection"ですよ。ということが表現されているようです。WebDavの時は"odata"の所に"WebDav"とは指定しなかったですが… ここに"WebDav"と"odata"の違いがありそうですね)
<D:mkcol xmlns:D=\"DAV:\" xmlns:p=\"urn:x-personium:xmlns\"><D:set><D:prop><D:resourcetype><D:collection/><p:odata/></D:resourcetype></D:prop></D:set></D:mkcol>

$ curl "https://personium.takky.org/usercell/userbox/ODataContents" -X MKCOL -i \
-d "<?xml version=\"1.0\" encoding=\"utf-8\"?><D:mkcol xmlns:D=\"DAV:\" xmlns:p=\"urn:x-personium:xmlns\"><D:set><D:prop><D:resourcetype><D:collection/><p:odata/></D:resourcetype></D:prop></D:set></D:mkcol>" \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 201 
Date: Wed, 20 Mar 2019 05:32:47 GMT
Content-Length: 0
Connection: keep-alive
ETag: "1-1553059967130"
X-Personium-Version: 1.7.4
Server: Personium

レスポンスコードが200番台なので、成功したようなのですが… ほんまかね??

確認してみましょう!
確認の方法も、WebDavと全く同じですね。

$ curl "https://personium.takky.org/usercell/userbox/ODataContents" \
-X PROPFIND -i \
-H 'Depth:1' \
-d '<?xml version="1.0" encoding="utf-8"?><D:propfind xmlns:D="DAV:"><D:allprop/></D:propfind>' \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 207 
Date: Wed, 20 Mar 2019 05:40:59 GMT
Content-Type: application/xml
Content-Length: 709
Connection: keep-alive
ETag: "1-1553059967130"
X-Personium-Version: 1.7.4
Server: Personium

<multistatus xmlns="DAV:">
    <response>
        <href>https://personium.takky.org/usercell/userbox/ODataContents</href>
        <propstat>
            <prop>
                <creationdate>2019-03-20T05:32:47.130+0000</creationdate>
                <getlastmodified>Wed, 20 Mar 2019 05:32:47 GMT</getlastmodified>
                <resourcetype>
                    <collection/>
                    <p:odata xmlns:p="urn:x-personium:xmlns"/>
                </resourcetype>
                <acl xml:base="https://personium.takky.org/usercell/__role/userbox/" xmlns:p="urn:x-personium:xmlns"/>
            </prop>
            <status>HTTP/1.1 200 OK</status>
        </propstat>
    </response>
</multistatus>

大丈夫そうです。
念のため、ユニットマネージャでも確認。
image.png

ちゃんとできてますね!! OKです。

3.管理者権限でのODataのEntityType(テーブル)の作成

次はテーブルの作成になりますね。
ODataではテーブルではなく EntityType と呼ばれているようです。
しかもこのテーブル作成時には、RDBでいうカラム(Entity)などは設定しなくても良いようです。
まずは、この EntityType を作成しましょう。

$ curl "https://pds.takky.org/OData/ODataBox/testOData/\$metadata/EntityType" \
-X POST -i \
-d '{ "Name":"profile"}' \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 201 
Date: Wed, 20 Mar 2019 05:59:25 GMT
Content-Type: application/json
Content-Length: 302
Connection: keep-alive
Location: https://personium.takky.org/usercell/userbox/ODataContents/$metadata/EntityType('profile')
DataServiceVersion: 2.0
ETag: W/"1-1553061565244"
X-Personium-Version: 1.7.4
Server: Personium

{
  "d":{
    "results":{
      "__metadata":{
        "uri":"https:\/\/personium.takky.org\/usercell\/userbox\/ODataContents\/$metadata\/EntityType('profile')",
        "etag":"W\/\"1-1553061565244\"",
        "type":"ODataSvcSchema.EntityType"
      },
      "Name":"profile","__published":"\/Date(1553061565244)\/",
      "__updated":"\/Date(1553061565244)\/"
    }
  }
}

これもレスポンスコードが200番台で返ってきました!
こちらも念のため、ユニットマネージャで確認しておきましょう…

image.png

"ODataContents"コレクションの配下に、"profile"が存在しています。
OKですね!!

コマンドでは確認すれば良いのでしょう?
以下のように"GET"で確認できるようで、WebDavの取得方法("PROPFIND")ではないみたいですね。

$ curl "https://personium.takky.org/usercell/userbox/ODataContents/\$metadata" \
-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200 
Date: Wed, 20 Mar 2019 06:11:00 GMT
Content-Type: application/xml;charset=utf-8
Content-Length: 1084
Connection: keep-alive
DataServiceVersion: 1.0
X-Personium-Version: 1.7.4
Server: Personium

<?xml version="1.0" encoding="utf-8"?>
  <edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:p="urn:x-personium:xmlns">
    <edmx:DataServices m:DataServiceVersion="1.0">
      <Schema xmlns="http://schemas.microsoft.com/ado/2006/04/edm" Namespace="UserData">
        <EntityType Name="profile" OpenType="true">
          <Key>
            <PropertyRef Name="__id"></PropertyRef>
          </Key>
          <Property Name="__id" Type="Edm.String" Nullable="false" DefaultValue="UUID()" p:Format="regEx('^.{1,400}$')"></Property>
          <Property Name="__published" Type="Edm.DateTime" Nullable="false" DefaultValue="SYSUTCDATETIME()" Precision="3"></Property>
          <Property Name="__updated" Type="Edm.DateTime" Nullable="false" DefaultValue="SYSUTCDATETIME()" Precision="3"></Property>
        </EntityType>
        <EntityContainer Name="UserData" m:IsDefaultEntityContainer="true">
          <EntitySet Name="profile" EntityType="UserData.profile"></EntitySet>
        </EntityContainer>
      </Schema>
    </edmx:DataServices>
  </edmx:Edmx>

急にXMLでのレスポンスになりました…(びっくり!)
EntityTypeは「Name="profile"」です。正しいですね。
Key が「Name="__id"」で、
Property として「Name="__id"」「Name="__published"」「Name="__updated"」があるのでしょうか??

こちらもユニットマネージャで確認してみましょう。
image.png

おゃ… [Schema]を開いてみると、Property には何もなく…「No properties added yet」とな?!
もしかすると上記の3つの値は、デフォルトで作成され、かつ、デフォルトで値が入力されるカラムなのかもね??

『OData Service Collection (OSC)の使い方』 というドキュメントに記載がありました。
やはり、3つの項目(列)は自動で作成されるようです。大丈夫!!
image.png

4.管理者権限でのデータのストア

では満を持して… データを挿入してみましょう。

$ curl "https://personium.takky.org/usercell/userbox/ODataContents/profile" \
-X POST -i \
-d '{"name": "Takky"}' \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 201 
Date: Wed, 20 Mar 2019 06:45:46 GMT
Content-Type: application/json
Content-Length: 344
Connection: keep-alive
Location: https://personium.takky.org/usercell/userbox/ODataContents/profile('d2f6a5c5c718401ab86c98a555e331f1')
DataServiceVersion: 2.0
ETag: W/"1-1553064346586"
X-Personium-Version: 1.7.4
Server: Personium

{
  "d":{
    "results":{
      "__metadata":{ 
        "uri":"https:\/\/personium.takky.org\/usercell\/userbox\/ODataContents\/profile('d2f6a5c5c718401ab86c98a555e331f1')",
        "etag":"W\/\"1-1553064346586\"",
        "type":"UserData.profile"
      },
      "__id":"d2f6a5c5c718401ab86c98a555e331f1",
      "__published":"\/Date(1553064346586)\/",
      "__updated":"\/Date(1553064346586)\/",
      "name":"Takky"
    }
  }
}

おぉ! イケましたわぁ。
name列が作られ、"Takky"が設定されています。
そして想定通り、"__id" "__published" "__updated"にも、値が入力されています。

ユニットマネージャでの確認でも、スキーマとして"name"が確認でき、実際のデータにも"name"列に"Takky"として1レコード挿入されています。完璧です!!
image.png

5.ユーザー権限でのスキーマの参照

では次に… ユーザー権限でODataのオブジェクトにアクセスしてみましょう。
当然、エラーになるんだと思います。

まずは、トークンの取得。

$ curl "https://personium.takky.org/usercell/__token" \
-X POST -i \
-d "grant_type=password&username={{userName}}&password={{userPassword}}" \
-H "Content-Type: application/x-www-form-urlencoded"

HTTP/1.1 200 
Date: Sun, 24 Mar 2019 01:49:13 GMT
Content-Type: application/json
Content-Length: 331
Connection: keep-alive
X-Personium-Version: 1.7.4
Server: Personium

{
  "access_token":"{{user_token}}",
  "refresh_token_expires_in":86400,
  "refresh_token":{{fefresh_token}}",
  "token_type":"Bearer",
  "expires_in":3600
}

では、ユーザー権限でアクセスしましょう。

$ curl "https://personium.takky.org/usercell/userbox/ODataContents/\$metadata" \
-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{user_token}}"

HTTP/1.1 403 
Date: Sun, 24 Mar 2019 02:02:05 GMT
Content-Type: application/json
Content-Length: 90
Connection: keep-alive
X-Personium-Version: 1.7.4
Server: Personium

{
  "code":"PR403-AU-0002",
  "message":{
    "lang":"en",
    "value":"Necessary privilege is lacking."
  }
}

当然、「権限が足りない」エラーですね。

では次に、<APIでWebDavを触ってみる>で作成済みの、ユーザー(user)にひも付いているロール(userrole)にACL(read, write)を付与しましょう。

url 'https://personium.takky.org/usercell/userbox/ODataContents'  \
-X ACL -i \
-d '<D:acl xmlns:D="DAV:" xmlns:p="urn:x-personium:xmlns" xml:base="https://personium.takky.org/usercell/__role/userbox/"><D:ace><D:principal><D:href>userrole</D:href></D:principal><D:grant><D:privilege><p:read/></D:privilege><D:privilege><p:write/></D:privilege></D:grant></D:ace></D:acl>' \
-H "Accept:application/json" -H "Authorization:Bearer {{unitAdminToken}}"

HTTP/1.1 200 
Date: Sun, 24 Mar 2019 02:14:04 GMT
Content-Length: 0
Connection: keep-alive
ETag: "2-1553059967130"
X-Personium-Version: 1.7.4
Server: Personium

ACLを付与したので、もう一度…

$ curl "https://personium.takky.org/usercell/userbox/ODataContents/\$metadata" \
-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{user_token}}"

HTTP/1.1 200 
Date: Sun, 24 Mar 2019 02:15:59 GMT
Content-Type: application/xml;charset=utf-8
Content-Length: 1172
Connection: keep-alive
DataServiceVersion: 1.0
X-Personium-Version: 1.7.4
Server: Personium

<?xml version="1.0" encoding="utf-8"?>
  <edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:p="urn:x-personium:xmlns">
    <edmx:DataServices m:DataServiceVersion="1.0">
      <Schema xmlns="http://schemas.microsoft.com/ado/2006/04/edm" Namespace="UserData">
        <EntityType Name="profile" OpenType="true">
          <Key>
            <PropertyRef Name="__id"></PropertyRef>
          </Key>
          <Property Name="__id" Type="Edm.String" Nullable="false" DefaultValue="UUID()" p:Format="regEx('^.{1,400}$')"></Property>
          <Property Name="__published" Type="Edm.DateTime" Nullable="false" DefaultValue="SYSUTCDATETIME()" Precision="3"></Property>
          <Property Name="__updated" Type="Edm.DateTime" Nullable="false" DefaultValue="SYSUTCDATETIME()" Precision="3"></Property>
          <Property Name="name" Type="Edm.String" Nullable="true" p:IsDeclared="false</Property>
        </EntityType>
        <EntityContainer Name="UserData" m:IsDefaultEntityContainer="true">
          <EntitySet Name="profile" EntityType="UserData.profile"></EntitySet>
        </EntityContainer>
      </Schema>
    </edmx:DataServices>
  </edmx:Edmx>

イケてますね!

6.ユーザー権限でのデータのストア

ここでは、name列に"USER"のレコードを挿入しましょう。
これに成功すると、unitadmmin で挿入した"Takky"との2レコードになるはずです。

curl "https://personium.takky.org/usercell/userbox/ODataContents/profile" \
-X POST -i \
-d '{"name": "USER"}' \
-H "Accept:application/json" -H "Authorization:Bearer {{user_token}}"

HTTP/1.1 201 
Date: Sun, 24 Mar 2019 02:23:25 GMT
Content-Type: application/json
Content-Length: 343
Connection: keep-alive
Location: https://personium.takky.org/usercell/userbox/ODataContents/profile('471d31832e894809b5d18943dae3d20c')
DataServiceVersion: 2.0
ETag: W/"1-1553394205719"
X-Personium-Version: 1.7.4
Server: Personium

{
  "d":{
    "results":{
      "__metadata":{
        "uri":"https:\/\/personium.takky.org\/usercell\/userbox\/ODataContents\/profile('471d31832e894809b5d18943dae3d20c')",
        "etag":"W\/\"1-1553394205719\"",
         "type":"UserData.profile"
      },
      "__id":"471d31832e894809b5d18943dae3d20c",
      "__published":"\/Date(1553394205719)\/",
      "__updated":"\/Date(1553394205719)\/",
      "name":"USER"
    }
  }
}

7.ユーザー権限でのデータの参照

では、実際に"Takky"と"USER"レコードがストアされているデータを参照(SELECT)してみましょう。

$ curl "https://personium.takky.org/usercell/userbox/ODataContents/profile" \
-X GET -i \
-H "Accept:application/json" -H "Authorization:Bearer {{user_token}}"

HTTP/1.1 200 
Date: Sun, 24 Mar 2019 02:43:13 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 672
Connection: keep-alive
DataServiceVersion: 2.0
X-Personium-Version: 1.7.4
Server: Personium

{
  "d":{
    "results":[
      {
        "__metadata":{
          "uri":"https:\/\/personium.takky.org\/usercell\/userbox\/ODataContents\/profile('d2f6a5c5c718401ab86c98a555e331f1')",
          "etag":"W\/\"1-1553064346586\"",
          "type":"UserData.profile"
        },
        "__id":"d2f6a5c5c718401ab86c98a555e331f1",
        "__published":"\/Date(1553064346586)\/",
        "__updated":"\/Date(1553064346586)\/",
        "name":"Takky"
      },{
        "__metadata":{
          "uri":"https:\/\/personium.takky.org\/usercell\/userbox\/ODataContents\/profile('471d31832e894809b5d18943dae3d20c')",
          "etag":"W\/\"1-1553394205719\"",
          "type":"UserData.profile"
        },
        "__id":"471d31832e894809b5d18943dae3d20c",
        "__published":"\/Date(1553394205719)\/",
        "__updated":"\/Date(1553394205719)\/",
        "name":"USER"
      }
    ]
  }
}

profile テーブルに、これまでにストアした「Takky」「USER」が存在していることが確認できます。OKですね。

ついでにユニットマネジャーでも確認。
同様に、「Takky」「USER」が存在しています。
OK!!
image.png

ODataコレクション(テーブル)の作成と、レコードの登録・参照が完了です!


最後に…

ODataとはインターフェスであり、実際のデータベースとしての機能は Elasticsearch が提供しています。Personium のデータベース機能を効果的に利用するためには、OData と Elasticsearchを把握することにより理解が深まるかと思います。

まぁでも全部を把握する必要もないと思いますので、Personium API リファレンス内の以下のAPIを把握することになるでしょう。
image.png

CollectionやEntityType、EntitySet などをざっくり把握できれば、ほぼRDBと似た操作でデータを扱うことができるので、大いに活用したい機能ですね。


メニュー

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした