Search:

Search all manuals
Search this manual
Manual
Couchbase Server マニュアル 2.0
Community Wiki and Resources
Couchbase Server 2.0をダウンロード
Couchbase 開発者ガイド 2.0
クライアントライブラリ
Couchbase Server フォーラム
Additional Resources
Community Wiki
Community Forums
Couchbase SDKs
Parent Section
D ビューのトラブルシューティング(技術的背景)
Chapter Sections
Chapters

D.4. include_docs=trueを使用したクエリでのドキュメントや行の間違い

次のようなデザインドキュメントを持っていると仮定します。

{
     "meta": {"id": "_design/test"},
     "views":
     {
         "view1": {
             "map": "function(doc, meta) { emit(meta.id,  doc.value); }"
         }
     }
 }

そしてバケットには、{"value": 1}というJSONの値を持つdoc1というドキュメントと、{"value": 2}というJSONの値を持つdoc2というドキュメントの2つのドキュメントだけがあり、最初にstale=falseinclude_docs=trueとgetでビューに問い合せます:

shell> curl -s 'http://localhost:9500/default/_design/test/_view/view1?include_docs=true&stale=false' | json_xs
 {
    "total_rows" :
2,
    "rows" :
[
       {
          "value" : 1,
          "doc"
: {
             "json" : {
                "value" : 1
             },
             "meta" : {
                "flags" : 0,
                "expiration" : 0,
                "rev" : "1-000000367916708a0000000000000000",
                "id" : "doc1"
             }
          },
          "id"
: "doc1",
          "key"
: "doc1"
       },
       {
          "value" : 2,
          "doc"
: {
             "json" : {
                "value" : 2
             },
             "meta" : {
                "flags" : 0,
                "expiration" : 0,
                "rev" : "1-00000037b8a32e420000000000000000",
                "id" : "doc2"
             }
          },
          "id"
: "doc2",
          "key"
: "doc2"
       }
    ]
 }

そのあとで、ドキュメントdoc1{"value": 111111}のJSONの値を持ち、ドキュメントdoc2{"value": 222222}のJSONの値を持つように両方のドキュメントを更新します。そして、stale=update_after(デフォルト)またはstale=okとgetでビューに問い合せます:

shell> curl -s 'http://localhost:9500/default/_design/test/_view/view1?include_docs=true' | json_xs
 {
    "total_rows" :
2,
    "rows" :
[
       {
          "value" : 1,
          "doc"
: {
             "json" : {
                "value" : 111111
             },
             "meta" : {
                "flags" : 0,
                "expiration" : 0,
                "rev" : "2-0000006657aeed6e0000000000000000",
                "id" : "doc1"
             }
          },
          "id"
: "doc1",
          "key"
: "doc1"
       },
       {
          "value" : 2,
          "doc"
: {
             "json" : {
                "value" : 222222
             },
             "meta" : {
                "flags" : 0,
                "expiration" : 0,
                "rev" : "2-00000067e3ee42620000000000000000",
                "id" : "doc2"
             }
          },
          "id"
: "doc2",
          "key"
: "doc2"
       }
    ]
 }

各行に含まれるドキュメントは、各行の値フィールドと一致しない、つまり含まれているドキュメントは、最新の(更新された)バージョンですが、インデックスの行の値は、まだドキュメントの以前の(最初の)バージョンを反映しています。

なぜこのような振る舞いになるのでしょうか?これは、include_docs=trueが、クエリ時に各行でディスクから各ドキュメントの最新リビジョンがフェッチされるように作用するからです。ドキュメントの以前のリビジョンを含める方法はありません。最新のvbucketデータベースMVCCスナップショット(http://en.wikipedia.org/wiki/Multiversion_concurrency_control)を介して以前のリビジョンにアクセスすることはできませんし、ドキュメントの特定のリビジョンが配置されているvbucketデータベースの以前のMVCCスナップショットから効率的に見つけることはできません。さらに、vbucketデータベースのコンパクションは、以前のすべてのMVCCスナップショット(ドキュメントのリビジョン)を削除します。要するに、これはデータベースエンジンの意図的な設計上の限界となっています。

ここで完全な一貫性を保証する唯一の方法は、map関数によって出力される値に、それらのドキュメント自体を含めることです。しかも、stale=falseを使用したクエリは、100%信頼できるものではなく、インデックスが更新されたすぐあとで、行がクライアントにディスクからストリーミングされている場合、ドキュメントの更新と削除はまだ例のように同じ振る舞いの結果となります。