7

CouchDBに関しては、私は初心者です。私は .NET SQL Server の世界から来ました。

CouchDB Definitive Guide をざっと読んで、「これはすごい」と思いました。今、私は学んだことのいくつかを実際の世界で実装することを期待してテストしています.

数週間前に Cloudant アカウントにサインアップし、テストや学習のために使用し始めました。

リンクされたドキュメントをいじると、背後にある理論全体が単純に見え、インターネット上の単純な例にも見えます。さまざまなリンクされたドキュメントの配列を持つドキュメントからいくつかの情報を取得したい場合、それら自体がリンクされたドキュメントの配列を持っています。多対多の関係テーブルに結合するマルチ SQL Server のように。以下にコードを示します。うまくいけば、それは理にかなっています。

たとえば、この SQL クエリを考えてみましょう。各テーブルに 1 つのエントリしかないと仮定すると、特定の SKU を持つ靴のすべての詳細を含む 1 つのレコードが返されるはずです。しかし、靴のサイズが複数ある場合は、さらにコードを記述する必要があります。

select ci.sku
        ,sc.color
        ,ss.size
        ,si.url
from CatalogItem ci
    join ShoeImages si
        on ci.sku = si.sku
        and ci.sku = '656F-PINSEC12'
    join ShoeSizes ss
        on ci.sku = ss.sku
    join ShoeColors sc
        on ci.sku = sc.sku

https://username.cloudant.com/test/_design/catalogue/_view/item-details?include_docs=true&key=%22656F-PINSEC12%22にある SKU ごとに、CouchDB に次の JSON を返してもらいたいと思います。

{
   "_id": "689fe6982f4d604541db67ee4050a535",
   "_rev": "5-64b5ddd751c51aadfcef1962c2c99c16",
   "type": "catalogue-item",
   "sku": "656F-PINSEC12",
   "upc": "8549875231",
   "shoe-colors": 
   [
        {
            "color": "black/houndstooth"
            "shoe-sizes": 
            [
                {
                    "size": 5,
                    "IsSizeAvailable": true
                },
                {
                    "size": 6,
                    "IsSizeAvailable": true
                },
                {
                    "size": 7,
                    "IsSizeAvailable": true
                },
                {
                    "size": 8,
                    "IsSizeAvailable": true
                },
                {
                    "size": 9,
                    "IsSizeAvailable": true
                },
                {
                    "size": 10,
                    "IsSizeAvailable": true
                },
                {
                    "size": 11,
                    "IsSizeAvailable": true
                },
                {
                    "size": 12,
                    "IsSizeAvailable": true
                },
                {
                    "size": 13,
                    "IsSizeAvailable": true
                },
                {
                    "size": 14,
                    "IsSizeAvailable": true
                }
            ],
            "shoe-images": 
            [
                {
                    "full-images": 
                    [
                        "http://www.someurl.com/full/656F-PINSEC12.jpg"
                    ],
                    "thumbnail-images": 
                    [
                        "http://www.someurl.com/thumb/656F-PINSEC12.jpg"
                    ]
                }
            ]
        }
    ]
}

次のドキュメントと map/reduce があるとします。

//--catalog item
{
   "_id": "689fe6982f4d604541db67ee4050a535",
   "_rev": "5-64b5ddd751c51aadfcef1962c2c99c16",
   "type": "catalogue-item",
   "sku": "656F-PINSEC12",
   "upc": "8549875231",
   "shoe-colors": [
       {
           "_id": "bbbb92c3d61ed9f4f0e8111fb20fcf43",
           "shoe-images": [
               {
                   "_id": "7b547bae4ac911c6f05b97eba6cb355a"
               }
           ],
           "shoe-sizes": [
               {
                   "_id": "12b6289d558d7ceb5bef725091666ce5"
               }
           ]
       }
   ]
}

