Esegui query sul database di stato
Questo argomento contiene informazioni per aiutarti a capire come eseguire query sul database di stato in cui sono memorizzati i dati di stato correnti del libro contabile blockchain.
Cos'è il database di stato?
I dati di stato correnti del libro mastro blockchain sono memorizzati nel database di stato.
Quando sviluppi i codici concatenati di Oracle Blockchain Platform, puoi estrarre i dati dal database di stato eseguendo query complesse. Oracle Blockchain Platform supporta query avanzate utilizzando la sintassi SQL Rich Query e le espressioni di ricerca CouchDB. Vedere Sintassi SQL Rich Query e CouchDB Rich Query Syntax.
Hyperledger Fabric non supporta le query SQL Rich. Se la rete Oracle Blockchain Platform contiene partecipanti a Hyperledger Fabric, è necessario eseguire le operazioni riportate di seguito.
-
Se i codici concatenati contengono una sintassi di query avanzata SQL, tali codici concatenati vengono installati solo sui peer membri che utilizzano Oracle Blockchain Platform.
-
Se è necessario installare un codice concatenato nei peer di Oracle Blockchain Platform e Hyperledger Fabric, utilizzare la sintassi CouchDB nei codici concatenati e confermare che i peer di Hyperledger Fabric sono impostati per utilizzare CouchDB come repository del database di stato. Oracle Blockchain Platform può elaborare CouchDB.
Come funziona Oracle Blockchain Platform con Berkeley DB?
Oracle Blockchain Platform utilizza Oracle Berkeley DB come database di stato. Oracle Blockchain Platform crea tabelle relazionali nel database Berkeley in base all'estensione SQLite. Questa architettura offre un modo efficace e performante per convalidare query avanzate SQL.
Per ogni codice concatenato di canale, Oracle Blockchain Platform crea una tabella DB Berkeley. Questa tabella memorizza i dati delle informazioni sullo stato e contiene almeno una colonna chiave denominata key e una colonna di valori denominata value o valueJson, a seconda che si stiano utilizzando i dati del formato JSON.
| Nome della colonna | Type | Descrizione |
|---|---|---|
key |
TEXT | Colonna chiave della tabella dello stato. |
value |
TEXT | Colonna valore della tabella stato. |
valueJson |
TEXT | Colonna dei valori del formato JSON della tabella di stato. |
Si noti che le colonne valueJson e value si escludono a vicenda. Pertanto, se il codice concatenato assegna un valore JSON a una chiave, la colonna valueJson conterrà tale valore e la colonna del valore verrà impostata su null. Se il codice concatenato assegna un valore non JSON a una chiave, la colonna valueJson verrà impostata su null e la colonna del valore conterrà il valore.
Esempio di database di stato
Di seguito sono riportati alcuni esempi di chiavi e relativi valori del database di stato dell'esempio Car Dealer.
| chiave | value | valueJson |
|---|---|---|
| abg1234 | nullo | {"docType": "vehiclePart", "serialNumber": "abg1234", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "airbag 2020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979} |
| abg1235 | nullo | {"docType": "vehiclePart", "serialNumber": "abg1235", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "airbag 4050", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979} |
| ser1236 | nullo | {"docType": "vehiclePart", "serialNumber": "ser1236", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "seatbelt 10020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979} |
| bra1238 | nullo | {"docType": "vehiclePart", "serialNumber": "bra1238", "assembler": "bobs-bits", "assemblyDate": 1502688979, "nome": "pastiglia freno 4200", "proprietario": "Detroit Auto", "richiamo": falso, "recallDate": 1502688979} |
| dtrt10001 | nullo | {"docType": "veicolo", "chassisNumber": "dtrt10001", "fabbricante": "Detroit Auto", "modello": "una coupé", "assemblyDate": 1502688979, "airbagSerialNumber": "abg1235", "proprietario": "Sam Dealer", "richiamo": falso, "recallDate": 1502688979 |
Rich query nella console
Gli amministratori possono eseguire e analizzare query avanzate dalla console.
Sintassi rich query supportata
Oracle Blockchain Platform supporta due tipi di sintassi rich query che è possibile utilizzare per eseguire query sul database di stato: SQL rich query e rich query CouchDB.
Sintassi query SQL Rich
Le estensioni JSON di Berkeley DB sono sotto forma di funzioni SQL.
Operazioni preliminari
Tenere presenti le informazioni riportate di seguito.
- È possibile accedere solo al codice concatenato canale (<STATE>) da cui si sta eseguendo la query.
- È supportata solo l'istruzione SELECT.
- Impossibile modificare la tabella del database di stato.
- Un'espressione di query RTF può avere una sola istruzione SELECT.
- Gli esempi in questo argomento sono solo alcuni modi in cui è possibile scrivere la query RTF. Si dispone dell'accesso alla sintassi SQL completa per eseguire query su un database SQL.
- Hai accesso all'estensione JSON1 (estensione SQLite). Vedere JSON1 Extension e SQL As Understand by SQLite.
Per ulteriori informazioni sulla scrittura e il test dei codici concatenati, vedere Sviluppa codici concatenati.
Come fare riferimento al database di stato nelle query
Il nome della tabella del database di stato è gestito internamente da Oracle Blockchain Platform, pertanto non è necessario conoscere il nome fisico del database di stato quando si scrive un codice concatenato.
Utilizzare, invece, l'alias <STATE> per fare riferimento al nome della tabella. Ad esempio: select key, value from <STATE>.
Si noti che l'alias <STATE> non fa distinzione tra maiuscole e minuscole, pertanto è possibile utilizzare <state>, <STATE> o <StAtE>.
Recupera tutte le chiavi
Utilizzare questa sintassi:
SELECT key FROM <STATE>Ad esempio, se si utilizza questa sintassi per eseguire una query sull'esempio Concessionario auto, verrà visualizzato il seguente elenco di chiavi:
chiave
abg1234
abg1235
ser1236
bra1238
dtrt10001
Recupera tutte le chiavi e tutti i valori ordinati in ordine alfabetico per chiave
Utilizzare questa sintassi:
SELECT key AS serialNumber, valueJson AS details FROM <state> ORDER BY keyAd esempio, se si utilizza questa sintassi per eseguire una query sull'esempio Rivenditore auto, si otterranno i seguenti risultati:
| serialNumber | details |
|---|---|
| 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, "nome": "pastiglia freno 4200", "proprietario": "Detroit Auto", "richiamo": falso, "recallDate": 1502688979} |
| dtrt10001 | {"docType": "veicolo", "chassisNumber": "dtrt10001", "fabbricante": "Detroit Auto", "modello": "una coupé", "assemblyDate": 1502688979, "airbagSerialNumber": "abg1235", "proprietario": "Sam Dealer", "richiamo": falso, "recallDate": 1502688979 |
| ser1236 | {"docType": "vehiclePart", "serialNumber": "ser1236", "assembler": "panama-parts", "assemblyDate": 1502688979, "name": "seatbelt 10020", "owner": "Detroit Auto", "recall": false, "recallDate": 1502688979} |
Recupera tutte le chiavi e i valori a partire da "abg"
Utilizzare questa sintassi:
SELECT key AS serialNumber, valueJson AS details FROM <state> WHERE key LIKE 'abg%'SELECT key, value FROM <STATE>Ad esempio, se si utilizza questa sintassi per eseguire una query sull'esempio Rivenditore auto, si otterranno i seguenti risultati:
| serialNumber | details |
|---|---|
| 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"} |
Recupera tutte le chiavi con valori che contengono una parte del veicolo di proprietà di "Detroit Auto"
Utilizzare questa sintassi:
SELECT key FROM <state> WHERE json_extract(valueJson, '$.docType') = 'vehiclePart' AND json_extract(valueJson, '$.owner') = 'Detroit Auto'
Ad esempio, se si utilizza questa sintassi per eseguire una query sull'esempio Concessionario auto, verrà visualizzato il seguente elenco di chiavi:
chiave
abg1234
abg1235
ser1236
bra1238
Recupera modello e produttore per tutte le auto possedute da "Sam Dealer"
Utilizzare questa sintassi:
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'
Ad esempio, se si utilizza questa sintassi per eseguire una query sull'esempio Rivenditore auto, si otterranno i seguenti risultati:
| modello | produttore |
|---|---|
| un coupé | Detroit Auto |
Se il valore di stato è un array JSON, è possibile utilizzare questa sintassi per recuperare il modello e il produttore per tutte le auto di proprietà di "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'
Sintassi rich query CouchDB
Utilizzare le informazioni riportate in questo argomento se si sta eseguendo la migrazione dei codici concatenati contenenti la sintassi CouchDB in Oracle Blockchain Platform o se è necessario scrivere codici concatenati da installare sui peer di Hyperledger Fabric che partecipano a una rete Oracle Blockchain Platform.
Se stai scrivendo un nuovo codice concatenato, Oracle consiglia di utilizzare query SQL rich per sfruttare i vantaggi delle prestazioni offerti da Oracle Blockchain Platform con Berkeley DB.
Per ulteriori informazioni sulla scrittura e il test dei codici concatenati, vedere Sviluppa codici concatenati.
Parametri query e sintassi selettore non supportati
Oracle Blockchain Platform non supporta il parametro use_index. Se utilizzato, Oracle Blockchain Platform ignora questo parametro e selezionerà automaticamente gli indici definiti nel file StateDB in questione.
| Parametro | Type | Descrizione |
|---|---|---|
| use_index | json | Indica a una query di utilizzare un indice specifico. |
Recupera tutti i modelli, i produttori e i proprietari di auto e li ordina per proprietario
Usare l'espressione seguente:
{
"fields": ["model", "manufacturer", "owner"],
"sort": [
"owner"
]
}Recupera modello e produttore per tutte le auto possedute da "Sam Dealer"
Usare l'espressione seguente:
{
"fields": ["model", "manufacturer"],
"selector": {
"docType" : "vehicle",
"owner" : "Sam Dealer"
}
}Indici database di stato
Il database di stato può contenere una grande quantità di dati. In questi casi Oracle Blockchain Platform utilizza gli indici per migliorare l'accesso ai dati.
Indici predefiniti
Quando viene distribuito un codice concatenato, Oracle Blockchain Platform crea due indici.
-
Indice chiave: creato nella colonna chiave.
-
Indice dei valori: creato nella colonna dei valori.
Indici personalizzati
In alcuni casi potrebbe essere necessario creare indici personalizzati. Per definire questi indici, utilizzare qualsiasi espressione risolvibile nel contesto della tabella di stato. Gli indici personalizzati creati rispetto a Berkeley DB si basano sulla sintassi SQLite, ma seguono comunque la stessa implementazione CouchDB fornita da Hyperledger Fabric.
È possibile utilizzare indici personalizzati per migliorare notevolmente le prestazioni delle istruzioni WHERE e ORDER BY in set di dati di grandi dimensioni. Poiché l'utilizzo di indici personalizzati rallenta l'inserimento dei dati, utilizzarli con cautela.
Ogni indice personalizzato è definito come un array di espressioni, che supportano indici composti, espressi come documento JSON all'interno di un file. Esiste un indice per file. È necessario raggruppare questo file con il codice concatenato in una cartella denominata indexes nella struttura di directory seguente: statedb/relationaldb/indexes. Per ulteriori informazioni, vedere Come aggiungere gli indici CouchDB durante l'installazione del codice concatenato.
Indici personalizzati di esempio
Gli esempi di indici personalizzati in questa sezione utilizzano l'esempio Rivenditore auto.
Esempio 1: questo esempio indicizza l'uso dell'espressione json_extract nel contesto delle espressioni WHERE e ORDER BY.
{"indexExpressions": ["json_extract(valueJson, '$.owner')"]}
Ad esempio:
SELECT … FROM … ORDER BY json_extract(valueJson, '$.owner')
Esempio 2: questo esempio indicizza l'uso composto delle due espressioni json_extract nel contesto delle espressioni WHERE e ORDER BY.
{"indexExpressions": ["json_extract(valueJson, '$.docType')", "json_extract(valueJson, '$.owner')"]}
Ad esempio:
SELECT … FROM … WHERE json_extract(valueJson, '$.docType') = 'vehiclePart' AND json_extract(valueJson, '$.owner') = 'Detroit Auto'
Esempio 3: in questo esempio viene creato sia l'indice descritto nell'esempio 1 che l'indice descritto nell'esempio 2. Ogni struttura JSON deve essere inclusa in un file separato. Ogni file descrive un singolo indice: un indice semplice come l'esempio 1 o un indice composto come l'esempio 2.
Indice 1: {"indexExpressions": ["json_extract(valueJson, '$.owner')"]}
Indice 2: {"indexExpressions": ["json_extract(valueJson, '$owner')", "json_extract(valueJson, '$.docType')"]}
Nell'esempio seguente, Index 2 viene applicato all'espressione AND nella parte WHERE della query, mentre Index 1 viene applicato all'espressione ORDER BY:
SELECT … FROM … WHERE json_extract(valueJson, '$.docType') = 'vehiclePart' AND json_extract(valueJson, '$.owner') = 'Detroit Auto' ORDER BY json_extract(valueJson, '$.owner')
Formato documento JSON
Il documento JSON deve essere nel seguente formato:
{"indexExpressions": [expr1, ..., exprN]}
Ad esempio:
{"indexExpressions": ["json_extract(valueJson, '$.owner')"]}
Differenze nella convalida delle query complesse
In alcuni casi, la query avanzata Hyperledger Fabric standard con CouchDB e la query avanzata Oracle Berkeley DB funzionano in modo diverso.
In Hyperledger Fabric standard con CouchDB, ogni coppia di chiavi e valori restituita dalla query viene aggiunta al set di lettura della transazione ed è convalidata al momento della convalida e senza rieseguire la query. In Berkeley DB, la coppia di chiave e valore restituita non viene aggiunta al set di lettura, ma il risultato della query RTF viene sottoposto a hash in un albero Merkle e convalidato in base alla riesecuzione della query al momento della convalida.
Hyperledger Fabric nativo non fornisce la protezione dei dati per query avanzate. Tuttavia, Berkeley DB contiene funzionalità che proteggono e convalidano la query RTF aggiungendo il valore hash dell'albero Merkle nel set di lettura, rieseguendo la query RTF e nella fase di convalida ricalcolando il valore dell'albero Merkle. Si noti che, poiché la convalida è più accurata in Oracle Blockchain Platform con Berkeley DB, a volte i richiami dei codici concatenati vengono contrassegnati per letture fantasma più frequenti.