[NoSQL] Implementare un Document Store NoSQL con Oracle 12c e le SODA API

Avete intenzione di implementare una schemaless application, memorizzando le informazioni in modo “dinamico” e flessibile, secondo il cosiddetto paradigma “NoSQL style document store”?

Anche Oracle DB, a partire dalla versione 12.1.0.2, fornisce il supporto per la memorizzazione, l’indicizzazione e la ricerca di documenti in formato JSON.

Oracle12c

Più dettagliatamente, Oracle DB 12c permette, senza necessità di installare plugin aggiuntivi, l’implementazione di un Document Store e fornisce il seguente set di API, progettate per garantire il supporto allo sviluppo di schemaless application:

  • SODA for Java: interfaccia di programmazione document-store per sviluppatori Java che usano JDBC per comunicare con il database. SODA for Java consiste di un set di semplici classi che rappresentano il database, una collezione di documenti e un documento. I metodi di queste classi forniscono tutte le funzionalità richieste per gestire ed interrogare documenti e collezioni di documenti memorizzati in un database Oracle;
  • SODA for REST: interfaccia REST-based document-store implementata come Java servlet e distribuita come parte dell’Oracle REST Data Services (ORDS) 3.0. Le applicazioni basate su SODA for REST usano il protocollo HTTP per comunicare con la Java Servlet. SODA for REST Servlet può anche essere eseguito su un HTTP Server nativo del database (esistono versioni “bundle” di Web Server, come TomCat e JBoss opportunamente configurati per accedere al DB Oracle tramite API SODA). I metodi HTTP come PUT, POST, GET e DELETE mappano le operazioni eseguite sui documenti JSON. Fornendo API di tipo REST è possibile integrare la soluzione con web application esterne per esporre i dati memorizzati nella base dati Oracle.

Riferimento: http://www.oracle.com/technetwork/database/appdev-with-soda-2606220.pdf

Modello relazionale VS. Modello No-SQL. Volendo comparare un database relazionale con un DB NoSQL “document-store”, è possibile dire che:

  • Una collezione di documenti è una tabella
  • Un documento è una riga di una tabella
  • Un campo del documento è una colonna della tabella

I documenti in formato JSON vengono memorizzati con un ID univoco all’interno di una collezione. Per ciascun documento è possibile recuperare metadati, come data di creazione, dati di aggiornamento, owner e versione del documento, ecc.

Le funzionalità offerte da un document store includono:

  • Creazione e cancellazione di una collezione
  • Creazione, ricerca, aggiornamento o cancellazione di un singolo documento in base al suo ID
  • Recupero dei documenti in una collezione
  • Ricerca di una collezione, tipicamente utilizzando Query By Example (QBE) metaphor
  • Creazione e cancellazione di indici

Dato questo semplice livello di funzionalità fornito da un document store, l’API diventa semplice, particolarmente quando comparato con le tradizionali API SQL-based come JDBC.

Il DBMS Oracle già forniva dalla versione 9 il supporto alla memorizzazione, alla ricerca e all’indicizzazione di documenti XML. Oracle Database 12c estende tale funzionalità ai documenti JSON, introducendo le due implementazioni dell’interfaccia SODA, denominate, come suddetto, SODA for REST e SODA for JAVA, e ponendosi sul mercato come valida alternativa tra i NoSQL-style Document Store.

Oracle NoSQL-style Document Store Capabilities. In Oracle DB 12c, i documenti vengono memorizzati, indicizzati e ricercati senza che il database ne conosca la struttura (schemaless). Ciò lascia agli sviluppatori la libertà di modificare la struttura dei documenti JSON in base alle esigenze. Non esiste un datatype dedicato per memorizzare i documenti JSON, ma gli stessi vengono memorizzati con i tipi standard VARCHAR2, CLOB e BLOB. Viene introdotto il nuovo constraint “IS JSON”, utilizzato per assicurare che il contenuto di una colonna sia un JSON valido, fornendo pieno supporto al trattamento avanzato dei JSON, come disaster recovery, replication, compression ed encryption.

