4 gaedirectでの条件検索
ここからはgaedirectでの条件検索機能を見ていきます。Bigtableは分散キー・バリューストア(分散KVS)ですが、分散KVSは特に条件検索での制約が多く、RDBには劣っている点も多いと言われています。確かに集合関数が使用できないことを始めとしてSQL機能では見劣りする点も多く、gaedirectの条件検索機能はさらにそのサブセットになっています。これはJavaScriptでの直接アクセス方式によるgaedirectではGAEデータストアの複合インデックスを使用することが困難なことからやむをえないとも言えます。しかしそのためにgaedirectの条件検索は使えない、ということは決してありません。
4.1 全件参照
(1)画面例
(2)プログラムサンプル
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>条件検索</title> <script type="text/javascript" src="/jslib/gaedirect.js"></script> <script type="text/javascript" src="/jslib/jquery-1.6.1.min.js"></script> <script type="text/javascript"> $(function(){ var query = ginit(); query["kind"] = "cook"; query["key"] = "none"; query["id"] = "name,tel,menu,bill"; var query = rinit(); var kind = "cook"; prop = "name,tel,menu,bill"; $("#rcond1").click(function(){ // Rev All var query = rinit(); $.get(gae(), query, function(res){render(prop, res);}); }); }); function rinit(){ var query = ginit(); query["kind"] = "cook"; //(1) query["key"] = "none"; //(2) query["id"] = "name,tel,menu,bill" //(3) return query; } function render(prop, res){ var tags = ""; var head = prop.split(","); var tags = "<table border='1'><tr><th>key</th>"; for (var i=0; i < head.length; i++){ tags += "<th>" + head[i] + "</th>"; } tags += "</tr>"; var entity = res.split("<e>"); for(var i = 0; i < entity.length; i++){ tags += "<tr>"; var property = entity[i].split("<p>"); for (var j = 0; j < property.length-1; j++) { tags += "<td>" + property[j] + "</td>"; } tags += "</tr>"; } tags += "</table>"; $("#out").html(tags); } </script> </head> <body> <h2 style="color: #aa0022">gaedirectで条件検索</h2> ステータス:<span id="stat"></span><br/> <div><input type="button" id="rcond1" value=" 参照 "/>[1] 全件参照</div> <div><input type="button" id="rcond2" value=" 参照 "/>[2] 名前で昇順ソート</div> <div><input type="button" id="rcond3" value=" 参照 "/>[3] メニューに「2」を含むエンティティを選択</div> <div><input type="button" id="rcond4" value=" 参照 "/>[4] 名前で降順ソート、オフセット=3</div> <div><input type="button" id="rcond5" value=" 参照 "/>[5] 名前で降順ソート、オフセット=2、リミット=5</div> <div><input type="button" id="rcond6" value=" 参照 "/>[6] 料金で昇順ソート、料金が3000円以上</div> <div><input type="button" id="rcond7" value=" 参照 "/>[7] 料金で降順ソート、3000≦料金<3800</div> <div><input type="button" id="rcond8" value=" 参照 "/>[8] メニューが「3」(洋食)」以外を含む</div> <div><input type="button" id="rcond9" value=" 参照 "/>[9] メニューが「2」(洋食)または「3」(中華)を含む</div> </p> <div id="out"></div> </body> </html>
gaedirectでの条件検索では最初に共通の処理として、(1)でkind名を指定し、(2)ではキー名にnoneを指定し、(3)でプロパティ項目(prop)の定義を行います、
次にkindとpropを引数指定してrinit ()関数での初期化処理を行います(注)。ここまではすべての条件検索で共通の指定項目ですが、この状態で(4)で$.getでのサーバリクエストを発行すれば全件検索になります。
サンプルでの画面表示は共通のrendar関数で行っています。GAEでの条件検索データは、次のファーマットでレスポンスされています。
- エンティティ単位で"<e>"で区切られる
- プロパティ単位で"<p>"で区切られる
また、ここでは処理していませんが、リストデータはカンマ(",")区切りで返されます。
render関数はサンプルでのレスポンスデータ用に作成された画面表示ルーチンです。
この部分の指定はv1.1ではより簡略化されています。またrinitをユーザが記述する形になっていますが、v1.1からはqinitを呼びだすだけで、ユーザ記述の必要はなくなります。
4.2 名前で昇順ソート
(1)画面例
(2)プログラムサンプル
$("#rcond2").click(function(){ var query = rinit(); query["SORT"] = "name:ASCENDING"; $.get(gae(), query, function(res){render(prop , res);}); });
ソートではqueryキーに"SORT"を指定し、バリューでソート対象のプロパティ値と、昇順(ASCENDING)または降順(DESCENDING)の指定を":"区切りで指定します。
4.3 メニューに「2」を含むエンティティを選択
(1)画面例
(2)プログラムサンプル
$("#rcond3").click(function(){ var query = rinit(); query["EQUAL"] = "menu:2"; $.get(gae(), query, function(res){render(prop, res);}); });
query["EQUAL"]の右辺に文字列で、プロパティ名とその値を「:」区切りで指定すると、イコール「=」検索になります。サンプルでは「menu="2"」 で検索が行われます。
リストプロパティの場合は図4-3のように、リストに「2」を含む場合は選択の対象になります。
4.4 名前で降順ソート、オフセット=3
(1)画面例
(2)プログラムサンプル
$("#rcond4").click(function(){ var query = rinit(); query["SORT"] = "name:DESCENDING"; query["OFFSET"] = "3"; $.get(gae(), query, function(res){render(prop, res);}); });
リスト4-4では、プロパティ「name」で降順ソートした後、先頭の3件をスキップしてデータ表示します。
4.5 名前で降順ソート、オフセット=2、リミット=5
(1)画面例
(2)プログラムサンプル
$("#rcond5").click(function(){ var query = rinit(); query["SORT"] = "name:DESCENDING"; query["OFFSET"] = "2"; query["LIMIT"] = "5"; $.get(gae(), query, function(res){render(prop, res);}); });
リスト4-5では、プロパティ名「name」で降順ソートした後、先頭の2件をスキップし、次からの5件を表示します。
4.6 料金で昇順ソート、料金が3000円以上
(1)画面例
(2)プログラムサンプル
$("#rcond6").click(function(){ var query = rinit(); query["SORT"] = "bill:ASCENDING"; query["GREATER_THAN"] = "in:bill:3000"; $.get(gae(), query, function(res){render(prop, res);}); });
リスト4-6では、プロパティ「bill」で昇順ソートした後、Integer型のプロパティ「bill」の値が3000以上のエンティティを表示します。
4.7 料金で降順ソート、3000≦料金<3800
(1)画面例
(2)プログラムサンプル
$("#rcond7").click(function(){ var query = rinit(); query["SORT"] = "bill:DESCENDING"; query["GREATER_THAN_OR_EQUAL"] = "in:bill:3000"; query["LESS_THAN"] = "in:bill:3800"; $.get(gae(), query, function(res){render(prop, res);}); });
リスト4-7では、「GREATER_THAN_OR_EQUAL」と「LESS_THAN」を使用して、プロパティbillに対して3000≦long<3800で条件検索しています。
4.8 メニューが「3」(洋食)」以外を含む
(1)画面例
(2)プログラムサンプル
$("#rcond8").click(function(){ var query = rinit(); query["NOT_EQUAL"] = "menu:3"; $.get(gae(), query, function(res){render(prop, res);}); });
リスト4-8では、「NOT_EQUAL」でmenuに3を含むエンティティを検索対象から除外しています。
ただしリストプロパティの場合は、図4-8のようにリストに3以外が含まれる場合は検索対象に含まれます。
4.9 メニューが「2」(洋食)または「3」(中華)を含む
(1)画面例
(2)プログラムサンプル
$("#rcond9").click(function(){ var query = rinit(); query["IN"] = "menu:2,3"; $.get(gae(), query, function(res){render(prop1, res);}); });
リスト4-9では、「IN」でプロパティmenuに、「2」(洋食)または「3」(中華)を含むプロパティが表示されます。
まとめ
ここまでgaedirectのCRUD(登録、参照、更新、削除)処理と条件検索を見てきましたが、このようなjQueryを使用した簡単なJavaScript記述でGAEのBigtableをアクセスすることができます。これは、GAEでのサーバ側プログラムを習得して同じコードを記述する場合に比べて、おそらく十分の一以下の工数でクラウドシステムを構築することができるはずです。そしてクラウド上にシステムを構築することは、「1.1 クラウド移行の意義」で述べたような利点があり、例えば非常時でもシステムダウンやデータ消失のない継続的運用の要求に対してはGAEのような本格的クラウドシステムが最も適しており、筆者の個人的な考えでは現状唯一の最適解と思います。
gaedirectはもちろんGAEのすべての機能を満足するものではなくそのサブセットにすぎませんが、データストアアクセスに関するか要となる機能については十分使用できるレベルです。またこれからも、GAEの機能を追加していき、JavaScriptおよびjQueryから可能な限りGAEのサーバ機能を使用することをできるようにする予定です。ただそのためには、多くの皆さんに使っていただくことがどうしても前提になってきますので、ぜひ多くの皆さんに使って頂ければと思います。
またこれからも、GAEの機能を追加していき、JavaScriptおよびjQueryから可能な限りGAEのサーバ機能を使用できるようにする予定です。たとえばChannel APIでのサーバプッシュ機能をクライアント側のJavaScript記述のみで行えるようにすることも現在進めています。
ただgaedirectの開発を進めていくためには、多くの皆さんに使っていただくことがどうしても前提になってきます。ぜひ多くの皆さんに使っていただければと思います。