TinyDB : Une base de données adaptée à vos projets personnels

Un outil pratique pour gérer une base de données sans se prendre la tête lors du développement de tes projets

Publié le par Thibault Houdon (mis à jour le )
paceTemps de lecture estimé : 8 minutes

Sur mon dernier projet, j'avais besoin de stocker un peu de données. Les solutions que je connaissais déjà ne me convenaient pas. Je n'avais ni envie de mettre en place une base de donnée SQL ni envie de m'embêter avec des fichiers JSON.

Il me fallait quelque chose entre les deux.

<blockquote>

A database optimised for your happiness.

</blockquote>

J'ai cherché un peu et j'ai découvert TinyDB qui est une minuscule base de données document oriented.

Ça existe depuis des années et ça continue d'être mis à jour régulièrement. C'est parfait pour les petits projets personnels. L'API est super simple et amusante à utiliser !

C'est un outil que tu devrais ajouter dans ta besace de développeur chevronné, je te le conseille.

Dans cet article, je te présente l'outil et je te montre les fonctionnalités de base comme l'ajout, la suppression, la mise à jour et la recherche.

Ah oui, TinyDB est open source, cela veut dire que tu peux y contribuer sur GIthub si jamais ça t'intéresse ! 👍

Les avantages

  • Écrit en Python pur
  • Aucune dépendances
  • Document Oriented
  • Compatible Python2 et Python3
  • Facile à utiliser, API très propre
  • Légère (~2000 lignes de codes, pas plus)
  • Extensible pour coller à vos besoins

Si tu as besoin d'une base de données simple avec une API propre qui fonctionne bien sans beaucoup de configurations, TinyDB pourrait être le bon choix pour toi.

Les inconvénients

  • Impossible de créer des index vu que c'est stocké en JSON
  • Impossible de gérer les relations entre les tables pour les mêmes raisons
  • Pas de garantie ACID (donc évite les opérations 'critiques' comme des paiements)
  • Faibles performances

→ Si tu as besoin de fonctionnalités avancées ou de hautes performances, TinyDB n'est pas la bonne base de données pour toi - pense à utiliser des bases de données plus classiques comme SQLite3 qui est fournie dans la librairie standard de Python.

Comment on l'utilise ?

Tout d'abord, il faut que tu l'installes, ça paraît évident. Pour ça, rien de compliqué, on passe par pip comme d'habitude :

pip install tinydb

Ensuite, on importe la librairie et on définit notre base de données :

from tinydb import TinyDB, Query, where

db = TinyDB('db.json')

Sans rentrer dans les détails :

  • TinyDB - Représente ta base de données
  • Query - Permet d'interroger ta base de données
  • where - Permet d'affiner tes critères de recherche

Si tu exécutes ce code, cela va juste créer un fichier db.json vide.

On va ensuite créer une table. Comme c'est bientôt l'été, j'ai envie de partir sur des fruits :

from tinydb import TinyDB, Query

db = TinyDB('db.json')
fruits = db.table('fruits')

Si tu ne crées pas de table, TinyDB le fait pour toi automatiquement et crée une table _default.

En faisant ça, tes données sont accessibles à n'importe quel moment et n'importe où dans ton programme sans que tu aies besoin de te reconnecter à ta base de données au préalable !

Personnellement, je trouve ça vraiment pratique.

Tout est prêt, on peut commencer à peupler notre table fruits :

J'utilise pprint plutôt que la fonction print de base histoire que ce soit plus simple à lire.

from tinydb import TinyDB, Query
from pprint import pprint

db = TinyDB('db.json')
fruits = db.table('fruits')

fruits.insert({'type': 'fraise', 'quantite': 4})
fruits.insert({'type': 'orange', 'quantite': 1})
fruits.insert({'type': 'banane', 'quantite': 7})

pprint(fruits.all())
#[{'quantite': 4, 'type': 'fraise'},
#{'quantite': 1, 'type': 'orange'},
#{'quantite': 7, 'type': 'banane'}]

Et si on regarde du côté de notre fichier db.json :

{"fruits": {"1": {"type": "fraise", "quantite": 4}, "2": {"type": "orange", "quantite": 1}, "3": {"type": "banane", "quantite": 7}}}

Tu peux remarquer que chaque entrée est automatiquement associée à un doc_id unique qui s'incrémente automatiquement à chaque fois que tu insères une nouvelle valeur 🙂

Tu peux aussi itérer sur le items de ta table avec une boucle for classique :

for fruit in fruits:
    pprint(fruit)
#[{'quantite': 4, 'type': 'fraise'},
#{'quantite': 1, 'type': 'orange'},
#{'quantite': 7, 'type': 'banane'}]

Et évidemment, tu peux aussi rechercher un élément en particulier, de plusieurs manières :

# SYNTAXE LONGUE
Fruit = Query()
fraise = fruits.search(Fruit.type == 'fraise')
pprint(fraise)
# [{'quantite': 4, 'type': 'fraise'}]

# SYNTAXE COURTE
fraise = fruits.search(where('type') == 'fraise')
pprint(fraise)
# [{'quantite': 4, 'type': 'fraise'}]

# VIA SON DOCUMENT ID
fraise = fruits.get(doc_id=1)
pprint(fraise)
# [{'quantite': 4, 'type': 'fraise'}]

Tu peux combiner à cela des opérateurs logiques et des opérateurs de comparaison pour affiner tes requêtes.

pprint(fruits.search((Fruit.quantite > 1) & (Fruit.quantite < 20)))
# [{'quantite': 4, 'type': 'fraise'}, {'quantite': 7, 'type': 'banane'}]

Une fois que tu as compris comment tout ça fonctionne, tu peux l'appliquer à tous les types d'opérations :

# METTRE À JOUR UN ITEM
fruits.update({'quantite': 8}, Fruit.type == 'fraise')

# SUPPRIMER UN ITEM
fruits.remove(where('type') == 'orange')

Si tu n'aimes pas ces fruits, tu peux faire du ménage comme ça :

fruits.truncate()
# {"fruits": {}}

Ou carrément supprimer tout ce qu'il y a dans ta base de données :

db.purge()
# []

Je pense que ces opérations de base couvriront 90% de tes besoins !

Si tu en veux plus, n'hésite pas à consulter la documentation officielle.

Tu pourrais par exemple stocker tes données directement en mémoire ou dans le cache plutôt que dans un fichier JSON.