Inoltre, è possibile eseguire delle query SQL direttamente sulle tabelle di documenti JSON del database utilizzando le JSON Path Expressions. Tali espressioni sono equivalenti al linguaggio xPath in XML e sono sintatticamente simili a JavaScript. Si riportano di seguito degli esempi:

JsonPathExpressions.png

SODA API. SODA fornisce un set di API semplice da utilizzare per lavorare con i documenti memorizzati in un Oracle Database. L’oggetto Database, che è richiesto per interagire con le Collections, viene istanziato usando un database connection con le API SQL standard di Oracle. La versione corrente di SODA adotta una strategia di optimistic locking, ma quella di pessimistic locking èsarà probabilmente disponibile nelle future release.

La specifica SODA definisce un set di metodi che forniscono le seguenti funzionalità:

  • Stabilire una connessione ad un Oracle Database Document Store
  • Creare e cancellare una collezione
  • Creare, ricerca, aggiornare e cancellare un documento
  • Elencare i contenuti di una collezione
  • Ricercare una collezione di documenti che “matchino” una espressione Query By Example (QBE)
  • Operazioni di “bulk insert” in una collezione
  • Creazione e cancellazione di indici

Di seguito, riporto alcune caratteristiche dell’implementazione “SODA for JAVA”, tralasciando “SODA for REST” (utile nel caso ci si voglia interfacciare direttamente con il Document Store con il paradigma REST).

SODA for JAVA. Consiste di un set di semplici classi che rappresentano un database, una collezione di documenti e il documento stesso. I metodi che queste classi forniscono permettono di gestire e ricercare le collezioni e i documenti JSON memorizzati. Utilizza una connessione JDBC standard e SQL*NET per comunicare con il database: ciò significa che le API sono transazionali e una serie di operazioni SODA può generare una singola transazione. Poiché SODA utilizza una connessione JDBC, è possibile utilizzare sia le API di SODA for JAVA che quelle tradizionali JDBC.

Di seguito, si riportano le principali classi di “SODA for JAVA” con relativa descrizione:

Classe Descrizione Commenti
OracleClient Classe client generica SODA. L’entry point di SODA per i JSON.
OracleRDBMSClient La classe Client dell’Oracle Database Usata per recuperare l’oggetto OracleDatabase
OracleDatabase Rappresenta un Document Store, il quale consiste di uno o più collezioni. Usato per accedere alle collezioni.
OracleDatabaseAdmin Usato per creare e cancellare collezioni
OracleCollection Rappresenta una collezione di un Document Store
OracleCollectionAdmin Usato per creare e cancellare indici
OracleDocument Rappresenta un documento in un Document Store Aggiorna (o crea) il documento con un dato ID

Struttura di un documento di una collezione. Di seguito, si riporta la struttura SQL di una collezione rappresentata su una tabella Oracle e contenente il JSON in corrispondenza di una colonna CLOB:

Name                                             Null?   Type

—————————————– ——– —————————-

ID                                              NOT NULL VARCHAR2(255)

CREATED_ON                                      NOT NULL TIMESTAMP(6)

LAST_MODIFIED                                   NOT NULL TIMESTAMP(6)

VERSION                                         NOT NULL VARCHAR2(255)

JSON_DOCUMENT                                     CLOB

Le colonne della tabella rappresentano quanto segue:

 ID ID autogenerato del singolo record
 JSON_DOCUMENT Contenuto del documento in JSON
 CREATED_ON Timestamp (autogenerato) di inserimento del record
 LAST_MODIFIED Timestamp (autogenerato) di modifica del record
 VERSION Versione del documento (incrementato automaticamente quando viene modificato)

