⏱ Reading time: 8 min

Uno degli ingredienti per sviluppare una buona applicazione è usare un buon database. In questo articolo scopriremo come è semplice integrare Couchbase Lite nelle app iOS.

Please accept YouTube cookies to play this video. By accepting you will be accessing content from YouTube, a service provided by an external third party.

YouTube privacy policy

If you accept this notice, your choice will be saved and the page will refresh.

Che cos’è Couchbase Lite? Couchbase Lite è l’SDK mobile, facente parte della suite Couchbase. Permette agli sviluppatori di integrare facilmente il database NoSQL nelle loro app mobile sia Android che iOS.

Integrazione di Couchbase su Mobile e su Web
Integrazione di Couchbase su Mobile e su Web

Per dare una panoramica sulle funzionalità dell’SDK, passeremo attraverso le operazioni CRUD che mette a disposizione, e per ciascuna vedremo i passaggi da seguire per l’utilizzo.

C come “Create”

Bene, il primo passaggio che dobbiamo fare è creare il nostro primo documento con Couchbase. Couchbase offre un metodo per creare un documento, saveDocument(_ document:concurrencyControl:). Questo metodo accetta due parametri: il primo è chiaramente il documento (CouchbaseLiteSwift.MutableDocument) da salvare; il secondo è un parametro opzionale (CouchbaseLiteSwift.ConcurrencyControl) che consente all’utente di scegliere se risolvere automaticamente possibili conflitti in fase di scrittura, o generare un’eccezione per consentire all’utente di gestire manualmente la risoluzione. Il valore predefinito è impostato a lastWriteWins.

Come si usa il metodo saveDocument?

In primis abbiamo bisogno di un’istanza del Database (CouchbaseLiteSwift.Database).

do {
    let database = try Database(name: "DatabaseName")
} catch {
    ...
}

Poi abbiamo bisogno di creare il documento che vogliamo salvare. Creiamo un nuovo documento (CouchbaseLiteSwift.MutableDocument) e aggiungiamo alcuni campi.

let doc = MutableDocument(id: "MyUniqueDocumentIdentifier")
doc.setString("Mickey", forKey: "name")
doc.setString("Mouse", forKey: "surname")
doc.setInt(91, forKey: "age")
doc.setString("Contact", forKey: "type")

Una volta istanziato, possiamo salvarlo.

do {
    try database.saveDocument(doc, concurrencyControl: .lastWriteWins)
} catch {
    ...
}

Come anticipato, creare e salvare un documento con Couchbase è veramente semplice e intuitivo.

Qualche accorgimento…

Typing: nel documento ho aggiunto un campo chiamato “type” (doc.setString("Contact", forKey: "type")). E’ un modo per consentire di assegnare al documento un tipo, suddividendo quindi il dataset e facilitando le operazioni di lettura. Vedremo in seguito come utilizzare questo campo.

Id: non è necessario fornire un ID quando si crea un documento. È un campo opzionale. Qualora non specificato, Couchbase genera per te un UUID.

Document creation: se lo desideri, puoi creare un documento da un dizionario (una mappa key-value) semplicemente passandolo come parametro sul costruttore del documento.

R come “Read”

Ora che abbiamo creato il nostro primo documento, vogliamo anche ottenerlo dal database. Andiamo a vedere come!

Ci sono due vie per recuperare un documento:

  1. Ottenerlo partendo dal suo ID;
  2. Effettuare una query di lettura.

ID

Per recuperare un documento usando il suo ID abbiamo prima bisogno di un’istanza del Database.

do {
    let database = try Database(name: "DatabaseName")
} catch {
    ...
}

Possiamo poi usare il metodo document(withID:...) che richiede come parametro l’id del documento da ottenere. Il metodo restituisce l’oggetto Document qualora esso venga trovato nel dataset, e in caso contrario restituisce un valore nullo. La firma del metodo infatti prevede il tipo Optional sui linguaggi tipizzati come Swift (CouchbaseLiteSwift.Document?).

let doc = database.document(withID: "MyUniqueDocumentIdentifier")

Query

Come per l’id, è necessaria un’istanza del database anche per la query.

do {
    let database = try Database(name: "DatabaseName")
} catch {
    ...
}

Lo step successivo è creare la query. Per fare questo, utilizziamo il metalinguaggio N1QL. N1QL consente all’utente di definire una query con una sintassi simile a SQL, ma interfacciandosi ad un database NoSQL.

let query = QueryBuilder
  .select(SelectResult.all())
  .from(DataSource.database(database))
  .where(
    Expression.property("type")
      .equalTo(Expression.string("Contact"))
  )

In questo modo abbiamo definito una semplice query che cerca tutti i documenti (con tutti i campi ovviamente) dal database in cui il campo type è uguale a Contact

Non ci resta che eseguire la query. Come risultato, riceviamo un set di risultati contenente tutti i documenti che corrispondono alle proiezioni e selezioni della query.

do {
    let result = try query.execute()
} catch {
   ...
}

L’oggetto risultante è conforme al protocollo Iterator, e può quindi essere iterato per operare su ogni documento contenuto nel result set. Il risultato restituito dalla query è un’istantanea dei dati, ottenuta al momento dell’esecuzione dell’operazione. I documenti modificati successivamente non saranno presi in considerazione.

In più…

Query listener: Couchbase fornisce anche un altro metodo per eseguire query. Questo secondo metodo consente all’utente non solo di recuperare i dati dalla query creata, ma anche di ascoltare le modifiche future che verranno effettuate sui dati afferenti al result set. Fare questo è tanto semplice quanto il primo metodo. Diamo un’occhiata!

