查詢狀態資料庫
本主題包含的資訊可協助您瞭解如何查詢儲存區塊鏈分類帳目前狀態資料的狀態資料庫。
什麼是狀態資料庫?
區塊鏈分類帳目前的狀態資料儲存在狀態資料庫中。
當您開發 Oracle Blockchain Platform 鏈碼時,可以執行豐富的查詢,從狀態資料庫擷取資料。Oracle Blockchain Platform 使用 SQL Rich Query 語法和 CouchDB find 表示式支援豐富的查詢。請參閱 SQL Rich Query Syntax 和 CouchDB Rich Query Syntax 。
Hyperledger Fabric 不支援 SQL Rich Query。如果您的 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 資料庫?
Oracle Blockchain Platform 使用 Oracle Berkeley DB 作為狀態資料庫。Oracle Blockchain Platform 會根據 SQLite 擴充功能,在 Berkeley 資料庫中建立關聯式表格。此架構提供健全且高效能的方式來驗證 SQL Rich Query。
對於每個通路鏈碼,Oracle Blockchain Platform 會建立一個 Berkeley DB 表格。此表格會儲存狀態資訊資料,並包含至少一個名為 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",「製造商」:"Detroit Auto","model":"a coupe","assemblyDate":1502688979,"airbagSerialNumber":"abg1235","owner":"Sam Dealer","recall":false,"recallDate":1502688979 |
支援的 Rich Query 語法
Oracle Blockchain Platform 支援兩種豐富的查詢語法,可用來查詢狀態資料庫:SQL Rich query 和 CouchDB Rich Query。
SQL Rich Query 語法
Berkeley DB JSON 擴充是以 SQL 函數的形式提供。
Before You Begin - 開始之前
請注意下列資訊:
- 您只能存取執行查詢的通道鏈碼 (<STATE>)。
- 只支援 SELECT 敘述句。
- 您無法修改狀態資料庫表格。
- Rich Query 表示式只能有一個 SELECT 敘述句。
- 本主題中的範例只是一些您可以撰寫 Rich Query 的方式。您可以存取一般的完整 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",「製造商」:"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 Dealer」擁有之所有汽車的型號和製造商
使用此語法:
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 Dealer」擁有之所有汽車的型號和製造商:
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 RTF 查詢語法
如果您要將包含 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 Dealer」擁有之所有汽車的型號和製造商
使用此表示式:
{
"fields": ["model", "manufacturer"],
"selector": {
"docType" : "vehicle",
"owner" : "Sam Dealer"
}
}
狀態資料庫索引
狀態資料庫可包含大量資料。在這種情況下,Oracle Blockchain Platform 使用索引來改善資料存取。
預設索引
部署鏈碼時,Oracle Blockchain Platform 會建立兩個索引。
-
索引鍵索引 — 建立於索引鍵資料欄。
-
值索引 — 在值欄上建立。
自訂索引
在某些情況下,您可能需要建立自訂索引。您可以使用任何可在狀態表格相關資訊環境中解析的表示式來定義這些索引。針對 Berkeley 資料庫建立的自訂索引使用 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')"]}
豐富查詢驗證的差異
在某些情況下,標準 Hyperledger Fabric 搭配 CouchDB 豐富查詢,以及 Oracle Berkeley DB 豐富查詢的行為會有所不同。
在標準 Hyperledger Fabric 中搭配 CouchDB,查詢傳回的每個索引鍵和值組都會新增至交易的讀取集,並在驗證時驗證,而且不會重新執行查詢。在 Berkeley DB 中,傳回的索引鍵與值組不會新增至讀取集,但 Rich Query 的結果會在 Merkle 樹狀結構中雜湊,並在驗證時依據重新執行查詢進行驗證。
原生 Hyperledger Fabric 不提供豐富查詢的資料保護。不過,Berkeley DB 包含的功能可藉由將 Merkle 樹狀結構雜湊值加入讀取集、重新執行 Rich 查詢,以及在驗證階段重新計算 Merkle 樹狀結構值,來保護和驗證 Rich Query。請注意,由於使用 Berkeley DB 的 Oracle Blockchain Platform 驗證更準確,因此有時會標記鏈碼呼叫以進行更頻繁的虛擬在製品讀取。