Per dettagli sulle API di SODA e sulla potenza espressiva delle Query By Example per la ricerca dei documenti di una collezione: http://docs.oracle.com/cd/E63251_01/doc.12/e58124/soda.htm#ADSDA107

Memorizzazione dei documenti JSON (codifica e datatype). Un documento JSON può essere considerato un dato semi-strutturato, ossia non conforme alla struttura formale dei modelli di dato associato con le basi di dati relazionali. Esso, comunque, contiene etichette o altri marcatori per separare gli elementi semantici e rafforzare le gerarchie di record e campi all’interno del dato. E’ anche conosciuto come “dato senza schema” o “dato con struttura autodescritta”.

Oracle raccomanda di memorizzare tali dati utilizzando datatype di tipo LOB, in quanto la quantità di caratteri può essere elevata (maggiore di 4000 byte e, dunque, della massima capacità di un datatype VARCHAR2). I datatype raccomandati per i contenuti testuali sono Characted Large Object (CLOB) e National Character Large Object (NCLOB).

Il datatype CLOB è raccomandato per la memorizzazione di stringhe o documenti di lunghezza fissa. Invece, il datatype NCLOB è raccomandato per quelli a lunghezza variabile.

Riferimento: https://docs.oracle.com/database/121/ADXDB/json.htm#ADXDB6252

Per quanto riguarda il character encoding, conviene adottare quello AL16UTF16 o AL32UTF8. In particolare, Oracle raccomanda l’uso di AL32UTF8 per memorizzare i dati con caratteri Unicode.

Riferimenti:
https://docs.oracle.com/cd/E11882_01/appdev.112/e18294.pdf
https://docs.oracle.com/database/121/NLSPG/ch2charset.htm#NLSPG179

Sicurezza dei dati. Al fine di salvaguardare la sicurezza e l’integrità dei dati,è possibile sfruttare il meccanismo di Oracle Secure Files, il quale consente anche le compressione dei dati memorizzati all’interno di datatype LOB.

Riferimento: https://docs.oracle.com/database/121/ADLOB/toc.htm

[iOS] iOs Data Storage guidelines reject (2.23 – App Store Review Guidelines)

Brutta parola, “Apple reject“. La strada per farsi approvare un’app da Apple per il rilascio su Apple Store è assai tortuosa. Occorre seguire per filo e per segno ciascun punto delle App Store Review Guidelines. C’è un punto (il 2.23) che riguarda le iOS Data Storage Guidelines che onestamente non riesco a “disambiguare”, visto che su vari blog si danno suggerimenti e pareri assai discordi su come rispettarle. Il mio grosso quesito è capire dove è corretto salvare i contenuti che vengono scaricati tramite la mia app, considerando che questi vengono prima acquistati (con il sistema In-App Purchases di Apple) e poi sincronizzati manualmente dagli utenti.

Nell’ultima app che ho sottoposto al processo di approvazione di Apple, mi è stato risposto con un messaggio di rigetto riguardo il punto 2.23 e che vi incollo di seguito:

2.23
We also found that your app does not follow the iOS Data Storage Guidelines, which is required per the App Store Review Guidelines.

In particular, we found that after downloading one content, your app stores 13.8 MB. To check how much data your app is storing:

– Install and launch your app
– Go to Settings > iCloud > Storage & Backup > Manage Storage
– If necessary, tap “Show all apps”
– Check your app’s storage

The iOS Data Storage Guidelines indicate that only content that the user creates using your app, e.g., documents, new files, edits, etc., may be stored in the /Documents directory – and backed up by iCloud.

Temporary files used by your app should only be stored in the /tmp directory; please remember to delete the files stored in this location when the user exits the app.

Data that can be recreated but must persist for proper functioning of your app – or because customers expect it to be available for offline use – should be marked with the “do not back up” attribute. For NSURL objects, add the NSURLIsExcludedFromBackupKeyattribute to prevent the corresponding file from being backed up. For CFURLRef objects, use the corresponding kCFURLIsExcludedFromBackupKeyattribute.

