Welcome to Tony's Notebook

First experiences with TinyDB

In this article I take a quick intro look at TinyDB which is a little document-oriented database written in pure Python. Data is stored in the database in JSON format. I was using TinyDB in conjunction with some Python web apps I was running on Glitch. I am really enjoying using Glitch to develop and host Python/Flask applications. I'll be writing a piece on Glitch for Python in the near future.

Note that TinyDB uses a single file for persistence, this is not a database management system, but it is a simple way to store and access data your Python application may need to process.

Installation

How to install on Glitch. Add the following to your requirements.txt file:

tinydb

That's it! This is how software is supposed to work.

Getting started

You need to make sure you import TinyDB first:

from tinydb import TinyDB, Query

This also imports Query as we're going to use that to run queries on our database. Before we do that we need to initialize the database:

db = TinyDB('db.json')

This gives you a db object that allows you to run queries on the database. TinyDB uses a file to store its data. In this case the file is db.json.

If you want to delete all records/documents from the database you can do the following:

db.truncate()

Now let's add some data:

from tinydb import TinyDB, Query

db = TinyDB('db.json')

obj = {'name': 'Fred', 'age': 60}
db.insert(obj)

obj = {'name': 'Jim', 'age': 40}
db.insert(obj)

You'll notice that what's happening is that we are simply inserting Python dictionary objects. Couldn't be simpler!

If you now look at your DB file you'll see the following:

less db.json | jq 
{
  "_default": {
    "1": {
      "name": "Fred",
      "age": 60
    },
    "2": {
      "name": "Jim",
      "age": 40
    }
  }
}

I pipe the output of less to jq just to nicely format the JSON.

You can see from this that the Python objects are now stored in the database file in JSON format.

Let's just add one more entry:

obj = {'name': 'Sally', 'age': 30}
db.insert(obj)

You're now ready to see how to run queries.

Querying the database

First, you can print all records easily:

print(db.all())

Or you can run queries to narrow down the data returned:

q = Query()
data = db.search(q.name == 'Fred')
print(data)

Or a variation:

data = db.search(q.age < 40)
print(data)

You can get really fancy and build multiple, complex queries. Here's a snippet from another project I'm working on:

# Query nodes - specify at least one query parameter
@app.route("/query", methods=['GET'])
def query_nodes():
  
  args = request.args
  for arg in args:
    print (arg, args[arg])

  # Build the query
  q = Query()
    
  queries = []
  if 'level' in args:
    queries.append((q.level == args['level']))
  if 'type' in args:
    queries.append((q.type == args['type']))
  if 'product' in args: 
    queries.append((q.product == args['product']))

  if (len(queries) == 0):
    print("Error - you must specify at least one field e.g. type")
    return ('Internal server error - specify at least one parameter', 500)
  
  qs = queries.pop()
  while (len(queries) > 0):
    qs =  qs & queries.pop()
  
  data = db.search(qs)
  return (jsonify(data))
...

The only limit is your imagination. Refer to the TinyDB documentation for further example. I found the documentation very accessible and informative. I was able to quickly build the applications I wanted by referring to the TinyDB docs. Nice!

Summary

In this article I took an introductory look at TinyDB, which is a nice little database to use for your web apps where you want to simply store data and run queries on it.

Resources