1

I have created a TinyDB (version 4.5.2, documentation: https://tinydb.readthedocs.io/en/latest/usage.html) database locally (macbook air, running macOS BigSur, v. 11.5.2), db.json, with a table named log, using Python 3.9.6 for the purpose of building a small application on top of some weight-training log-data. Currently I am trying to query the log table for data where the exercise has the name: squat. Getting either all exercises back when using the any method, or an empty list when using the all method. The data in the db.json has the following structure (just showing 2 exercises):

{
  "log": {
    "1": {
      "date": "2021-12-11",
      "split": "legday",
      "exercises": [
        {
          "name": "squat",
          "sets": [
            { "set no.": 1, "reps": 8, "weight": "70 kg" },
            { "set no.": 2, "reps": 8, "weight": "80 kg" },
            { "set no.": 3, "reps": 5, "weight": "90 kg" },
            { "set no.": 4, "reps": 5, "weight": "90 kg" }
          ]
        },
        {
          "name": "deadlift",
          "sets": [
            { "set no.": 1, "reps": 8, "weight": "70 kg" },
            { "set no.": 2, "reps": 8, "weight": "80 kg" },
            { "set no.": 3, "reps": 5, "weight": "90 kg" },
            { "set no.": 4, "reps": 5, "weight": "90 kg" }
          ]
        }
      ]
    }
  }
}

What I have tried so far:

"""
Date: 2021-12-11
Author: Gustav Collin Rasmussen
Purpose: Store and analyze weight-training data
"""

import json

from tinydb import Query, TinyDB


def insert_data(db, log):
    """Store training log in database"""
    log_path = "training_log.json"
    with open(log_path) as rf:
        json_content = json.load(rf)
    log.insert(json_content)


def describe_workout(db):
    """Simple summary statistics for each exercise"""
    for item in db:
        for exercise in item["exercises"]:
            print(f"exercise: {exercise['name']}")
            print(f"number of sets: {len(exercise['sets'])}\n")


def analyze_workout(db, log):
    """Deeper analysis of workout"""
    Log = Query()
    Exercise = Query()
    # print(log.search(Exercise.date == "2021-12-11"))
    print(log.search(Log.exercises.any(Exercise.name == "squat")))  # <---------- RETURNS ALL DATA !
    # print(db.search(Exercise.exercises.all(Exercise.name == "squat")))
    print(log.search(Log.exercises.all(Exercise.name == "squat")))  # <---------- RETURNS EMPTY LIST !


def main():
    db = TinyDB("db.json")
    log = db.table("log")

    # insert_data(db, log)
    # describe_workout(db)
    analyze_workout(db, log)  # <-------- CALLING THE QUERIES FROM HERE !


if __name__ == "__main__":
    main()

The official examples for querying nested JSON is very similar, from https://tinydb.readthedocs.io/en/latest/usage.html :

>>> Group = Query()
>>> Permission = Query()
>>> groups = db.table('groups')
>>> groups.insert({
        'name': 'user',
        'permissions': [{'type': 'read'}]})
>>> groups.insert({
        'name': 'sudo',
        'permissions': [{'type': 'read'}, {'type': 'sudo'}]})
>>> groups.insert({
        'name': 'admin',
        'permissions': [{'type': 'read'}, {'type': 'write'}, {'type': 'sudo'}]})
Now let’s search this table using nested any/all queries:

>>> # Group has a permission with type 'read'
>>> groups.search(Group.permissions.any(Permission.type == 'read'))
[{'name': 'user', 'permissions': [{'type': 'read'}]},
 {'name': 'sudo', 'permissions': [{'type': 'read'}, {'type': 'sudo'}]},
 {'name': 'admin', 'permissions':
        [{'type': 'read'}, {'type': 'write'}, {'type': 'sudo'}]}]
>>> # Group has ONLY permission 'read'
>>> groups.search(Group.permissions.all(Permission.type == 'read'))
[{'name': 'user', 'permissions': [{'type': 'read'}]}]

so I am confused about the different behaviour. Can you see the missing link here?

(also had a look at the similar question on SO, Is it possible to query nested json object using TinyDB without luck )

Gustav Rasmussen
  • 3,720
  • 4
  • 23
  • 53
  • 1
    Tangential, but you probably want `exercises` to be a dictionary with keys of `name` and values of your `sets` rather than a list – JonSG Dec 11 '21 at 18:02
  • Could you show a small example of this structure, and how to query for a specific exercise ? – Gustav Rasmussen Dec 11 '21 at 20:16
  • @JonSG took your advice on data structure: https://github.com/TheNewThinkTank/Fitness-Tracker/blob/main/data/log_archive/JSON/2021/December/training_log_2021-12-11.json , which is a lot more clear now. Still struggling with the `analyze_workout` function call in: https://github.com/TheNewThinkTank/Fitness-Tracker/blob/main/src/training.py . If you see the issue, please feel free to post an answer that I may then approve. – Gustav Rasmussen Dec 21 '21 at 11:10
  • Hi, if you update the question with the changes you made, I will install tinydb and see about getting you an answer – JonSG Dec 21 '21 at 16:49

0 Answers0