Hatena::ブログ(Diary)

Kazzzの日記 このページをアンテナに追加 RSSフィード

2013-11-17

[]_docIdはインデックスが作られない?

生成したJSonドキュメントをキーによるフィルタで取得しようと

http://hostName/_je/docment?cond=_docId.gt.6O2GzSUnhB0Yglm7GyZquH

みたいな感じでURLを構成したのだが、クエリに全く掛からない。

jsonengineのドキュメントには以下のように書いてあるのだが

自動生成されるプロパティ
以下のプロパティーは、 jsonengine によって自動的に生成され、クライアントは変更する必要が有りません。これらの値は、フィルタリングやソートに使用することが出来ます。

_docId:各ドキュメントに振られる一意なID
_createdAt:ドキュメントが生成された時点のタイムスタンプ(long型)
_createdBy:ドキュメントを生成したユーザのユーザID
_updatedAt:ドキュメントが更新された時点のタイムスタンプ(long型)
_updatedBy:ドキュメントを更新したユーザのユーザID

基本的な使い方> 自動生成されるプロパティー

とあるので、_docIdもフィルタに使えるのだろうと思っていたのだが、実際にソースを見ると

    • JEDoc.java#isSkippedProp
private boolean isSkippedProp(String propName) {
    return propName.startsWith("_")
        && !(propName.equals(PROP_NAME_CREATED_AT)
            || propName.equals(PROP_NAME_CREATED_BY)
            || propName.equals(PROP_NAME_UPDATED_AT)
            || propName.equals(PROP_NAME_UPDATED_BY) || propName
            .equals(PROP_NAME_DISPLAY_NAME));
}

とあり、_docIdはインデックス生成の対照にはならないようだ。

2013-11-16

[][]jsonengineでページネーション

カーソル使おう、jsonengineに手を入れよう、AngularJS側でディレクティブ作ろうとか色々考えたんだが、jsonengineの条件式で出来てしまいそうなことに気が付いた。

page1-10
pagesize10
fetchLimit100
filterlimit=(10*10)=100

|

page11-20
pagesize10
fetchLimit100
filtercond=_docId.gt."id100"&limit=100

|

page21-30
pagesize10
fetchLimit100
filtercond=_docId.gt."id200"&limit=100

:
:
ポイントはフェッチした最初最後の_docIdを次の条件キーとして保存しておくことか。

一度に100件ずつ取得してあとはJavaScriptに任せて、ページの端に来たらjsonengineの条件を合成しなおして問合せ。
limitの制限内の件数の取得且つインデックスの付いたプロパティが使えるならカーソル使わなくても出来るし、降順のページネーションとか考えたらむしろカーソルの方が面倒かも。

結論 : jsonengine良くできてんな!

2013-08-17

[][][]DataStoreにputされたオブジェクトが直後のgetに含まれない

フロントエンドをAngularJSで書いてサーバーにはjsonengine(Slim3)を叩くプロトタイプを書いているのだが、腑に落ちない点がある。
jsonengineはRESTを受け付けるようにできており、jsonオブジェクトの問合せ(query)と保存(save)はAngularJSの$resourceをサービスとして書ける。

services.js
var services = angular.module('Hoge.Services', ['ngResource']);
services.factory("HogeProject", function($resource) {
    var Project = $resource(
        '/hoge/project?_docId=:projectId', {}, {
            query: {
                method: 'GET'
                , params: { projectId: '@projectId' }
            },
            save: {
                method: 'POST'
                , params: { projectId: '@projectId'}
                , data: { _doc : '@_doc'}  // StrigifyしたJSONをセット
            },
        });
    return Project;
});

呼び出すには以下のようなコードとなる。

HogeProjectサービスを呼び出すHogeController.js
function HogeController($scope, $route, $routeParams, HogeProject) {
   $scope.insertProject = function() {
        HogeProject.save({projectId : '', _doc: JSON.stringify($scope.formData)}
            , function(data) {
                //成功時
                //リロード
                $route.reload();
            }, function(responce) {
                //失敗時
            });
    };
}

insertProjectを呼び出すHTML
<form ng-contoller="HogeController">
    <button type="submit" ng-click="insertUdateProject()">登録</button>
</form>

中身はAjax Request/Responseだが随分とスマートになったもんだ。
まあそれはいいんだが、このようにしてjsonengineに保存したデータが、すぐには問合せの対象にはならないのである。

jsonengine側のコード(CRUDService.javaより抜粋)
public String put(CRUDRequest jeReq, boolean isUpdateOnly) {
    final Transaction tx = Datastore.beginTransaction();
    JEDoc jeDoc = getJEDoc(tx, jeReq);
    Datastore.put(tx, jeDoc);
    tx.commit();
}

サーバー側、jsonengineは内部ではSlim3のDatasourceクラスのputをトランザクション中で使っているが、内部的にはローレベルAPIを叩いており速度的には問題はないはずだ。
実際計測してもputに数ms〜数10msしかかかっておらずコミットも正常に完了している。

にも関わらず、直後に問合せしても登録されたはずのデータがgetで返ってこない。数100ms〜1秒程度遅れるようだ。
まだ調べているが、どうやらデータそのもののputが完了しても、その後非同期に他の処理を行っており、これが完了しないとgetの一覧には載ってこないのだと思われる。 うーん。なんだろ。