[{"data":1,"prerenderedAt":1611},["ShallowReactive",2],{"navigation_docs":3,"-essentials-models":106,"-essentials-models-surround":1606},[4,26,57,83],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":25},"Getting Started","i-lucide-rocket","/getting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","/getting-started/introduction","1.getting-started/1.introduction","i-lucide-info",{"title":16,"path":17,"stem":18,"icon":19},"Installation","/getting-started/installation","1.getting-started/2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick Start","/getting-started/quick-start","1.getting-started/3.quick-start","i-lucide-play",false,{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":25},"Core Concepts","i-lucide-book-open","/essentials","2.essentials",[32,37,42,47,52],{"title":33,"path":34,"stem":35,"icon":36},"Models","/essentials/models","2.essentials/1.models","i-lucide-box",{"title":38,"path":39,"stem":40,"icon":41},"Collections","/essentials/collections","2.essentials/2.collections","i-lucide-folder",{"title":43,"path":44,"stem":45,"icon":46},"Views","/essentials/views","2.essentials/3.views","i-lucide-table",{"title":48,"path":49,"stem":50,"icon":51},"Schema Evolution","/essentials/schema-evolution","2.essentials/4.schema-evolution","i-lucide-git-branch",{"title":53,"path":54,"stem":55,"icon":56},"Relations","/essentials/relations","2.essentials/5.relations","i-lucide-link",{"title":58,"icon":59,"path":60,"stem":61,"children":62,"page":25},"Advanced","i-lucide-settings","/advanced","3.advanced",[63,68,73,78],{"title":64,"path":65,"stem":66,"icon":67},"Time-Series","/advanced/time-series","3.advanced/1.time-series","i-lucide-chart-line",{"title":69,"path":70,"stem":71,"icon":72},"Async Support","/advanced/async","3.advanced/2.async","i-lucide-zap",{"title":74,"path":75,"stem":76,"icon":77},"PostgreSQL","/advanced/postgresql","3.advanced/3.postgresql","i-lucide-database",{"title":79,"path":80,"stem":81,"icon":82},"Performance Guide","/advanced/performance","3.advanced/4.performance","i-lucide-gauge",{"title":84,"icon":85,"path":86,"stem":87,"children":88,"page":25},"API Reference","i-lucide-file-code","/api","4.api",[89,94,98,101],{"title":90,"path":91,"stem":92,"icon":93},"Engine","/api/engine","4.api/1.engine","i-lucide-cog",{"title":95,"path":96,"stem":97,"icon":41},"Collection","/api/collection","4.api/2.collection",{"title":33,"path":99,"stem":100,"icon":36},"/api/models","4.api/3.models",{"title":102,"path":103,"stem":104,"icon":105},"Exceptions","/api/exceptions","4.api/4.exceptions","i-lucide-alert-triangle",{"id":107,"title":33,"body":108,"description":1599,"extension":1600,"links":1601,"meta":1602,"navigation":1603,"path":34,"seo":1604,"stem":35,"__hash__":1605},"docs/2.essentials/1.models.md",{"type":109,"value":110,"toc":1583},"minimark",[111,115,120,132,254,261,265,268,474,482,486,493,727,735,739,745,795,798,883,904,908,917,984,992,1069,1089,1107,1242,1248,1251,1254,1319,1330,1334,1337,1466,1473,1483,1487,1495,1579],[112,113,114],"p",{},"Every piece of data in CentauroDB is a Pydantic model. You define your schema as a Python class, and CentauroDB handles the rest — serialization, storage, versioning, and deserialization. This guide covers how to define models correctly and which base class to choose.",[116,117,119],"h2",{"id":118},"defining-your-first-model","Defining your first model",[112,121,122,123,127,128,131],{},"Inherit from ",[124,125,126],"code",{},"CentauroModel"," and set a ",[124,129,130],{},"__centauro_name__",":",[133,134,139],"pre",{"className":135,"code":136,"language":137,"meta":138,"style":138},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","from centaurodb import CentauroModel\n\nclass Sensor(CentauroModel):\n    __centauro_name__ = \"Sensor\"\n    unit: str = \"\"\n    location: str = \"\"\n    threshold: float = 100.0\n","python","",[124,140,141,160,167,187,206,223,237],{"__ignoreMap":138},[142,143,146,150,154,157],"span",{"class":144,"line":145},"line",1,[142,147,149],{"class":148},"s7zQu","from",[142,151,153],{"class":152},"sTEyZ"," centaurodb ",[142,155,156],{"class":148},"import",[142,158,159],{"class":152}," CentauroModel\n",[142,161,163],{"class":144,"line":162},2,[142,164,166],{"emptyLinePlaceholder":165},true,"\n",[142,168,170,174,178,182,184],{"class":144,"line":169},3,[142,171,173],{"class":172},"spNyl","class",[142,175,177],{"class":176},"sBMFI"," Sensor",[142,179,181],{"class":180},"sMK4o","(",[142,183,126],{"class":176},[142,185,186],{"class":180},"):\n",[142,188,190,193,196,199,203],{"class":144,"line":189},4,[142,191,192],{"class":152},"    __centauro_name__ ",[142,194,195],{"class":180},"=",[142,197,198],{"class":180}," \"",[142,200,202],{"class":201},"sfazB","Sensor",[142,204,205],{"class":180},"\"\n",[142,207,209,212,214,217,220],{"class":144,"line":208},5,[142,210,211],{"class":152},"    unit",[142,213,131],{"class":180},[142,215,216],{"class":176}," str",[142,218,219],{"class":180}," =",[142,221,222],{"class":180}," \"\"\n",[142,224,226,229,231,233,235],{"class":144,"line":225},6,[142,227,228],{"class":152},"    location",[142,230,131],{"class":180},[142,232,216],{"class":176},[142,234,219],{"class":180},[142,236,222],{"class":180},[142,238,240,243,245,248,250],{"class":144,"line":239},7,[142,241,242],{"class":152},"    threshold",[142,244,131],{"class":180},[142,246,247],{"class":176}," float",[142,249,219],{"class":180},[142,251,253],{"class":252},"sbssI"," 100.0\n",[112,255,256,257,260],{},"That's it — this model is ready to be stored in a ",[258,259,95],"a",{"href":39},".",[116,262,264],{"id":263},"the-three-rules","The three rules",[112,266,267],{},"CentauroDB enforces three constraints at class-definition time. Break any of them and you get a clear error immediately — not a runtime surprise weeks later.",[269,270,271,278,289,350,354,361,461,468],"steps",{},[272,273,275,276],"h3",{"id":274},"every-model-needs-a-__centauro_name__","Every model needs a ",[124,277,130],{},[112,279,280,281,284,285,288],{},"This ",[124,282,283],{},"ClassVar[str]"," is the model's stable identity in the database — it's stored in the ",[124,286,287],{},"name"," column and used to filter rows in views and name-based queries. Without it, renaming a Python class would silently change the stored name, causing views to miss old rows with no error or warning.",[133,290,292],{"className":135,"code":291,"language":137,"meta":138,"style":138},"class SensorReading(CentauroModel):\n    __centauro_name__ = \"Sensor\"   # DB identity stays \"Sensor\"\n    unit: str = \"\"\n\n# Even after renaming the class, old rows still match\n# because __centauro_name__ hasn't changed\n",[124,293,294,307,324,336,340,345],{"__ignoreMap":138},[142,295,296,298,301,303,305],{"class":144,"line":145},[142,297,173],{"class":172},[142,299,300],{"class":176}," SensorReading",[142,302,181],{"class":180},[142,304,126],{"class":176},[142,306,186],{"class":180},[142,308,309,311,313,315,317,320],{"class":144,"line":162},[142,310,192],{"class":152},[142,312,195],{"class":180},[142,314,198],{"class":180},[142,316,202],{"class":201},[142,318,319],{"class":180},"\"",[142,321,323],{"class":322},"sHwdD","   # DB identity stays \"Sensor\"\n",[142,325,326,328,330,332,334],{"class":144,"line":169},[142,327,211],{"class":152},[142,329,131],{"class":180},[142,331,216],{"class":176},[142,333,219],{"class":180},[142,335,222],{"class":180},[142,337,338],{"class":144,"line":189},[142,339,166],{"emptyLinePlaceholder":165},[142,341,342],{"class":144,"line":208},[142,343,344],{"class":322},"# Even after renaming the class, old rows still match\n",[142,346,347],{"class":144,"line":225},[142,348,349],{"class":322},"# because __centauro_name__ hasn't changed\n",[272,351,353],{"id":352},"all-fields-must-have-defaults","All fields must have defaults",[112,355,356,357,360],{},"Without defaults, old rows that lack a new field would fail to load. Defaults make adding fields safe — old data simply gets the default value on read. A field without a default raises ",[124,358,359],{},"TypeError"," at class definition time.",[133,362,364],{"className":135,"code":363,"language":137,"meta":138,"style":138},"class Sensor(CentauroModel):\n    __centauro_name__ = \"Sensor\"\n    unit: str = \"\"              # OK — default = \"\"\n    location: str = \"unknown\"   # OK — default = \"unknown\"\n    pages: int | None = None    # OK — Optional with None\n    rating: float               # TypeError at class definition\n",[124,365,366,378,390,406,426,449],{"__ignoreMap":138},[142,367,368,370,372,374,376],{"class":144,"line":145},[142,369,173],{"class":172},[142,371,177],{"class":176},[142,373,181],{"class":180},[142,375,126],{"class":176},[142,377,186],{"class":180},[142,379,380,382,384,386,388],{"class":144,"line":162},[142,381,192],{"class":152},[142,383,195],{"class":180},[142,385,198],{"class":180},[142,387,202],{"class":201},[142,389,205],{"class":180},[142,391,392,394,396,398,400,403],{"class":144,"line":169},[142,393,211],{"class":152},[142,395,131],{"class":180},[142,397,216],{"class":176},[142,399,219],{"class":180},[142,401,402],{"class":180}," \"\"",[142,404,405],{"class":322},"              # OK — default = \"\"\n",[142,407,408,410,412,414,416,418,421,423],{"class":144,"line":189},[142,409,228],{"class":152},[142,411,131],{"class":180},[142,413,216],{"class":176},[142,415,219],{"class":180},[142,417,198],{"class":180},[142,419,420],{"class":201},"unknown",[142,422,319],{"class":180},[142,424,425],{"class":322},"   # OK — default = \"unknown\"\n",[142,427,428,431,433,436,439,442,444,446],{"class":144,"line":208},[142,429,430],{"class":152},"    pages",[142,432,131],{"class":180},[142,434,435],{"class":176}," int",[142,437,438],{"class":180}," |",[142,440,441],{"class":180}," None",[142,443,219],{"class":180},[142,445,441],{"class":180},[142,447,448],{"class":322},"    # OK — Optional with None\n",[142,450,451,454,456,458],{"class":144,"line":225},[142,452,453],{"class":152},"    rating",[142,455,131],{"class":180},[142,457,247],{"class":176},[142,459,460],{"class":322},"               # TypeError at class definition\n",[272,462,464,467],{"id":463},"extraforbid-is-banned",[124,465,466],{},"extra=\"forbid\""," is banned",[112,469,470,471,473],{},"Old rows may contain fields that no longer exist in your current model. Pydantic needs to silently ignore them, so ",[124,472,466],{}," would cause read failures. CentauroDB rejects it at class definition time.",[475,476,477,478,481],"callout",{"icon":14},"These three rules are what make ",[258,479,480],{"href":49},"zero-migration schema evolution"," possible. They're validated when Python loads your class, so mistakes surface immediately.",[116,483,485],{"id":484},"working-with-stored-objects","Working with stored objects",[112,487,488,489,492],{},"After writing or reading an object, it carries database metadata in the ",[124,490,491],{},"row"," attribute:",[133,494,496],{"className":135,"code":495,"language":137,"meta":138,"style":138},"from centaurodb import Engine, Collection\n\nengine = Engine(\"monitoring.db\")\ncoll = Collection(engine, \"monitoring\")\n\nobj = Sensor(unit=\"Celsius\", location=\"pelion\")\ncoll.write_object(obj)\n\nprint(obj.row.id)          # int — auto-incremented primary key\nprint(obj.row.name)        # \"Sensor\" — the __centauro_name__\nprint(obj.row.write_time)  # datetime — when first written\nprint(obj.row.edit_time)   # datetime — when last updated\n",[124,497,498,515,519,541,567,571,611,628,633,659,681,704],{"__ignoreMap":138},[142,499,500,502,504,506,509,512],{"class":144,"line":145},[142,501,149],{"class":148},[142,503,153],{"class":152},[142,505,156],{"class":148},[142,507,508],{"class":152}," Engine",[142,510,511],{"class":180},",",[142,513,514],{"class":152}," Collection\n",[142,516,517],{"class":144,"line":162},[142,518,166],{"emptyLinePlaceholder":165},[142,520,521,524,526,529,531,533,536,538],{"class":144,"line":169},[142,522,523],{"class":152},"engine ",[142,525,195],{"class":180},[142,527,508],{"class":528},"s2Zo4",[142,530,181],{"class":180},[142,532,319],{"class":180},[142,534,535],{"class":201},"monitoring.db",[142,537,319],{"class":180},[142,539,540],{"class":180},")\n",[142,542,543,546,548,551,553,556,558,560,563,565],{"class":144,"line":189},[142,544,545],{"class":152},"coll ",[142,547,195],{"class":180},[142,549,550],{"class":528}," Collection",[142,552,181],{"class":180},[142,554,555],{"class":528},"engine",[142,557,511],{"class":180},[142,559,198],{"class":180},[142,561,562],{"class":201},"monitoring",[142,564,319],{"class":180},[142,566,540],{"class":180},[142,568,569],{"class":144,"line":208},[142,570,166],{"emptyLinePlaceholder":165},[142,572,573,576,578,580,582,586,588,590,593,595,597,600,602,604,607,609],{"class":144,"line":225},[142,574,575],{"class":152},"obj ",[142,577,195],{"class":180},[142,579,177],{"class":528},[142,581,181],{"class":180},[142,583,585],{"class":584},"sHdIc","unit",[142,587,195],{"class":180},[142,589,319],{"class":180},[142,591,592],{"class":201},"Celsius",[142,594,319],{"class":180},[142,596,511],{"class":180},[142,598,599],{"class":584}," location",[142,601,195],{"class":180},[142,603,319],{"class":180},[142,605,606],{"class":201},"pelion",[142,608,319],{"class":180},[142,610,540],{"class":180},[142,612,613,616,618,621,623,626],{"class":144,"line":239},[142,614,615],{"class":152},"coll",[142,617,260],{"class":180},[142,619,620],{"class":528},"write_object",[142,622,181],{"class":180},[142,624,625],{"class":528},"obj",[142,627,540],{"class":180},[142,629,631],{"class":144,"line":630},8,[142,632,166],{"emptyLinePlaceholder":165},[142,634,636,639,641,643,645,648,650,653,656],{"class":144,"line":635},9,[142,637,638],{"class":528},"print",[142,640,181],{"class":180},[142,642,625],{"class":528},[142,644,260],{"class":180},[142,646,491],{"class":647},"swJcz",[142,649,260],{"class":180},[142,651,652],{"class":647},"id",[142,654,655],{"class":180},")",[142,657,658],{"class":322},"          # int — auto-incremented primary key\n",[142,660,662,664,666,668,670,672,674,676,678],{"class":144,"line":661},10,[142,663,638],{"class":528},[142,665,181],{"class":180},[142,667,625],{"class":528},[142,669,260],{"class":180},[142,671,491],{"class":647},[142,673,260],{"class":180},[142,675,287],{"class":647},[142,677,655],{"class":180},[142,679,680],{"class":322},"        # \"Sensor\" — the __centauro_name__\n",[142,682,684,686,688,690,692,694,696,699,701],{"class":144,"line":683},11,[142,685,638],{"class":528},[142,687,181],{"class":180},[142,689,625],{"class":528},[142,691,260],{"class":180},[142,693,491],{"class":647},[142,695,260],{"class":180},[142,697,698],{"class":647},"write_time",[142,700,655],{"class":180},[142,702,703],{"class":322},"  # datetime — when first written\n",[142,705,707,709,711,713,715,717,719,722,724],{"class":144,"line":706},12,[142,708,638],{"class":528},[142,710,181],{"class":180},[142,712,625],{"class":528},[142,714,260],{"class":180},[142,716,491],{"class":647},[142,718,260],{"class":180},[142,720,721],{"class":647},"edit_time",[142,723,655],{"class":180},[142,725,726],{"class":322},"   # datetime — when last updated\n",[112,728,729,730,734],{},"See ",[258,731,733],{"href":732},"/api/models#rowfields","RowFields API"," for the complete field list.",[116,736,738],{"id":737},"validation-on-assignment","Validation on assignment",[112,740,741,742,744],{},"By default, ",[124,743,126],{}," validates field values whenever you set an attribute. This catches type errors early:",[133,746,748],{"className":135,"code":747,"language":137,"meta":138,"style":138},"sensor = Sensor(unit=\"Celsius\")\nsensor.threshold = \"oops\"  # raises ValidationError immediately\n",[124,749,750,773],{"__ignoreMap":138},[142,751,752,755,757,759,761,763,765,767,769,771],{"class":144,"line":145},[142,753,754],{"class":152},"sensor ",[142,756,195],{"class":180},[142,758,177],{"class":528},[142,760,181],{"class":180},[142,762,585],{"class":584},[142,764,195],{"class":180},[142,766,319],{"class":180},[142,768,592],{"class":201},[142,770,319],{"class":180},[142,772,540],{"class":180},[142,774,775,778,780,783,785,787,790,792],{"class":144,"line":162},[142,776,777],{"class":152},"sensor",[142,779,260],{"class":180},[142,781,782],{"class":647},"threshold",[142,784,219],{"class":180},[142,786,198],{"class":180},[142,788,789],{"class":201},"oops",[142,791,319],{"class":180},[142,793,794],{"class":322},"  # raises ValidationError immediately\n",[112,796,797],{},"For performance-critical code (e.g., ingesting thousands of objects in a tight loop), you can opt out:",[133,799,801],{"className":135,"code":800,"language":137,"meta":138,"style":138},"from pydantic import ConfigDict\n\nclass FastSensor(CentauroModel):\n    __centauro_name__ = \"FastSensor\"\n    model_config = ConfigDict(validate_assignment=False, populate_by_name=True)\n    value: float = 0.0\n",[124,802,803,815,819,832,845,869],{"__ignoreMap":138},[142,804,805,807,810,812],{"class":144,"line":145},[142,806,149],{"class":148},[142,808,809],{"class":152}," pydantic ",[142,811,156],{"class":148},[142,813,814],{"class":152}," ConfigDict\n",[142,816,817],{"class":144,"line":162},[142,818,166],{"emptyLinePlaceholder":165},[142,820,821,823,826,828,830],{"class":144,"line":169},[142,822,173],{"class":172},[142,824,825],{"class":176}," FastSensor",[142,827,181],{"class":180},[142,829,126],{"class":176},[142,831,186],{"class":180},[142,833,834,836,838,840,843],{"class":144,"line":189},[142,835,192],{"class":152},[142,837,195],{"class":180},[142,839,198],{"class":180},[142,841,842],{"class":201},"FastSensor",[142,844,205],{"class":180},[142,846,847,850,852,855,857,860,863,866],{"class":144,"line":208},[142,848,849],{"class":152},"    model_config ",[142,851,195],{"class":180},[142,853,854],{"class":528}," ConfigDict",[142,856,181],{"class":180},[142,858,859],{"class":584},"validate_assignment",[142,861,862],{"class":180},"=False,",[142,864,865],{"class":584}," populate_by_name",[142,867,868],{"class":180},"=True)\n",[142,870,871,874,876,878,880],{"class":144,"line":225},[142,872,873],{"class":152},"    value",[142,875,131],{"class":180},[142,877,247],{"class":176},[142,879,219],{"class":180},[142,881,882],{"class":252}," 0.0\n",[884,885,886,887,890,891,894,895,898,899,903],"warning",{},"Always include ",[124,888,889],{},"populate_by_name=True"," when overriding ",[124,892,893],{},"model_config",". Omitting it breaks ",[124,896,897],{},"renamed_from()"," — see the ",[258,900,902],{"href":901},"/advanced/performance#disable-assignment-validation-for-hot-paths","Performance guide"," for details.",[116,905,907],{"id":906},"choosing-between-centauromodel-and-centauromodelseries","Choosing between CentauroModel and CentauroModelSeries",[112,909,910,911,916],{},"Use ",[912,913,914],"strong",{},[124,915,126],{}," when your objects represent entities with metadata only — configuration, records, documents, settings:",[133,918,920],{"className":135,"code":919,"language":137,"meta":138,"style":138},"class Config(CentauroModel):\n    __centauro_name__ = \"Config\"\n    theme: str = \"dark\"\n    language: str = \"en\"\n",[124,921,922,935,948,966],{"__ignoreMap":138},[142,923,924,926,929,931,933],{"class":144,"line":145},[142,925,173],{"class":172},[142,927,928],{"class":176}," Config",[142,930,181],{"class":180},[142,932,126],{"class":176},[142,934,186],{"class":180},[142,936,937,939,941,943,946],{"class":144,"line":162},[142,938,192],{"class":152},[142,940,195],{"class":180},[142,942,198],{"class":180},[142,944,945],{"class":201},"Config",[142,947,205],{"class":180},[142,949,950,953,955,957,959,961,964],{"class":144,"line":169},[142,951,952],{"class":152},"    theme",[142,954,131],{"class":180},[142,956,216],{"class":176},[142,958,219],{"class":180},[142,960,198],{"class":180},[142,962,963],{"class":201},"dark",[142,965,205],{"class":180},[142,967,968,971,973,975,977,979,982],{"class":144,"line":189},[142,969,970],{"class":152},"    language",[142,972,131],{"class":180},[142,974,216],{"class":176},[142,976,219],{"class":180},[142,978,198],{"class":180},[142,980,981],{"class":201},"en",[142,983,205],{"class":180},[112,985,910,986,991],{},[912,987,988],{},[124,989,990],{},"CentauroModelSeries"," when each object also carries a series of timestamped numeric values — sensor readings, stock prices, metrics:",[133,993,995],{"className":135,"code":994,"language":137,"meta":138,"style":138},"from centaurodb import CentauroModelSeries, CentauroValues\n\nclass WeatherStation(CentauroModelSeries):\n    __centauro_name__ = \"WeatherStation\"\n    city: str = \"\"\n    elevation: float = 0.0\n",[124,996,997,1013,1017,1030,1043,1056],{"__ignoreMap":138},[142,998,999,1001,1003,1005,1008,1010],{"class":144,"line":145},[142,1000,149],{"class":148},[142,1002,153],{"class":152},[142,1004,156],{"class":148},[142,1006,1007],{"class":152}," CentauroModelSeries",[142,1009,511],{"class":180},[142,1011,1012],{"class":152}," CentauroValues\n",[142,1014,1015],{"class":144,"line":162},[142,1016,166],{"emptyLinePlaceholder":165},[142,1018,1019,1021,1024,1026,1028],{"class":144,"line":169},[142,1020,173],{"class":172},[142,1022,1023],{"class":176}," WeatherStation",[142,1025,181],{"class":180},[142,1027,990],{"class":176},[142,1029,186],{"class":180},[142,1031,1032,1034,1036,1038,1041],{"class":144,"line":189},[142,1033,192],{"class":152},[142,1035,195],{"class":180},[142,1037,198],{"class":180},[142,1039,1040],{"class":201},"WeatherStation",[142,1042,205],{"class":180},[142,1044,1045,1048,1050,1052,1054],{"class":144,"line":208},[142,1046,1047],{"class":152},"    city",[142,1049,131],{"class":180},[142,1051,216],{"class":176},[142,1053,219],{"class":180},[142,1055,222],{"class":180},[142,1057,1058,1061,1063,1065,1067],{"class":144,"line":225},[142,1059,1060],{"class":152},"    elevation",[142,1062,131],{"class":180},[142,1064,247],{"class":176},[142,1066,219],{"class":180},[142,1068,882],{"class":252},[112,1070,1071,1073,1074,1076,1077,1080,1081,1084,1085,1088],{},[124,1072,990],{}," extends ",[124,1075,126],{}," with a ",[124,1078,1079],{},"values"," list and a ",[124,1082,1083],{},".df"," property for Polars DataFrame access. Each instance tracks ",[912,1086,1087],{},"one"," measurement series. Metadata lives in JSON, values live in a separate normalized table.",[112,1090,1091,1092,1094,1095,1098,1099,1102,1103,1106],{},"The ",[124,1093,1079],{}," field accepts either a list of ",[124,1096,1097],{},"CentauroValues"," or a Polars DataFrame with ",[124,1100,1101],{},"time"," and ",[124,1104,1105],{},"value"," columns:",[133,1108,1110],{"className":135,"code":1109,"language":137,"meta":138,"style":138},"import polars as pl\n\ndf = pl.DataFrame({\n    \"time\": [\"2025-06-01T08:00:00\", \"2025-06-01T09:00:00\"],\n    \"value\": [22.5, 24.1],\n})\nstation = WeatherStation(city=\"Sparta\", values=df)\n",[124,1111,1112,1125,1129,1147,1180,1202,1207],{"__ignoreMap":138},[142,1113,1114,1116,1119,1122],{"class":144,"line":145},[142,1115,156],{"class":148},[142,1117,1118],{"class":152}," polars ",[142,1120,1121],{"class":148},"as",[142,1123,1124],{"class":152}," pl\n",[142,1126,1127],{"class":144,"line":162},[142,1128,166],{"emptyLinePlaceholder":165},[142,1130,1131,1134,1136,1139,1141,1144],{"class":144,"line":169},[142,1132,1133],{"class":152},"df ",[142,1135,195],{"class":180},[142,1137,1138],{"class":152}," pl",[142,1140,260],{"class":180},[142,1142,1143],{"class":528},"DataFrame",[142,1145,1146],{"class":180},"({\n",[142,1148,1149,1152,1154,1156,1158,1161,1163,1166,1168,1170,1172,1175,1177],{"class":144,"line":189},[142,1150,1151],{"class":180},"    \"",[142,1153,1101],{"class":201},[142,1155,319],{"class":180},[142,1157,131],{"class":180},[142,1159,1160],{"class":180}," [",[142,1162,319],{"class":180},[142,1164,1165],{"class":201},"2025-06-01T08:00:00",[142,1167,319],{"class":180},[142,1169,511],{"class":180},[142,1171,198],{"class":180},[142,1173,1174],{"class":201},"2025-06-01T09:00:00",[142,1176,319],{"class":180},[142,1178,1179],{"class":180},"],\n",[142,1181,1182,1184,1186,1188,1190,1192,1195,1197,1200],{"class":144,"line":208},[142,1183,1151],{"class":180},[142,1185,1105],{"class":201},[142,1187,319],{"class":180},[142,1189,131],{"class":180},[142,1191,1160],{"class":180},[142,1193,1194],{"class":252},"22.5",[142,1196,511],{"class":180},[142,1198,1199],{"class":252}," 24.1",[142,1201,1179],{"class":180},[142,1203,1204],{"class":144,"line":225},[142,1205,1206],{"class":180},"})\n",[142,1208,1209,1212,1214,1216,1218,1221,1223,1225,1228,1230,1232,1235,1237,1240],{"class":144,"line":239},[142,1210,1211],{"class":152},"station ",[142,1213,195],{"class":180},[142,1215,1023],{"class":528},[142,1217,181],{"class":180},[142,1219,1220],{"class":584},"city",[142,1222,195],{"class":180},[142,1224,319],{"class":180},[142,1226,1227],{"class":201},"Sparta",[142,1229,319],{"class":180},[142,1231,511],{"class":180},[142,1233,1234],{"class":584}," values",[142,1236,195],{"class":180},[142,1238,1239],{"class":528},"df",[142,1241,540],{"class":180},[475,1243,729,1245,1247],{"icon":1244},"i-lucide-arrow-right",[258,1246,64],{"href":65}," for the complete guide on writing values, update modes, and Polars integration.",[116,1249,1097],{"id":1250},"centaurovalues",[112,1252,1253],{},"A single time-series data point with two fields:",[133,1255,1257],{"className":135,"code":1256,"language":137,"meta":138,"style":138},"from centaurodb import CentauroValues\n\npoint = CentauroValues(\n    time=\"2025-06-01T08:00:00\",  # ISO timestamp (auto-coerced by Pydantic)\n    value=22.5                   # numeric value\n)\n",[124,1258,1259,1269,1273,1286,1304,1315],{"__ignoreMap":138},[142,1260,1261,1263,1265,1267],{"class":144,"line":145},[142,1262,149],{"class":148},[142,1264,153],{"class":152},[142,1266,156],{"class":148},[142,1268,1012],{"class":152},[142,1270,1271],{"class":144,"line":162},[142,1272,166],{"emptyLinePlaceholder":165},[142,1274,1275,1278,1280,1283],{"class":144,"line":169},[142,1276,1277],{"class":152},"point ",[142,1279,195],{"class":180},[142,1281,1282],{"class":528}," CentauroValues",[142,1284,1285],{"class":180},"(\n",[142,1287,1288,1291,1293,1295,1297,1299,1301],{"class":144,"line":189},[142,1289,1290],{"class":584},"    time",[142,1292,195],{"class":180},[142,1294,319],{"class":180},[142,1296,1165],{"class":201},[142,1298,319],{"class":180},[142,1300,511],{"class":180},[142,1302,1303],{"class":322},"  # ISO timestamp (auto-coerced by Pydantic)\n",[142,1305,1306,1308,1310,1312],{"class":144,"line":208},[142,1307,873],{"class":584},[142,1309,195],{"class":180},[142,1311,1194],{"class":252},[142,1313,1314],{"class":322},"                   # numeric value\n",[142,1316,1317],{"class":144,"line":225},[142,1318,540],{"class":180},[112,1320,1321,1322,1325,1326,1329],{},"If you need multiple series per entity (e.g., temperature ",[912,1323,1324],{},"and"," humidity for the same station), create a separate subclass and object for each. The combination of ",[124,1327,1328],{},"(object_id, time)"," forms the composite primary key in the values table.",[116,1331,1333],{"id":1332},"nested-models","Nested models",[112,1335,1336],{},"Not all related data needs its own collection entry. If the nested data is small, bounded, and always loaded with its parent, embed it as a plain Pydantic model inside the JSON blob:",[133,1338,1340],{"className":135,"code":1339,"language":137,"meta":138,"style":138},"from pydantic import BaseModel\n\nclass Preferences(BaseModel):\n    theme: str = \"dark\"\n    language: str = \"en\"\n\nclass User(CentauroModel):\n    __centauro_name__ = \"User\"\n    name: str = \"\"\n    prefs: Preferences = Preferences()   # embedded in the parent's JSON\n",[124,1341,1342,1353,1357,1371,1387,1403,1407,1420,1433,1446],{"__ignoreMap":138},[142,1343,1344,1346,1348,1350],{"class":144,"line":145},[142,1345,149],{"class":148},[142,1347,809],{"class":152},[142,1349,156],{"class":148},[142,1351,1352],{"class":152}," BaseModel\n",[142,1354,1355],{"class":144,"line":162},[142,1356,166],{"emptyLinePlaceholder":165},[142,1358,1359,1361,1364,1366,1369],{"class":144,"line":169},[142,1360,173],{"class":172},[142,1362,1363],{"class":176}," Preferences",[142,1365,181],{"class":180},[142,1367,1368],{"class":176},"BaseModel",[142,1370,186],{"class":180},[142,1372,1373,1375,1377,1379,1381,1383,1385],{"class":144,"line":189},[142,1374,952],{"class":152},[142,1376,131],{"class":180},[142,1378,216],{"class":176},[142,1380,219],{"class":180},[142,1382,198],{"class":180},[142,1384,963],{"class":201},[142,1386,205],{"class":180},[142,1388,1389,1391,1393,1395,1397,1399,1401],{"class":144,"line":208},[142,1390,970],{"class":152},[142,1392,131],{"class":180},[142,1394,216],{"class":176},[142,1396,219],{"class":180},[142,1398,198],{"class":180},[142,1400,981],{"class":201},[142,1402,205],{"class":180},[142,1404,1405],{"class":144,"line":225},[142,1406,166],{"emptyLinePlaceholder":165},[142,1408,1409,1411,1414,1416,1418],{"class":144,"line":239},[142,1410,173],{"class":172},[142,1412,1413],{"class":176}," User",[142,1415,181],{"class":180},[142,1417,126],{"class":176},[142,1419,186],{"class":180},[142,1421,1422,1424,1426,1428,1431],{"class":144,"line":630},[142,1423,192],{"class":152},[142,1425,195],{"class":180},[142,1427,198],{"class":180},[142,1429,1430],{"class":201},"User",[142,1432,205],{"class":180},[142,1434,1435,1438,1440,1442,1444],{"class":144,"line":635},[142,1436,1437],{"class":152},"    name",[142,1439,131],{"class":180},[142,1441,216],{"class":176},[142,1443,219],{"class":180},[142,1445,222],{"class":180},[142,1447,1448,1451,1453,1456,1458,1460,1463],{"class":144,"line":661},[142,1449,1450],{"class":152},"    prefs",[142,1452,131],{"class":180},[142,1454,1455],{"class":152}," Preferences ",[142,1457,195],{"class":180},[142,1459,1363],{"class":528},[142,1461,1462],{"class":180},"()",[142,1464,1465],{"class":322},"   # embedded in the parent's JSON\n",[112,1467,1468,1469,1472],{},"When the child needs its own lifecycle — independent queries, growing over time, visible in views — use ",[124,1470,1471],{},"parent_ref"," instead.",[475,1474,729,1475,1482],{"icon":1244},[258,1476,1478,1479,1481],{"href":1477},"/essentials/relations#parent_ref-vs-nested-models","Relations — ",[124,1480,1471],{}," vs nested models"," for a detailed comparison and rules of thumb.",[116,1484,1486],{"id":1485},"renaming-fields-safely","Renaming fields safely",[112,1488,910,1489,1491,1492,1494],{},[124,1490,897],{}," when you need to rename a field without breaking old data. See ",[258,1493,48],{"href":49}," for the full guide.",[133,1496,1498],{"className":135,"code":1497,"language":137,"meta":138,"style":138},"from centaurodb import renamed_from\n\nclass Sensor(CentauroModel):\n    __centauro_name__ = \"Sensor\"\n    temperature: float = renamed_from(\"temp\", default=0.0)\n    # Old JSON {\"temp\": 42.0} reads correctly as temperature=42.0\n",[124,1499,1500,1511,1515,1527,1539,1574],{"__ignoreMap":138},[142,1501,1502,1504,1506,1508],{"class":144,"line":145},[142,1503,149],{"class":148},[142,1505,153],{"class":152},[142,1507,156],{"class":148},[142,1509,1510],{"class":152}," renamed_from\n",[142,1512,1513],{"class":144,"line":162},[142,1514,166],{"emptyLinePlaceholder":165},[142,1516,1517,1519,1521,1523,1525],{"class":144,"line":169},[142,1518,173],{"class":172},[142,1520,177],{"class":176},[142,1522,181],{"class":180},[142,1524,126],{"class":176},[142,1526,186],{"class":180},[142,1528,1529,1531,1533,1535,1537],{"class":144,"line":189},[142,1530,192],{"class":152},[142,1532,195],{"class":180},[142,1534,198],{"class":180},[142,1536,202],{"class":201},[142,1538,205],{"class":180},[142,1540,1541,1544,1546,1548,1550,1553,1555,1557,1560,1562,1564,1567,1569,1572],{"class":144,"line":208},[142,1542,1543],{"class":152},"    temperature",[142,1545,131],{"class":180},[142,1547,247],{"class":176},[142,1549,219],{"class":180},[142,1551,1552],{"class":528}," renamed_from",[142,1554,181],{"class":180},[142,1556,319],{"class":180},[142,1558,1559],{"class":201},"temp",[142,1561,319],{"class":180},[142,1563,511],{"class":180},[142,1565,1566],{"class":584}," default",[142,1568,195],{"class":180},[142,1570,1571],{"class":252},"0.0",[142,1573,540],{"class":180},[142,1575,1576],{"class":144,"line":225},[142,1577,1578],{"class":322},"    # Old JSON {\"temp\": 42.0} reads correctly as temperature=42.0\n",[1580,1581,1582],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":138,"searchDepth":162,"depth":162,"links":1584},[1585,1586,1593,1594,1595,1596,1597,1598],{"id":118,"depth":162,"text":119},{"id":263,"depth":162,"text":264,"children":1587},[1588,1590,1591],{"id":274,"depth":169,"text":1589},"Every model needs a __centauro_name__",{"id":352,"depth":169,"text":353},{"id":463,"depth":169,"text":1592},"extra=\"forbid\" is banned",{"id":484,"depth":162,"text":485},{"id":737,"depth":162,"text":738},{"id":906,"depth":162,"text":907},{"id":1250,"depth":162,"text":1097},{"id":1332,"depth":162,"text":1333},{"id":1485,"depth":162,"text":1486},"Define your data with CentauroModel and CentauroModelSeries — the foundation of CentauroDB.","md",null,{},{"icon":36},{"title":33,"description":1599},"z_jrpFmj6np78Z6zwNXtPPrEna8S1l6B5XGuIV26QUI",[1607,1609],{"title":21,"path":22,"stem":23,"description":1608,"icon":24,"children":-1},"Build a working app with CentauroDB in under 5 minutes — define, store, query, evolve.",{"title":38,"path":39,"stem":40,"description":1610,"icon":41,"children":-1},"Store, read, update, and query your models with Collection and TimeSeriesCollection.",1781105060350]