NoSQL en Flutter
Tags: flutter, dart, nosql, async
Published: 2020-03-27 17:20:27

¡Buenas a todos! En este post veremos como usar una base de datos NoSQL en Flutter para guardar información de forma persistente.

# SharedPreferences vs NoSQL databases

Muchos que hayáis estado trabajando/jugando con Flutter conoceréis que se recomienda el uso del paquete [shared_Preferences](https://pub.dev/packages/shared_preferences) para guardar información en formato **clave-valor** del usuario.

En mi caso, trabajando en un proyecto para utilizar Flutter en Mobile, web y desktop, encontré un problema para usarlo. En SO Linux no está soportado todavía por lo que debía encontrar otra solución. En ese momento encontré Sembast.

# Sembast
[Sembast](https://pub.dev/packages/sembast) es un paquete que nos permite trabajar con bases de datos NoSQL. Este paquete tiene bastantes versiones estables y un buen rating global sobre la estabilidad del mismo.

Para instalarlo únicamente deberemos añadirlo en nuestro pubspec.yaml

```yaml
sembast: ^2.3.0
```
# Planteamiento del problema

En mi aplicación necesitaba guardar el token de autentificación del usuario al hacer login y poder recuperarlo por cada petición que tuviera que hacer al backend.

# Sembast en Web

En el día que escribo el artículo sembast tiene un paquete independiente para web pero que no voy a utilizar porque no permite la elección de la clave para guardar datos, debes recoger la clave al guardar el dato y usarla cuando quieras recuperarlo. Por esta razón voy a usar shared_preferences o sembast dependiendo de la plataforma donde corre.

# Utilización

Este paquete nos provee de métodos para el acceso y guardado de datos NoSQL. En mi caso, he creado una clase TokenProvider estática para poder acceder al token y guardarlo sin tener que estar creando instancias del mismo y a la vez permitiendo diferenciar la plataforma donde corre y elegir que paquete usar. Empezamos indicando el fichero donde va a guardar la información.

```dart
import 'package:sembast/sembast.dart';
import 'package:sembast/sembast_io.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/foundation.dart' show kIsWeb;

class TokenProvicer{
  static final String dbPath = 'token.db';
  static final DatabaseFactory dbFactory = databaseFactoryIo;
}
```

Con esto tenemos indicado donde va a guardar la información y un objeto propio del paquete que nos permite trabajar con las bases de datos que le indiquemos.

### Guardar el token

Para guardar el token simplemente he creado un método que recibe el token como String, abre una "conexión" a la base de datos, ya que es en local, y obtiene un *store*

Teniendo ya nuestra colección o *store* podemos proceder a guardar el token de forma asíncrona. El paquete nos proporciona un método record donde indicaremos su clave y con el método put indicamos su base de datos y lo que queremos guardar.


```dart
static __saveTokenMobilDesktop(String token) async {
    Database db = await dbFactory.openDatabase(dbPath);
    var store = StoreRef.main();

    await store.record('token').put(db, token);
  }
```

En el caso de correr en web y no poder utilizar este paquete

```dart
static __saveTokenWeb(String token) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();

    await prefs.setString('token', token);
  }
```

Y el método que expone y decide cómo guardar el token

```dart
static saveToken(String token) {
    kIsWeb ? __saveTokenWeb(token) : __saveTokenMobilDesktop(token);
  }
```


### Recuperar el token

Teniendo la información guardada, únicamente debemos acceder a ella para poder leer el token y hacer las peticiones. En este caso, creamos otro método que no recibe parámetros y devuelve el token con el que vamos a hacer la petición.

```dart
static __loadTokenMobilDesktop() async {
    Database db = await dbFactory.openDatabase(dbPath);
    var store = StoreRef.main();

    return await store.record('token').get(db) as String;
  }
```

En el caso de usar shared_preferences.
```dart
  static __loadTokenWeb() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    
    return prefs.getString('token');
  }
```

Y el método que expone y decide.
```dart
static loadToken() {
    return kIsWeb ? __loadTokenWeb() : __loadTokenMobilDesktop();
  }
```

### Uso en nuestra aplicación

Teniendo la clase creada, solo debemos referenciarla cuando vayamos a guardar el token, por ejemplo:

```dart
await loginProvider.login();
TokenProvicer.saveToken(loginProvider.token);
```

Y donde vayamos a hacer la petición.

```dart
this.token = await TokenProvicer.loadToken();
final response = await http.get(
      this.endPoint + username,
      headers: {'Authorization': 'Bearer $token'}
      );
```

# Conclusión
Sembast es un paquete muy sencillo y estable para el manejo de bases de datos NoSQL aunque tenga la limitación de que en su parte web todavía no ofrece las mismas funcionalidades que en Mobile o Desktop.

Os animo a echarle un vistazo en su [repo](https://github.com/tekartik/sembast.dart) donde encontraréis muchos más ejemplos y características del paquete. También agradecer a la organización que ha creado y mantiene el paquete [tekatrik](http://www.tekartik.com/)

¡Un saludo y hasta la próxima!