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 )