查詢狀態資料庫
本主題包含的資訊可協助您瞭解如何查詢儲存區塊鏈分類帳目前狀態資料的狀態資料庫。
狀態資料庫是什麼?
區塊鏈分類帳目前的狀態資料儲存在狀態資料庫中。
當您開發 Oracle Blockchain Platform 鏈碼時,可以執行 Rich Query,從狀態資料庫擷取資料。Oracle Blockchain Platform 使用 SQL Rich Query 語法和 CouchDB 尋找表示式,支援豐富的查詢。請參閱 SQL Rich Query Syntax 和 CouchDB Rich Query Syntax 。
Hyperledger Fabric 不支援 SQL 豐富查詢。如果您的 Oracle Blockchain Platform 網路包含 Hyperledger Fabric 參與者,則必須確定執行下列作業:
-
如果您的鏈碼包含 SQL Rich Query 語法,則那些鏈碼只會安裝在使用 Oracle Blockchain Platform 的成員對等體上。
-
如果需要在 Oracle Blockchain Platform 和 Hyperledger Fabric 對等上安裝鏈碼,請在鏈碼中使用 CouchDB 語法,並確認 Hyperledger Fabric 對等體已設定為使用 CouchDB 作為其狀態資料庫儲存庫。Oracle Blockchain Platform 可以處理 CouchDB。
Oracle Blockchain Platform 如何與 Berkeley DB 搭配運作?
Oracle Blockchain Platform 使用 Oracle Berkeley DB 作為狀態資料庫。Oracle Blockchain Platform 會根據 SQLite 擴充功能,在 Berkeley 資料庫中建立關聯式表格。此架構提供完善且高效能的方式來驗證 SQL 豐富查詢。
Oracle Blockchain Platform 會為每個通路鏈碼建立 Berkeley 資料庫表格。此表格儲存狀態資訊資料,並至少包含一個名為 key
的索引鍵資料欄,以及一個名為 value
或 valueJson
的值資料欄 (視您是否使用 JSON 格式資料而定)。
資料欄名稱 | Type | 描述 |
---|---|---|
key |
TEXT | 狀態表格的索引鍵資料欄。 |
value |
TEXT | 狀態表格的值資料欄。 |
valueJson |
TEXT | 狀態表格的 JSON 格式值資料欄。 |
請注意,valueJson
和 value
資料欄是互斥的。因此,如果鏈碼將 JSON 值指派給索引鍵,則 valueJson
資料欄將會保留該值,而值資料欄將會設為空值。如果鏈碼將非 JSON 值指派給索引鍵,則 valueJson
資料欄將設為空值,而值資料欄將保留值。
狀態資料庫範例
以下是「汽車經銷商」範例狀態資料庫中的關鍵碼及其值範例:
索引鍵 | value | valueJson |
---|---|---|
abg1234 | 空值 | {"docType": "vehiclePart", "serialNumber": "abg1234", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "airbag 2020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979} |
abg1235 | 空值 | {"docType": "vehiclePart", "serialNumber": "abg1235", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "airbag 4050", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979} |
ser1236 | 空值 | {"docType": "vehiclePart", "serialNumber": "ser1236", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "seatbelt 10020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979} |
bra1238 | 空值 | {"docType": "vehiclePart", "serialNumber": "bra1238", "assembler": "bobs-bits", "assemblyDate": 1502688979, "name": "brakepad 4200", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979} |
dtrt10001 | 空值 | {"docType": "vehicle", "chassisNumber": "dtrt10001", "manufacturer": "Detroit Auto", "model": "a coupe", "assemblyDate": 1502688979, "airbagSerialNumber": "abg1235", "owner": "Sam Dealer", "recall": false, "recallDate": 1502688979 |
支援的 RTF 查詢語法
Oracle Blockchain Platform 支援兩種類型的豐富查詢語法,可用來查詢狀態資料庫:SQL Rich Query 和 CouchDB Rich Query。
SQL RTF 查詢語法
Berkeley DB JSON 擴充為 SQL 函數的形式。
Before You Begin - 開始之前
請注意下列資訊:
- 您只能存取執行查詢的來源通道鏈碼 (<STATE>)。
- 只支援 SELECT 敘述句。
- 您無法修改狀態資料庫表格。
- Rich Query 表示式只能有一個 SELECT 敘述句。
- 本主題中的範例只是一些您可以撰寫豐富查詢的方式。您可以存取一般完整 SQL 語法來查詢 SQL 資料庫。
- 您可以存取 JSON1 副檔名 (SQLite 副檔名)。請參閱 JSON1 Extension 和 SQL As Understood by SQLite 。
如果您需要有關撰寫與測試鏈碼的詳細資訊,請參閱開發鏈碼。
如何參照查詢中的狀態資料庫
狀態資料庫表格名稱是由 Oracle Blockchain Platform 內部管理,因此在撰寫鏈碼時,您不需要知道狀態資料庫的實體名稱。
您必須改用 <STATE>
別名來參照表格名稱。例如:select key, value from <STATE>
。
請注意,<STATE>
別名不區分大小寫,因此您可以使用 <state>
、<STATE>
或 <StAtE>
等項目。
擷取所有索引鍵
使用此語法:
SELECT key FROM <STATE>
例如,如果您使用此語法來查詢「汽車經銷商」範例,則會得到下列索引鍵清單:
金鑰
abg1234
abg1235
ser1236
bra1238
dtrt10001
依索引鍵依字母順序擷取所有索引鍵與值
使用此語法:
SELECT key AS serialNumber, valueJson AS details FROM <state> ORDER BY key
例如,如果您使用此語法來查詢「汽車經銷商」範例,則會得到下列結果:
serialNumber | 詳細資訊 |
---|---|
abg1234 | {"docType": "vehiclePart", "serialNumber": "abg1234", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "airbag 2020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979} |
abg1235 | {"docType": "vehiclePart", "serialNumber": "abg1235", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "airbag 4050", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979} |
bra1238 | {"docType": "vehiclePart", "serialNumber": "bra1238", "assembler": "bobs-bits", "assemblyDate": 1502688979, "name": "brakepad 4200", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979} |
dtrt10001 | {"docType": "vehicle", "chassisNumber": "dtrt10001", "manufacturer": "Detroit Auto", "model": "a coupe", "assemblyDate": 1502688979, "airbagSerialNumber": "abg1235", "owner": "Sam Dealer", "recall": false, "recallDate": 1502688979 |
ser1236 | {"docType": "vehiclePart", "serialNumber": "ser1236", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "seatbelt 10020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979} |
擷取以 "abg" 開頭的所有索引鍵和值
使用此語法:
SELECT key AS serialNumber, valueJson AS details FROM <state> WHERE key LIKE 'abg%'SELECT key, value FROM <STATE>
例如,如果您使用此語法來查詢「汽車經銷商」範例,則會得到下列結果:
serialNumber | 詳細資訊 |
---|---|
abg1234 | {"docType": "vehiclePart", "serialNumber": "abg1234", "assembler": "panama-parts", "assemblyDate": "1502688979", "name": "airbag 2020", "owner": "Detroit Auto", "recall": "false", "recallDate": "1502688979"} |
abg1235 | {"docType": "vehiclePart", "serialNumber": "abg1235", "assembler": "panama-parts", "assemblyDate": "1502688979", "name": "airbag 4050", "owner": "Detroit Auto", "recall": "false", "recallDate": "1502688979"} |
擷取包含「Detroit Auto」所擁有之車輛零件值的所有索引鍵
使用此語法:
SELECT key FROM <state> WHERE json_extract(valueJson, '$.docType') = 'vehiclePart' AND json_extract(valueJson, '$.owner') = 'Detroit Auto'
例如,如果您使用此語法來查詢「汽車經銷商」範例,則會得到下列索引鍵清單:
金鑰
abg1234
abg1235
ser1236
bra1238
擷取「Sam 經銷商」所有汽車的型號與製造商
使用此語法:
SELECT json_extract(valueJson, '$.model') AS model, json_extract(valueJson, '$.manufacturer') AS manufacturer FROM <state> WHERE json_extract(valueJson, '$.docType') = 'vehicle' AND json_extract(valueJson, '$.owner') = 'Sam Dealer'
例如,如果您使用此語法來查詢「汽車經銷商」範例,則會得到下列結果:
模型 | 製造商 |
---|---|
優惠券 | 自動偵測 |
如果州值為 JSON 陣列,您可以使用此語法來擷取「Sam 經銷商」所有汽車的型號和製造商:
SELECT json_extract(j.value, '$.model') AS model, json_extract(j.value, '$.manufacturer') AS manufacturer FROM <state> s, json_each(json_extract(s.valueJson,'$')) j WHERE json_valid(j.value) AND json_extract(j.value, '$.owner') = 'Sam Dealer'
CouchDB Rich Query 語法
如果您將包含 CouchDB 語法的鏈碼移轉至 Oracle Blockchain Platform ,或需要撰寫鏈碼以安裝在參與 Oracle Blockchain Platform 網路的 Hyperledger Fabric 對等體上,請使用本主題中的資訊。
如果您正在撰寫新的鏈碼,Oracle 建議您使用 SQL Rich Query,以利用 Oracle Blockchain Platform 與 Berkeley DB 提供的效能優點。
如果您需要有關撰寫與測試鏈碼的詳細資訊,請參閱開發鏈碼。
不支援的查詢參數和選取器語法
Oracle Blockchain Platform 不支援 use_index
參數。如果使用,Oracle Blockchain Platform 會忽略此參數,而且會自動選取在有問題的 StateDB 上定義的索引。
Parameter - 參數 | Type | 描述 |
---|---|---|
use_index | json | 指示查詢使用特定索引。 |
依擁有者擷取汽車的所有模型、製造商及業主,以及訂單
使用此表示式:
{
"fields": ["model", "manufacturer", "owner"],
"sort": [
"owner"
]
}
擷取「Sam 經銷商」所有汽車的型號與製造商
使用此表示式:
{
"fields": ["model", "manufacturer"],
"selector": {
"docType" : "vehicle",
"owner" : "Sam Dealer"
}
}
狀態資料庫索引
狀態資料庫可包含大量資料。在這種情況下,Oracle Blockchain Platform 會使用索引來改善資料存取。
預設索引
部署鏈碼後,Oracle Blockchain Platform 會建立兩個索引。
-
索引鍵索引 - 在索引鍵資料欄上建立。
-
值索引 - 在值資料欄上建立。
自訂索引
在某些情況下,您可能需要建立自訂索引。您可以使用可以在狀態表格的相關資訊環境中解析的任何表示式來定義這些索引。針對 Berkeley DB 建立的自訂索引使用 SQLite 語法,否則會遵循 Hyperledger Fabric 提供的相同 CouchDB 實行。
請注意,您可以使用自訂索引,大幅改善大型資料集上 WHERE 和 ORDER BY 敘述句的效能。因為使用自訂索引會減緩資料插入的速度,所以您應該謹慎地使用它們。
每個自訂索引都會定義為支援複合索引的表示式陣列,以一個檔案內的 JSON 文件表示 (請注意,每個檔案都有一個索引)。您必須在下列目錄結構中,以 "indexes" 資料夾中的鏈碼封裝此檔案:statedb/relationaldb/indexes
。請參閱如何在鏈碼安裝期間新增 CouchDB 索引。
自訂索引範例
本節中的自訂索引範例使用「汽車經銷商」範例。
範例 1 - 此範例會編製 WHERE 和 ORDER BY 表示式相關資訊環境中使用 json_extract
表示式的索引。
{"indexExpressions": ["json_extract(valueJson, '$.owner')"]}
舉例而言:
SELECT … FROM … ORDER BY json_extract(valueJson, '$.owner')
範例 2 - 此範例會編製 WHERE 和 ORDER BY 表示式相關資訊環境中兩個 json_extract
表示式的複合使用索引。
{"indexExpressions": ["json_extract(valueJson, '$.docType')", "json_extract(valueJson, '$.owner')"]}
舉例而言:
SELECT … FROM … WHERE json_extract(valueJson, '$.docType') = 'vehiclePart' AND json_extract(valueJson, '$.owner') = 'Detroit Auto'
範例 3 - 此範例會建立兩個索引:範例 1 中說明的索引,以及範例 2 中說明的索引。請注意,每個 JSON 結構都必須包含在個別檔案中。每個檔案都描述單一索引:一個簡單的索引 (例如「範例 1」),或是一個複合索引 (例如「範例 2」)。
索引 1:{"indexExpressions": ["json_extract(valueJson, '$.owner')"]}
索引 2:{"indexExpressions": ["json_extract(valueJson, '$owner')", "json_extract(valueJson, '$.docType')"]}
在下列範例中,「索引 2」會套用至查詢之 WHERE
部分的 AND
表示式,而「索引 1」會套用至 ORDER BY
表示式:
SELECT … FROM … WHERE json_extract(valueJson, '$.docType') = 'vehiclePart' AND json_extract(valueJson, '$.owner') = 'Detroit Auto' ORDER BY json_extract(valueJson, '$.owner')
JSON 文件格式
JSON 文件的格式必須如下:
{"indexExpressions": [expr1, ..., exprN]}
舉例而言:
{"indexExpressions": ["json_extract(valueJson, '$.owner')"]}
驗證 RTF 查詢的差異
在某些情況下,具有 CouchDB 豐富查詢的標準 Hyperledger Fabric 和 Oracle Berkeley DB 豐富查詢的運作方式會有所不同。
在搭配 CouchDB 的標準 Hyperledger Fabric 中,查詢傳回的每個索引鍵與值組都會新增至交易的讀取集,並在驗證時驗證,且不會重新執行查詢。在 Berkeley DB 中,傳回的索引鍵與值組不會新增至讀取集,但會在 Merkle 樹狀結構中雜湊豐富的查詢結果,並在驗證時根據重新執行查詢進行驗證。
原生 Hyperledger Fabric 不提供豐富查詢的資料保護。不過,Berkeley DB 包含透過將 Merkle 樹狀結構雜湊值新增至讀取集、重新執行 Rich Query,以及在驗證階段重新計算 Merkle 樹狀結構值來保護和驗證 Rich Query 的功能。請注意,由於 Berkeley DB 在 Oracle Blockchain Platform 中驗證更加精確,因此有時會標示鏈碼呼叫以進行更頻繁的虛擬讀取。