//--shoe images
{
   "_id": "7b547bae4ac911c6f05b97eba6cb355a",
   "_rev": "4-4fde0cac1b4b8afc618bbba5b6669193",
   "type": "shoe-images",
   "sku": "656F-PINSEC12",
   "color": "Black/Houndstoot",
   "full-images": [
       "http://www.someurl.com/full/656F-PINSEC12.jpg"
   ],
   "thumbnail-images": [
       "http://www.someurl.com/thumb/656F-PINSEC12.jpg"
   ]
}

//--shoe color
{
   "_id": "bbbb92c3d61ed9f4f0e8111fb20fcf43",
   "_rev": "2-e5d07c00a0261c231dd2be9b26a6c0dc",
   "type": "shoe-color",
   "sku": "656F-PINSEC12",
   "color": "black/houndstooth"
}

//--shoe sizes
{
   "_id": "12b6289d558d7ceb5bef725091666ce5",
   "_rev": "2-192df709f9de1ef27e9e5f4404863bcc",
   "type": "shoe-sizes",
   "sku": "656F-PINSEC12",
   "shoe-color": "black/houndstooth",
   "shoe-sizes": [
       {
           "size": 5,
           "IsSizeAvailable": true
       },
       {
           "size": 6,
           "IsSizeAvailable": true
       },
       {
           "size": 7,
           "IsSizeAvailable": true
       },
       {
           "size": 8,
           "IsSizeAvailable": true
       },
       {
           "size": 9,
           "IsSizeAvailable": true
       },
       {
           "size": 10,
           "IsSizeAvailable": true
       },
       {
           "size": 11,
           "IsSizeAvailable": true
       },
       {
           "size": 12,
           "IsSizeAvailable": true
       },
       {
           "size": 13,
           "IsSizeAvailable": true
       },
       {
           "size": 14,
           "IsSizeAvailable": true
       }
   ]
}

//--map/reduce
{
   "_id": "_design/catalog",
   "_rev": "4-de5baf04b485768de12d78e5a0e5aa5e",
   "views": {
       "item": {
           "map": "function(doc) 
                {
                  if (doc.type === 'catalog-item') 
                  {
                    emit([doc.sku, doc], null);
                    if (doc.shoe-colors) 
                    {
                      for (var sc in doc.shoe-colors) 
                      {
                        emit([doc.sku, Number(sc)+1], {_id: doc.shoe-colors[sc]._id});
                        for (var si in doc.shoe-colors[sc].shoe-images) 
                        {
                            emit([doc.sku, Number(si)+1], {_id: doc.shoe-colors[sc].shoe-images[si]._id});
                        }
                        for (var sz in doc.shoe-colors[sc].shoe-sizes) 
                        {
                            emit([doc.sku, Number(sz)+1], {_id: doc.shoe-colors[sc].shoe-sizes[sz]._id});
                        }
                      }
                    }
                  }
                }"
       }
   }
}

これを実装するより良い方法があるかもしれませんが、リンクされたドキュメントの配列も持つリンクされたドキュメントの配列を持つドキュメントを持つことが可能かどうかを確認したかったのです。しかし、私の map/reduce は何も返しません。返されるのは次のとおりです。

{"total_rows":0,"offset":0,"rows":[

]}

新しいショーのサイズを追加したり、靴のサイズを利用できないとマークしたりすると、以前の値をすべて CouchDB に戻す必要があるため、誰かがすべての情報を 1 つのドキュメントに保存することはないと思います。 1 つのフィールドを更新します。

うまくいけば、私の質問は理にかなっています Oo__oO

4

1 に答える 1

5

これの秘訣は、JOIN の観点から考えるのをやめることです。リンクされたドキュメントを使用すると、別のタイプのドキュメントのプロパティに基づいて、あるタイプのドキュメントにインデックスを付けることができます。これは、次の 2 つの機能の組み合わせを使用して機能します。

  1. CouchDB では、ビューを照会するときに include_docs=true を指定して、ビューの結果とともにインデックス付きドキュメントを返すことができます。
  2. ビューの結果で _id プロパティを指定することにより、CouchDB に任意のドキュメントを返すように指示できます。結果ごとに 1 つのドキュメントしか返せないことに注意してください。