For more information, please see Technical Q&A 1719: How do I prevent files from being backed up to iCloud and iTunes?

In poche parole, Apple dice che quando l’app permette agli utenti di scaricare contenuti (downloadable contents), che siano essi immagini, video, audio, pdf, ecc., questo potrebbe far diminuire lo spazio sul dispositivo (e fin qui nessun problema); ma la cosa indesiderata è che il nuovo sistema iCloud potrebbe backuppare l’app con tutti i file scaricati e consumare lo spazio dell’account (che come si sa, è gratuito fino ai primi 5 giga, e a pagamento annuale in base alle soglie di spazio richiesto). A questo punto è iniziata la mia indagine e ho studiato un pò il caso per capire meglio come risolvere questo grosso dilemma e magari aiutarvi ad affrontarlo alla meglio.

Nel rispetto dei requisiti di storage dei dati sugli iDevice, Apple ha stilato le iOS Data Storage Guidelines in cui si legge questo (NOTA. La traduzione è ad interpretazione mia e mi scuso per eventuali errori):

iOS Data Storage Guidelines. iCloud include un sistema di backup che automaticamente effettua il salvataggio dei dati presenti sui device iOs degli utenti in modalità WI-FI. Tutto quello che si trova nella Home Directory della propria app viene backuppato, ad eccezione dell’application bundle, delle directory di cache e dei file temporanei.
Le musiche acquistate (su iTunes), le apps, le Camera Roll (le foto inserite nelle categorie, dette “rullini”), le impostazioni del telefono, la home screen e l’organizzazione delle app, i messaggi e le suonerie vengono automaticamente backuppate.

Poichè i backup vengono eseguiti in modalità wireless e memorizzati in iCloud per ciascun utente, occorre minimizzare la quantità di dati che le apps memorizzano. File grandi allungano i tempi di backup e consumano spazio di storage sull’account iCloud.

Affinchè i backup siano il più possibile efficienti, occorre assicurare che l’app memorizzi i dati in accordo con le seguenti linee guida:

  1. Solo i documenti o altri dati che vengono generati dall’utente (user-generated), o che non possono essere altrimenti ricreati dall’app, devono essere memorizzati nella directory /Documents e verranno automaticamente backuppati da iCloud.
  2. I dati che possono essere scaricati più volte o rigenerati dovrebbero essere memorizzati nella directory /Library/Caches. Esempi di file che potrebbero essere salvati nella directory Caches includono i file di cache del database e contenuto scaricabile (downloadable content), come magazine, newspaper e map applications.
  3. I dati che vengono usati soltanto temporaneamente dovrebbero essere memorizzati nella directory /tmp. Sebbene questi file non vengono backuppati da iCloud, occorre ricordare di cancellarli quando non servono più così da non consumare spazio sul dispositivo dell’utente.
  4. Usare l’attributo “do not back up per specificare i file che dovrebbero rimanere sul device, anche in situazioni di basso storage. Questo attributo si usa con i dati che possono essere ricreati ma che occorre siano persistenti, anche in situazioni di basso storage, per far funzionare propriamente l’app o perchè gli utenti si aspettano di averli disponibili anche durante l’uso offline. L’attributo funziona sui file marcati a prescindere dalla directory in cui si trovano, inclusa la directory Documents. Questi file non verranno eliminati o non verranno inclusi nell’iCloud dell’utente o di backup di iTunes. Poichè questi file utilizzano spazio di archiviazione sul device, la vostra app è responsabile del controllo e dell’eliminazione periodica di questi file.

Per maggiori dettagli vedi: Technical Q&A QA1719-How do I prevent files from being backed up to iCloud and iTunes?

Prima di entrare nel meglio della trattazione tecnica e del codice di programmazione, riporto quanto estratto dal documento di App Backup Best Practices.

Continua la lettura