2013-07-25 41 views
7

當談到CouchDB時,我是一個新手。我來自.NET SQL Server世界。CouchDB:鏈接引用不同文檔類型數組的文檔

在通過CouchDB瀏覽權威指南時,我喜歡「wut wut this awesome」。現在我正在測試一些我學到的東西,希望在現實世界中實現它。

幾周前我剛剛註冊了一個Cloudant帳戶,並開始使用它進行一些測試/學習。

在混淆鏈接文件時,背後的整個理論看起來很簡單,也是互聯網上兩岸前沿的例子。我想從包含不同鏈接文檔的文檔中檢索一些信息,這些文檔本身有鏈接文檔的數組。就像加入到多對多關係表的多SQL Server一樣。你會看到下面的代碼。希望它是有道理的。

以SQL查詢爲例。假設每個表中只有一個條目,我們應該獲得一條記錄,其中包含給定SKU的鞋子的所有細節。但是,如果我們有多個鞋號,我們將不得不再編寫一些代碼。

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 

我想CouchDB的由SKU在https://username.cloudant.com/test/_design/catalogue/_view/item-details?include_docs=true&key=%22656F-PINSEC12%22

{ 
    "_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" 
        ] 
       } 
      ] 
     } 
    ] 
} 

鑑於下列文件和地圖返回以下JSON /減少:

//--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}); 
         } 
         } 
        } 
        } 
       }" 
     } 
    } 
} 

有可能是一個更好的方式實現這一點,但我想看看是否有可能有一個鏈接文檔的數組也有一系列鏈接文檔的文檔。但是我的地圖/縮小並沒有返回任何東西。所有返回是:

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

]} 

我猜有人不會存儲在一個單一文件的所有信息,因爲,說我們添加一個新的展示大小或標記的鞋碼爲不可用,這將意味着一個必須將所有先前的值傳回CouchDB才更新一個字段。

希望我的問題是有道理的Oo__oO

+0

「wut wut this awesome」<3 – garbados

回答

5

與此招是從連接中的思維脫身。鏈接文檔爲您提供了一種基於另一種文檔的屬性來索引一種文檔的技術。這個工程使用的兩個特徵的組合:

  1. 的CouchDB允許你指定include_docs =真正的查詢視圖視圖結果一起返回索引的文檔時。
  2. 您可以通過在視圖結果中指定_id屬性來告訴CouchDB返回ANY文檔。請注意,每個結果只能返回一個文檔。

舉個例子,假設你有文件

{ 
    "_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"] 
} 

,那麼你可以使用地圖功能的SKU標誌圖像:

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

這是認識到地圖功能僅對原始d進行操作也很重要保存的禮物。

我想在你的例子中,「目錄項目」和「鞋子顏色」文件是多餘的。您可以定義一個地圖功能,以便通過SKU索引「鞋子圖像」和「鞋子尺寸」文檔。

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

假設這被分配到視圖 「項目明細」,您的查詢:

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 
       } 
      ] 

     }  
    ] 
} 

如果你想將這些成果轉化爲聯合收割機單個JSON文檔,你可以看看使用list function來生成自定義的JSON輸出。但是,我不確定這會帶來多大收益。

看起來通常使用更精細的數據模型(例如,每個鞋/尺寸組合可以是單獨的文檔)更好,並使用映射函數來聚合給定SKU的數據。

+0

非常感謝您提供非常有益的答案。幫了很多忙。 – tim