Quick Start
This guide takes you from zero to a working CentauroDB application. You'll define a model, store objects, query them with Python and SQL, and see schema evolution in action — all without writing a single migration.
1. Define a model
Every model inherits from CentauroModel and needs a __centauro_name__ — a stable identifier that decouples your Python class name from stored data:
from centaurodb import CentauroModel
class Note(CentauroModel):
__centauro_name__ = "Note"
title: str = ""
body: str = ""
tag: str = "general"
2. Create an engine and collection
from centaurodb import Engine, Collection
engine = Engine("app.db") # file-based SQLite
coll = Collection(engine, "app") # creates the table automatically
That's it — no CREATE TABLE, no connection pooling setup. For in-memory databases, use Engine() or Engine(":memory:").
3. Write objects
note = Note(title="Chiron's teachings", body="Wisdom from Mount Pelion", tag="lore")
coll.write_object(note)
After writing, the object has database metadata:
print(note.row.id) # 1
print(note.row.name) # "Note"
print(note.row.write_time) # when it was stored
Write a few more so we have data to query:
coll.write_objects([
Note(title="The Golden Fleece", body="Guarded by a sleepless dragon", tag="quest"),
Note(title="Labyrinth blueprint", body="Thread from Ariadne required", tag="quest"),
Note(title="Herbs of Pelion", body="Centaur remedies for battle wounds", tag="lore"),
])
4. Read objects
# By id
loaded = coll.read_object_by_id(1, Note)
print(loaded.title) # "Chiron's teachings"
# Latest note
latest = coll.read_latest_object(Note)
print(latest.title) # "Herbs of Pelion"
# All notes
all_notes = coll.read_objects(Note)
print(len(all_notes)) # 4
5. Query with the field DSL
Filter objects without writing SQL:
# By tag
quests = coll.read_objects(Note.fields.tag == "quest")
print(len(quests)) # 2
# Pattern matching
pelion_notes = coll.read_objects(Note.fields.title.like("%Pelion%"))
# Multiple conditions (AND)
results = coll.read_objects(
Note.fields.tag == "lore",
Note.fields.title.like("%Chiron%"),
)
6. Update objects
loaded.body = "Zero migrations, forever!"
coll.update_object(loaded)
# edit_time is updated; write_time is preserved
7. Query with SQL views
Create a SQL view to make your JSON data queryable with standard SQL — connect any BI tool, ORM, or dashboard. The view name is {collection}_view_{name} (here app_view_search). See Choosing a view name for naming conventions.
coll.create_view("search", Note)
df = coll.sql_select("""
SELECT title, tag
FROM app_view_search
WHERE tag = 'quest'
ORDER BY edit_time DESC
""")
print(df)
# ┌──────────────────────┬───────┐
# │ title ┆ tag │
# │ --- ┆ --- │
# │ str ┆ str │
# ╞══════════════════════╪═══════╡
# │ Labyrinth blueprint ┆ quest │
# │ The Golden Fleece ┆ quest │
# └──────────────────────┴───────┘
Speed up filtered queries by adding an index on the fields you filter on:
coll.create_index("tag")
8. Evolve your schema
Now add a priority field — no migration file, no ALTER TABLE:
class Note(CentauroModel):
__centauro_name__ = "Note"
title: str = ""
body: str = ""
tag: str = "general"
priority: int = 0 # new field — old rows get 0 on read
# Old data loads fine
old_note = coll.read_object_by_id(1, Note)
print(old_note.priority) # 0 — the default
Refresh the view to pick up the new column:
coll.refresh_view("search", Note)
Full example
from centaurodb import CentauroModel, Collection, Engine
class Note(CentauroModel):
__centauro_name__ = "Note"
title: str = ""
body: str = ""
tag: str = "general"
priority: int = 0
engine = Engine("app.db")
coll = Collection(engine, "app")
# Write
coll.write_object(Note(title="Chiron's teachings", body="Wisdom from Pelion", tag="lore", priority=1))
coll.write_object(Note(title="The Golden Fleece", body="Guarded by a dragon", tag="quest"))
# Create a SQL view (virtual — reads live data from the table)
coll.create_view("search", Note)
# Indexes live on the table, independent of the view
coll.create_index("tag")
coll.create_index("priority")
# Query with Python
lore = coll.read_objects(Note.fields.tag == "lore")
# Query with SQL
df = coll.sql_select(
"SELECT title FROM app_view_search WHERE priority > 0"
)