let token = query.addChangeListener { queryChange in
    let results = queryChange.results?.allResults()
}

La closure verrà invocata ogni volta che cambieranno i documenti inclusi nel risultato della query. Il token restituito dai metodi addChangeListener può essere utilizzato per interrompere la sottoscrizione agli aggiornamenti.

query.removeChangeListener(withToken: token)

Document conversion: come per la creazione, puoi facilmente convertire un Document in un dizionario (e viceversa) usando il metodo toDictionary().

U come “Update”

Bene, ora che siamo in grado di creare e leggere documenti su Couchbase, perché non capire come aggiornarli?

L’aggiornamento di un documento è molto simile alla creazione. Hai solo bisogno di ottenere il documento, aggiornarlo e salvarlo di nuovo. Vediamo come. Iniziamo con il Database.

do {
    let database = try Database(name: "DatabaseName")
} catch {
    ...
}

Recuperiamo poi il documento da aggiornare…

let doc = database.document(withID: "MyUniqueDocumentIdentifier")

… E aggiorniamolo!

let docToUpdate = doc.toMutable()
docToUpdate.setString("Male", forKey: "gender")

Naturalmente poi persistiamo le modifiche.

do {
    try database.saveDocument(docToUpdate, concurrencyControl: .lastWriteWins)
} catch {
    ...
}

D come “Delete”

Ultimo ma non meno importante, l’eliminazione di un documento. Potremmo aver bisogno di eliminare alcuni documenti, ed ecco qui come si può fare.

Come sempre hai bisogno del database.

do {
    let database = try Database(name: "DatabaseName")
} catch {
    ...
}

Come per l’operazione di aggiornamento, recuperiamo il documento da eliminare.

let doc = database.document(withID: "MyUniqueDocumentIdentifier")

E ora è possibile utilizzare il metodo deleteDocument(_ document: concurrencyControl:) per eliminarlo. Similmente a saveDocument, possiamo scegliere se risolvere i conflitti manualmente o mantenere automaticamente la versione corrispondente all’ultima scrittura.

do {
    try database.deleteDocument(doc, concurrencyControl: .lastWriteWins)
} catch {
    ...
}

Conclusione… o forse no?

Ottimo, da adesso siamo in grado di integrare Couchbase Lite nelle nostre app. In sintesi, ecco cosa abbiamo visto:

  1. Creare un documento;
  2. Leggere un documento (o molti), ricevendo anche aggiornamenti in tempo reale;
  3. Aggiornare un documento (azione simile alla creazione);
  4. Eliminare un documento.

Cos’altro puoi desiderare? Credo niente di più! 😄

Scherzi a parte, le funzionalità di Couchbase Lite non terminano qui. Perché la ciliegina sulla torta arriva proprio ora. Sì, perché Couchbase offre un’altra fantastica funzionalità!

Sincronizzazione

La sincronizzazione è una delle funzionalità di punta di Couchbase. E implementarla è tanto semplice quanto efficace. 

Couchbase Lite fornisce la possibilità di sincronizzare in locale un’istanza di un database remoto che risiede su un Couchbase Server. Tutta o in parte. La sincronizzazione avviene attraverso il Sync Gateway, che dialoga con Couchbase Server e determina le modifiche da propagare al client. L’SDK client si connette al Sync Gateway tramite un protocollo websocket.
Per la replica utilizziamo il Replicator di Couchbase.

do {
    let database = try Database(name: DatabaseName)
} catch {
    ...
}

Cosa serve per avviare un oggetto Replicator (CouchbaseLiteSwift.Replicator)?

Abbiamo bisogno di un oggetto di configurazione in cui l’unico campo obbligatorio è l’URL per contattare il Sync Gateway. Gli altri campi opzionali sono, ad esempio, replicatorType con cui è possibile scegliere la direzionalità della replica rispetto al client, ossia se deve funzionare in push, pull, oppure entrambi. Un altro campo per la configurazione della replica è continuous: un flag che consente di configurare la replica per essere eseguita una volta sola o continuamente.

let targetEndpoint = URLEndpoint(url: "ws://localhost:4984/bucketname/")
 
let replConfig = ReplicatorConfiguration(database: database, target: targetEndpoint)
replConfig.replicatorType = .pushAndPull
replConfig.continuous = true
replConfig.authenticator = BasicAuthenticator(username: "user", password: "pwd")
 
let replicator = Replicator(config: replConfig)

Una volta ottenuto l’oggetto replicator abbiamo solo bisogno di avviare la replica…

replicator.start()

…o di interromperla.

replicator.stop()

Qualche accorgimento

Osserva lo stato della replica: come per la query, anche per la replica possiamo aggiungere un listener per ricevere le modifiche sul suo stato.

let token = replicator.addChangeListener { changes in
    let status = changes.status
}

Per quanto riguarda le query, il token è utilizzato per rimuovere la sottoscrizione dal replicatore.

replicator.removeChangeListener(withToken: token)

Conclusioni

Couchbase Lite, come parte della suite Couchbase, è una potente freccia per l’arco di uno sviluppatore mobile. In questo articolo abbiamo trattato solo una piccola parte delle sue potenzialità. Essendo una tecnologia ricca di possibilità e sfaccettature, il nostro consiglio è quello di approfondire le funzionalità di Couchbase, leggendo anche i prossimi articoli di questa rubrica, per consentirti di avere il pieno controllo del database delle tue app e non solo. Inoltre, potrai capire come questa soluzione può adattarsi al meglio alle tue esigenze.

Non ti resta che attendere l’uscita del prossimo articolo di Couchbase 😉

A presto!