Zend_Cloud_DocumentService 爲所有主要的文檔數據庫抽象了接口——不管是在雲計算還是在本地部署——所以開發者通過一個 API 就可以訪問它們的通常功能。換句話來說,一個應用程序可以使用這些數據庫和服務,而不必關心這些應用程序是如何被部署的。在部署的時候,可以通過修改配置來選擇數據源。
文檔數據庫和服務在應用程序的開發階段變得越來越普遍。這些數據源不同於傳統的關係數據源,它們爲了性能、可擴展性以及靈活性,儘量避免複雜的關係。文檔基礎的服務例子有 Amazon SimpleDB 和 Azure Table Storage。
Simple Cloud API 爲提供商指特性提供了一些靈活的機制,通過在每一個方法簽名中使用一個 $options 數組。一些適配器要求特定的選項也必須被加入到 $options 數組中。從一個配置文件中檢索這些選項從而維護所有服務和數據庫的兼容性,這是一個很好的實踐;不被識別的選項被會簡單的被忽略,這使得根據不同環境使用不同的服務變爲可能。
如果更多的提供商需求被要求,開發者應該繼承特定的 Zend_Cloud_DocumentService 適配器,來爲這些特性增加支持。在這種方式中,可以在 Simple Cloud 適配器的子類中,通過對 Simple Cloud API 擴展的引用,從而調用提供商指定的特性。
Zend_Cloud_DocumentService_Adapter 接口
Zend_Cloud_DocumentService_Adapter 接口定義了每個具體的文檔服務適配器需要應用的方法。以下是 Simple Cloud API 的內置適配器:
- Zend_Cloud_DocumentService_Adapter_SimpleDb
- Zend_Cloud_DocumentService_Adapter_WindowsAzure
爲了初始化一個文檔服務適配器,使用 Zend_Cloud_DocumentService_Factory::getAdapter() 這個靜態方法,它可以接受一個配置數組或者一個 Zend_Config 對象。document_adapter 鍵應該指定具體的適配器類,通過類名。適配器特定的鍵同時也可以配置參數傳遞。
例一 使用 SimpleDB 適配器
支持的適配器選項
選項鍵 | 描述 | 用於 | 是否必須 | 默認值 |
---|---|---|---|---|
document_class |
用來表示返回文檔的類。這個類必須繼承 Zend_Cloud_DocumentService_Document 從而確保兼容所有的文檔服務。對於返回一個文檔或者文檔集合的所有方法,將會使用到這個類。 |
構造函數 | 否 | Zend_Cloud_Document_Service_Document |
documentset_class |
用於表示文檔集合的類。默認是 Zend_Cloud_DocumentService_DocumentSet 。 典型的,這個類的對象將會由 listDocuments() 和 query() 返回。任何爲這個配置值提供的類,必須繼承 Zend_Cloud_DocumentService_DocumentSet 。 |
構造函數 | 否 | Zend_Cloud_DocumentService_DocumentSet |
選項鍵 | 描述 | 用於 | 是否必須 | 默認值 |
---|---|---|---|---|
query_class |
用來爲這個文檔服務創建和收集查詢的類 select() 將會創建這個類名的對象, listDocuments() 也可以達到這個效果。 |
構造函數 | 否 | Zend_Cloud_DocumentService_Adapter_SimpleDb_Query |
aws_accesskey | 你的 Amazon AWS 訪問鑰匙 | 構造函數 | 是 | 沒有 |
aws_secretkey | 你的 Amazon AWS 密匙 | 構造函數 | 是 | 沒有 |
http_adapter | 在所有訪問操作中將要使用的 HTTP 適配器 | 構造函數 | 否 | Zend_Http_Client_Adapter_Socket |
merge |
如果是一個 true,則所有的屬性值將會被合併。你也可以 指定一個鍵對數組,這些鍵是將要被合併的屬性的鍵名,同時值指示是否需要合併;一個 true 將會合並給定的鍵。在這個數組中任何沒有被指定的屬性將會被替換。 |
updateDocument() | 否 | True |
return_documents |
如果是一個 true, query() 將返回一個 Zend_Cloud_DocumentService_DocumentSet 對象 這個對象包括 Zend_Cloud_DocumentService_Document 對象(默認情況下);否則它將返回一個數組的數組。 |
query() | 否 | True |
選項鍵 | 描述 | 用於 | 是否必須 | 默認值 |
---|---|---|---|---|
query_class |
用來爲這個文檔服務創建和收信查詢語句的類 select() 將會創建這個類名的對象, listDocuments() 也有相同的作用。 |
構造函數 | 否 | Zend_Cloud_DocumentService_Adapter_WindowsAzure_Query |
default_partition_key |
如果在文檔標誌符(document identifier)沒有指定的時候,將要被使用的默認的分區鍵。 Windows Azure 要求一個雙層文檔 ID,由一個 PartitionKey 和一個 RowKey 組成。PartitionKey 將典型的是一個在你的數據庫或者一個集合中通用的,而 RowKey 的值將會變化。由此,這個設置將允許你來指定所有的文檔將要使用的默認的 PartitionKey。 如果沒有指定,適配器將默認使用集合的名字作爲 PartitionKey |
構造函數, setDefaultPartitionKey() | 否 | 文檔所屬的任何集合的名字 |
storage_accountname | Windows Azure 賬號名 | 構造函數 | 是 | 沒有 |
storage_accountkey | Windows Azure 賬號鑰匙/td> | 構造函數 | 是 | 沒有 |
storage_host |
Windows Azure 訪問主機,默認是 table.core.windows.net |
構造函數 | 否 | table.core.windows.net |
storage_proxy_host | 代理主機名 | 構造函數 | 否 | 沒有 |
storage_proxy_port | 代理端口 | 構造函數 | 否 | 8080 |
storage_proxy_credentials | 代理證書 | 構造函數 | 否 | 沒有 |
HTTP 適配器 | 用於所以訪問操作的 HTTP 適配器 | 構造函數 | 否 | 沒有 |
verify_etag |
確認目標文檔上的 ETag,同時只有當 ETag 和期望值相匹配的時候才執行操作 |
updateDocument() , replaceDocument() , deleteDocument() | 否 | False |
基本概念
每一個基於文檔的服務和數據庫在它們的 API 內使用它們自己的專業術語和結構。SimpleCloud API 把廣大提供商品之間共享的一些普遍概念和操作識別和抽象出來。
文檔儲存由大量的集合(collections)組成,這些集合是與 SQL 數據庫中的數據庫表相類似的邏輯儲存單位。集合包括文檔(documents),文檔事實是一套鍵->值對,同時帶有一些針對儲存引擎的元數據(metadata),文檔由一個獨一無二的 document ID 區分開來。
每一個文檔擁有它自己的結構(字段組合),而無須與其它任何文檔結構相匹配,甚至是同一個集合內的文檔(也無須結構匹配)。事實上,你可以在文檔被創建以後,再修改它的結構。
可以通過 ID 或者查詢一個集合來檢索文檔。
文檔由 Zend_Cloud_DocumentService_Document 類來代表。注意這個文檔類不對提供的 ID 和數據進行驗證,也不強制必須和每一個適配器的要求相兼容。
可以通過把鍵名作爲對象的屬性和作爲數組的元素來對文檔字段進行訪問。
Zend_Cloud_DocumentService_Document 基本接口如下:
注意:Windows Azure 文檔標識符
Windos Azure 技術上要求綁定兩個字段來區別文檔:PartitionKey 和 RowKey,由此,鍵名將被 array(PartitionKey, RowKey) 這種結構完全認證——這使得它們無法移植。在大多數情況下,PartitionKey 對於一個單獨的集合的文檔是不會有變化的——而且極可能在你整個數據庫表中都不會有變化。因此,DocumentService 爲指定鍵提供了幾個選擇:
- 數組鍵總是如預期的發生作用
- 如果提供了一個字符串鍵:
- 如果給構造函數提供一個 default_partition_key 值,或者傳遞到 setDefaultPartitionKey() 方法中,那個值將會被當作 PartitionKey 使用
- 否則,你正在操作的集合名字將會被使用
如果你想使你的應用程序最大程度的可移植,方便的做法是使用字符串鍵。只不過要注意你的記錄將會包括一些額外的字段來表示你不應該把你的數據移植到其它服務的鍵(PartitionKey,RowKey 和之前沒有討論過的時間戳 Timestamp)
例二 創建一個文檔
例三 探訪文檔數據
異常
如果在文檔服務中發生一些錯誤,Zend_Cloud_DocumentService_Exception 被拋出。如果異常是因爲下層的服務驅動引發的,你可以使用 getClientException() 方法來檢索原始異常。
由於不同的雲提供商應用不同的服務,一些驅動並不應用特定的特性。在這種情況下,Zend_Cloud_OperationNotAvailableException 被拋出。
創建一個集合
使用 createCollection() 來創建一個新的集合。
例四 創建集合
如果你調用 createCollection() 的時候,使用一個已經存在的集合名字作爲參數,服務將不會做任何事情,並且不會動現存的集合。
刪除一個集合
通過調用 deleteCollection() 方法來刪除一個集合。
例五 刪除一個集合
刪除一個集合,將會刪除這個集合下的所有文檔。
注意:對於一些服務而言,刪除一個集合需要相當多的時間。在集合和它的文檔沒有被徹底刪除之前,你不能重新創建一個名字相同的集合。
刪除一個不存在的集合將不會有影響。
列出可用的集合
可以用 listCollection() 返回一個現存的集合清單。這個方法返回一個數組,這個數組包括了你在創建這個適配器時指定的賬戶下的所有集合的名字。
例六 列出集合
插入一個文檔
爲了插入一個文檔,你需要提供一個 Zend_Cloud_DocumentService_Document 對象或者相關數據的關聯數組,以及你要插入文檔的集合。
許多提供商要求你爲你的文檔提供一個文檔 ID。如果使用一個 Zend_Cloud_DocumentService_Document,你可以在實例化這個對象的時候,通過傳遞 ID 給構造函數來指定文檔 ID。如果使用一個關聯數組,鍵名將會是適配器特定的位置;例如,在 Azure,ID 是由 PartitionKey 和 RowKey 組成;在Amazon SimpleDB,ID 就是 ItemName;你可以通過在 _id 字段指定鍵名來使得更有可移植性。
由此,最簡單同時也是最具兼容性的做法是通過使用一個 Document 對象來指定鍵。
例七 插入一個文檔
替換一個文檔
替換一個文檔意味着移除與一個特定文檔鍵相關的所有文檔數據,同時用一套新的數據替換它。不同於更新,這個操作不會合並新舊數據,而是把文檔整個替換掉。替換操作,就像 insertDocument(),接受一個 Zend_Cloud_DocumentService_Document 文檔或者一個鍵->值對的數組作爲參數,用來指定新字段的名字和值,同時需要一個文檔所在集合的名字作爲參數。
注意:文檔 ID 是必須的
爲了替換文檔,文檔 ID 是必須的。正如插入一個文檔,如果你使用一個關聯數組來描述文檔,你將需要提供一個提供商相關的鍵,來指示文檔 ID。因此,要在提供商之中替換一個文檔最具兼容性的做法是使用 Document 對象,正如以下所示。
例八 替換一個文檔
你也可以使用一個存在的 Document 對象,重新分配字段或者/和分配新的字段,然後把它傳遞給 replaceDocument() 方法:
更新一個文檔
更新一個文檔,在一個存在的文檔中改變鍵->值對。這個操作不會分享替換操作的語音;沒有指定值的鍵,在數據組中不會被更改。你必須同時提供一個文檔鍵和數據,既可以通過傳遞一個 Zend_Cloud_DocumentService_Document 文檔對象也可以通過傳遞一個數組,給這個方法。如果鍵是空的,同時還提供了一個文檔對象,文檔鍵將被使用。
例九 更新一個文檔
Amazon SimpleDB 支持多值字段,所以數據更新將會和舊的鍵值合併,而不是取代它們。選項合併應該包括一個將要被合併的字段名字的數組。這個數組應該是鍵->值對;鍵對應字段鍵,值是一個布爾值,指示合併的狀態(true 表示要被合併;false 將不合並)。在合併選項中沒有指明的任何鍵將被會替換,而不是合併。
例十 合併文檔字段
刪除一個文檔
通過傳遞鍵給 deleteDocument() 可以刪除一個文檔。刪除一個不存在的文檔沒有影響。
例十一 刪除一個文檔
捕獲一個文檔
你可以通過指定一個文檔的鍵,來捕獲相對應的文檔。fetchDodument() 返回一個 Zend_Cloud_DocumentService_Document 的實例。
例十三 捕獲一個文檔
查詢一個集合
爲了在集合內找到符合標準的文檔,可以使用 query() 方法。這個方法既可以接受一個字符串作爲參數,這個字符串是一個依賴適配器的查詢語句,然後被原樣傳遞給具體的適配器;也可以接受一個 Zend_Cloud_DocumentService_Query 查詢對象實例作爲參數。返回的是一個 Zend_Cloud_DocumentService_DocumentSet,它包括了符合查詢語句條件的 Zend_Cloud_DocumentService_Document 實例。DocumentSet 對象是可反覆和可計算的。
例十三 使用一個字符串查詢語句來查詢一個集合
如果使用一個查詢對象,典型的,你將使用 select() 方法來進行檢索。這將確保查詢對象對於你的適配器是有意義的,這將確保查詢對象集合成你的適配器所能理解的語法。
例十四 使用結構查詢對象來查詢一個集合
Zend_Cloud_DocumentService_Query 類並不限制哪一個查詢從句可以被使用,但從句必須被底層的適配器所支持。現在支持的從句包括以下:
- select() ——定義在結果將要返回的字段
注意: Windows Azure 忽略這個從句的參數,而總是返回全部的文檔
- from() ——定義在查詢中將要使用的集合名字
- where() ——定義查詢的條件。它接受三個參數:條件,用來替換條件中“?”字段的參數數組,以及一個應該是“and”或者是“or”的聯結參數,這個參數用來把當前條件和先前條件結合起來。多個 where() 從句可以被指定
- whereId() ——定義文檔 ID(key)條件。相匹配的文檔必須擁有相同的 key。這個方法接受一個參數——請求的 ID(key)
- limit() ——限制返回文檔的數量
- order() ——按照指定的字段對返回數據進行排序。接受兩個參數——第一個是字段名字,第二個是“asc”或者“desc”用來指定排序方向
注意: 這個從句目前還不被 Windows Azure 支持。
創建一個查詢
爲了方便用戶,select() 方法實例化一個與適配器相關的查詢對象,然後爲它設置成 SELECT 從句。
例十五 創建一個結構查詢
訪問具體的適配器
有時候有必要訪問 Document API 正在運行的服務的適配器。這個可以通過使用 getAdapter() 方法來完成。
注意: 訪問底層的適配器將會破壞在服務之間的可移植性,所以只有在異常環境下才能使用它。
例十六 使用具體的適配器