例として、ドキュメントがあるとしましょう

{
     "_id": "111",
     "type", "shoe",
     "sku": "656F-PINSEC12",
     "shoe-color": "black/houndstooth",
     "imageId": "222"
}

{
     "_id": "222",
     "type": "image",
     "full-images": ["http://www.someurl.com/full/656F-PINSEC12.jpg"]
     "thumbnail-images": ["http://www.someurl.com/thumb/656F-PINSEC12.jpg"]
}

次に、map 関数を使用して SKU ごとに画像をインデックス化できます。

function(doc) {
     if(doc.type === "shoe") {
         emit(doc.sku, {_id: doc.imageId });
     }
}

また、マップ機能は保存された元のドキュメントに対してのみ機能することを認識することも重要です。

あなたの例では、「カタログアイテム」と「靴の色」のドキュメントは冗長だと思います。たとえば、SKU ごとに「靴の画像」と「靴のサイズ」のドキュメントをインデックス化するマップ関数を定義できます。

function(doc) {
    if(doc.SKU) {
        emit(doc.SKU, null);
    }
}

これがビュー「item-details」に割り当てられたと仮定すると、クエリは次のようになります。

https://username.cloudant.com/test/_design/catalogue/_view/item-details?include_docs=true&key=%22656F-PINSEC12%22

戻るべき

{
   "total_rows":2,
   "offset":0,
   "rows":
   [
       {
          "id":"7b547bae4ac911c6f05b97eba6cb355a",
          "key":"656F-PINSEC12",
          "value":null,
          "doc":{
             "_id": "7b547bae4ac911c6f05b97eba6cb355a",
             "_rev": "4-4fde0cac1b4b8afc618bbba5b6669193",
             "type": "shoe-images",
             "sku": "656F-PINSEC12",
             "color": "Black/Houndstoot",
             "full-images": [
                 "http://www.someurl.com/full/656F-PINSEC12.jpg"
             ],
             "thumbnail-images": [
                  "http://www.someurl.com/thumb/656F-PINSEC12.jpg"
             ]
          }
      },
      {
          "id":"12b6289d558d7ceb5bef725091666ce5",
          "key":"656F-PINSEC12",
          "value":null
          "doc":{
            "_id": "12b6289d558d7ceb5bef725091666ce5",
           "_rev": "2-192df709f9de1ef27e9e5f4404863bcc",
           "type": "shoe-sizes",
           "sku": "656F-PINSEC12",
           "shoe-color": "black/houndstooth",
           "shoe-sizes": [
               {
                   "size": 5,
                   "IsSizeAvailable": true
               },
               {
                   "size": 6,
                   "IsSizeAvailable": true
               },
               {
                   "size": 7,
                   "IsSizeAvailable": true
               },
               {
                   "size": 8,
                   "IsSizeAvailable": true
               },
               {
                   "size": 9,
                   "IsSizeAvailable": true
               },
               {
                   "size": 10,
                   "IsSizeAvailable": true
               },
               {
                   "size": 11,
                   "IsSizeAvailable": true
               },
               {
                   "size": 12,
                   "IsSizeAvailable": true
               },
               {
                   "size": 13,
                   "IsSizeAvailable": true
               },
               {
                   "size": 14,
                   "IsSizeAvailable": true
               }
           ]

        }       
    ] 
}

これらの結果を 1 つの JSON ドキュメントに結合したい場合は、リスト関数を使用してカスタム JSON 出力を生成することを検討できます。ただし、それがあなたに多くの利益をもたらすかどうかはわかりません。

一般的には、より詳細なデータ モデル (たとえば、各靴とサイズの組み合わせを個別のドキュメントにすることができます) を使用し、マップ関数を使用して特定の SKU のデータを集計する方がよいようです。

于 2013-07-25T10:00:09.040 に答える