[{"data":1,"prerenderedAt":814},["ShallowReactive",2],{"navigation":3,"\u002Fguides\u002Frelations":103,"\u002Fguides\u002Frelations-surround":809},[4,9,31,87,98],{"title":5,"path":6,"stem":7,"icon":8},"Getting started","\u002Fgetting-started","01.getting-started","i-tabler-rocket",{"title":10,"icon":11,"path":12,"stem":13,"children":14,"page":30},"Concepts","i-tabler-code","\u002Fconcepts","02.concepts",[15,20,25],{"title":16,"path":17,"stem":18,"icon":19},"Architecture","\u002Fconcepts\u002Farchitecture","02.concepts\u002Farchitecture","i-tabler-sitemap",{"title":21,"path":22,"stem":23,"icon":24},"Metadata and registry","\u002Fconcepts\u002Fmetadata-and-registry","02.concepts\u002Fmetadata-and-registry","i-tabler-schema",{"title":26,"path":27,"stem":28,"icon":29},"Query Engine","\u002Fconcepts\u002Fquery-engine","02.concepts\u002Fquery-engine","i-tabler-engine",false,{"title":32,"icon":33,"path":34,"stem":35,"children":36,"page":30},"Guide","i-tabler-arrow-ramp-right","\u002Fguides","03.guides",[37,42,47,52,57,62,67,72,77,82],{"title":38,"path":39,"stem":40,"icon":41},"Audit Log","\u002Fguides\u002Faudit-log","03.guides\u002Faudit-log","i-tabler-history",{"title":43,"path":44,"stem":45,"icon":46},"Cursor pagination","\u002Fguides\u002Fcursor-pagination","03.guides\u002Fcursor-pagination","i-tabler-arrow-bar-to-down",{"title":48,"path":49,"stem":50,"icon":51},"Domain Events","\u002Fguides\u002Fdomain-events","03.guides\u002Fdomain-events","i-tabler-broadcast",{"title":53,"path":54,"stem":55,"icon":56},"Field visibility","\u002Fguides\u002Ffield-visibility","03.guides\u002Ffield-visibility","i-tabler-eye-off",{"title":58,"path":59,"stem":60,"icon":61},"Lifecycle hooks","\u002Fguides\u002Flifecycle-hooks","03.guides\u002Flifecycle-hooks","i-tabler-arrows-split",{"title":63,"path":64,"stem":65,"icon":66},"Production playground","\u002Fguides\u002Fplayground","03.guides\u002Fplayground","i-tabler-flask",{"title":68,"path":69,"stem":70,"icon":71},"Queries and filters","\u002Fguides\u002Fqueries-and-filters","03.guides\u002Fqueries-and-filters","i-tabler-filter",{"title":73,"path":74,"stem":75,"icon":76},"Relations","\u002Fguides\u002Frelations","03.guides\u002Frelations","i-tabler-link",{"title":78,"path":79,"stem":80,"icon":81},"Schema consistency","\u002Fguides\u002Fschema-consistency","03.guides\u002Fschema-consistency","i-tabler-database-search",{"title":83,"path":84,"stem":85,"icon":86},"Validation","\u002Fguides\u002Fvalidation","03.guides\u002Fvalidation","i-tabler-checkup-list",{"title":88,"icon":89,"path":90,"stem":91,"children":92,"page":30},"Adapters","i-tabler-plug","\u002Fadapters","04.adapters",[93],{"title":94,"path":95,"stem":96,"icon":97},"Drizzle adapter","\u002Fadapters\u002Fdrizzle","04.adapters\u002Fdrizzle","i-simple-icons-drizzle",{"title":99,"path":100,"stem":101,"icon":102},"Current limitations","\u002Fcurrent-limitations","05.current-limitations","i-tabler-circle-dashed-x",{"id":104,"title":73,"body":105,"description":802,"extension":803,"links":804,"meta":805,"navigation":806,"path":74,"seo":807,"stem":75,"__hash__":808},"docs\u002F03.guides\u002Frelations.md",{"type":106,"value":107,"toc":793},"minimark",[108,117,122,236,242,246,331,334,338,421,430,434,585,588,613,616,697,707,727,731,734,743,756,760,763,782,789],[109,110,111,112,116],"p",{},"Relations belong to metadata. They do not create PostgreSQL foreign keys and are only loaded when requested through ",[113,114,115],"code",{},"populate",".",[118,119,121],"h2",{"id":120},"many-to-one","Many to one",[123,124,129],"pre",{"className":125,"code":126,"language":127,"meta":128,"style":128},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  name: 'owner',\n  kind: 'manyToOne',\n  target: 'users',\n  foreignKey: 'ownerId',\n  references: 'id'\n}\n","ts","",[113,130,131,140,163,180,197,214,230],{"__ignoreMap":128},[132,133,136],"span",{"class":134,"line":135},"line",1,[132,137,139],{"class":138},"sMK4o","{\n",[132,141,143,147,150,153,157,160],{"class":134,"line":142},2,[132,144,146],{"class":145},"sBMFI","  name",[132,148,149],{"class":138},":",[132,151,152],{"class":138}," '",[132,154,156],{"class":155},"sfazB","owner",[132,158,159],{"class":138},"'",[132,161,162],{"class":138},",\n",[132,164,166,169,171,173,176,178],{"class":134,"line":165},3,[132,167,168],{"class":145},"  kind",[132,170,149],{"class":138},[132,172,152],{"class":138},[132,174,175],{"class":155},"manyToOne",[132,177,159],{"class":138},[132,179,162],{"class":138},[132,181,183,186,188,190,193,195],{"class":134,"line":182},4,[132,184,185],{"class":145},"  target",[132,187,149],{"class":138},[132,189,152],{"class":138},[132,191,192],{"class":155},"users",[132,194,159],{"class":138},[132,196,162],{"class":138},[132,198,200,203,205,207,210,212],{"class":134,"line":199},5,[132,201,202],{"class":145},"  foreignKey",[132,204,149],{"class":138},[132,206,152],{"class":138},[132,208,209],{"class":155},"ownerId",[132,211,159],{"class":138},[132,213,162],{"class":138},[132,215,217,220,222,224,227],{"class":134,"line":216},6,[132,218,219],{"class":145},"  references",[132,221,149],{"class":138},[132,223,152],{"class":138},[132,225,226],{"class":155},"id",[132,228,229],{"class":138},"'\n",[132,231,233],{"class":134,"line":232},7,[132,234,235],{"class":138},"}\n",[109,237,238,239,241],{},"The source entity stores ",[113,240,209],{},". The resolver collects those values and loads matching target rows.",[118,243,245],{"id":244},"one-to-one","One to one",[123,247,249],{"className":125,"code":248,"language":127,"meta":128,"style":128},"{\n  name: 'profile',\n  kind: 'oneToOne',\n  target: 'profiles',\n  foreignKey: 'profileId',\n  references: 'id'\n}\n",[113,250,251,255,270,285,300,315,327],{"__ignoreMap":128},[132,252,253],{"class":134,"line":135},[132,254,139],{"class":138},[132,256,257,259,261,263,266,268],{"class":134,"line":142},[132,258,146],{"class":145},[132,260,149],{"class":138},[132,262,152],{"class":138},[132,264,265],{"class":155},"profile",[132,267,159],{"class":138},[132,269,162],{"class":138},[132,271,272,274,276,278,281,283],{"class":134,"line":165},[132,273,168],{"class":145},[132,275,149],{"class":138},[132,277,152],{"class":138},[132,279,280],{"class":155},"oneToOne",[132,282,159],{"class":138},[132,284,162],{"class":138},[132,286,287,289,291,293,296,298],{"class":134,"line":182},[132,288,185],{"class":145},[132,290,149],{"class":138},[132,292,152],{"class":138},[132,294,295],{"class":155},"profiles",[132,297,159],{"class":138},[132,299,162],{"class":138},[132,301,302,304,306,308,311,313],{"class":134,"line":199},[132,303,202],{"class":145},[132,305,149],{"class":138},[132,307,152],{"class":138},[132,309,310],{"class":155},"profileId",[132,312,159],{"class":138},[132,314,162],{"class":138},[132,316,317,319,321,323,325],{"class":134,"line":216},[132,318,219],{"class":145},[132,320,149],{"class":138},[132,322,152],{"class":138},[132,324,226],{"class":155},[132,326,229],{"class":138},[132,328,329],{"class":134,"line":232},[132,330,235],{"class":138},[109,332,333],{},"Resolution is the same as many-to-one, but the metadata expresses a different domain cardinality.",[118,335,337],{"id":336},"one-to-many","One to many",[123,339,341],{"className":125,"code":340,"language":127,"meta":128,"style":128},"{\n  name: 'projects',\n  kind: 'oneToMany',\n  target: 'projects',\n  foreignKey: 'ownerId',\n  references: 'id'\n}\n",[113,342,343,347,362,377,391,405,417],{"__ignoreMap":128},[132,344,345],{"class":134,"line":135},[132,346,139],{"class":138},[132,348,349,351,353,355,358,360],{"class":134,"line":142},[132,350,146],{"class":145},[132,352,149],{"class":138},[132,354,152],{"class":138},[132,356,357],{"class":155},"projects",[132,359,159],{"class":138},[132,361,162],{"class":138},[132,363,364,366,368,370,373,375],{"class":134,"line":165},[132,365,168],{"class":145},[132,367,149],{"class":138},[132,369,152],{"class":138},[132,371,372],{"class":155},"oneToMany",[132,374,159],{"class":138},[132,376,162],{"class":138},[132,378,379,381,383,385,387,389],{"class":134,"line":182},[132,380,185],{"class":145},[132,382,149],{"class":138},[132,384,152],{"class":138},[132,386,357],{"class":155},[132,388,159],{"class":138},[132,390,162],{"class":138},[132,392,393,395,397,399,401,403],{"class":134,"line":199},[132,394,202],{"class":145},[132,396,149],{"class":138},[132,398,152],{"class":138},[132,400,209],{"class":155},[132,402,159],{"class":138},[132,404,162],{"class":138},[132,406,407,409,411,413,415],{"class":134,"line":216},[132,408,219],{"class":145},[132,410,149],{"class":138},[132,412,152],{"class":138},[132,414,226],{"class":155},[132,416,229],{"class":138},[132,418,419],{"class":134,"line":232},[132,420,235],{"class":138},[109,422,423,424,426,427,429],{},"The resolver collects source ",[113,425,226],{}," values, loads targets whose ",[113,428,209],{}," is in that set, then groups rows by foreign key.",[118,431,433],{"id":432},"many-to-many","Many to many",[123,435,437],{"className":125,"code":436,"language":127,"meta":128,"style":128},"{\n  name: 'teams',\n  kind: 'manyToMany',\n  target: 'teams',\n  through: {\n    table: 'teamMembers',\n    sourceForeignKey: 'userId',\n    targetForeignKey: 'teamId'\n  },\n  sourceKey: 'id',\n  targetKey: 'id'\n}\n",[113,438,439,443,458,473,487,497,513,529,544,550,566,580],{"__ignoreMap":128},[132,440,441],{"class":134,"line":135},[132,442,139],{"class":138},[132,444,445,447,449,451,454,456],{"class":134,"line":142},[132,446,146],{"class":145},[132,448,149],{"class":138},[132,450,152],{"class":138},[132,452,453],{"class":155},"teams",[132,455,159],{"class":138},[132,457,162],{"class":138},[132,459,460,462,464,466,469,471],{"class":134,"line":165},[132,461,168],{"class":145},[132,463,149],{"class":138},[132,465,152],{"class":138},[132,467,468],{"class":155},"manyToMany",[132,470,159],{"class":138},[132,472,162],{"class":138},[132,474,475,477,479,481,483,485],{"class":134,"line":182},[132,476,185],{"class":145},[132,478,149],{"class":138},[132,480,152],{"class":138},[132,482,453],{"class":155},[132,484,159],{"class":138},[132,486,162],{"class":138},[132,488,489,492,494],{"class":134,"line":199},[132,490,491],{"class":145},"  through",[132,493,149],{"class":138},[132,495,496],{"class":138}," {\n",[132,498,499,502,504,506,509,511],{"class":134,"line":216},[132,500,501],{"class":145},"    table",[132,503,149],{"class":138},[132,505,152],{"class":138},[132,507,508],{"class":155},"teamMembers",[132,510,159],{"class":138},[132,512,162],{"class":138},[132,514,515,518,520,522,525,527],{"class":134,"line":232},[132,516,517],{"class":145},"    sourceForeignKey",[132,519,149],{"class":138},[132,521,152],{"class":138},[132,523,524],{"class":155},"userId",[132,526,159],{"class":138},[132,528,162],{"class":138},[132,530,532,535,537,539,542],{"class":134,"line":531},8,[132,533,534],{"class":145},"    targetForeignKey",[132,536,149],{"class":138},[132,538,152],{"class":138},[132,540,541],{"class":155},"teamId",[132,543,229],{"class":138},[132,545,547],{"class":134,"line":546},9,[132,548,549],{"class":138},"  },\n",[132,551,553,556,558,560,562,564],{"class":134,"line":552},10,[132,554,555],{"class":145},"  sourceKey",[132,557,149],{"class":138},[132,559,152],{"class":138},[132,561,226],{"class":155},[132,563,159],{"class":138},[132,565,162],{"class":138},[132,567,569,572,574,576,578],{"class":134,"line":568},11,[132,570,571],{"class":145},"  targetKey",[132,573,149],{"class":138},[132,575,152],{"class":138},[132,577,226],{"class":155},[132,579,229],{"class":138},[132,581,583],{"class":134,"line":582},12,[132,584,235],{"class":138},[109,586,587],{},"The junction table must be registered and built like every other table.",[589,590,592,597,601,605,609],"steps",{"level":591},"3",[593,594,596],"h3",{"id":595},"load-matching-junction-rows","Load matching junction rows",[593,598,600],{"id":599},"collect-unique-target-foreign-key-values","Collect unique target foreign-key values",[593,602,604],{"id":603},"load-target-rows-in-one-query","Load target rows in one query",[593,606,608],{"id":607},"index-targets-and-junction-rows-in-memory","Index targets and junction rows in memory",[593,610,612],{"id":611},"attach-ordered-related-arrays-to-source-entities","Attach ordered related arrays to source entities",[118,614,615],{"id":115},"Populate",[123,617,619],{"className":125,"code":618,"language":127,"meta":128,"style":128},"const users = await engine.findMany('users', {\n  populate: ['projects', 'teams']\n})\n",[113,620,621,661,689],{"__ignoreMap":128},[132,622,623,627,631,634,638,641,643,647,650,652,654,656,659],{"class":134,"line":135},[132,624,626],{"class":625},"spNyl","const",[132,628,630],{"class":629},"sTEyZ"," users ",[132,632,633],{"class":138},"=",[132,635,637],{"class":636},"s7zQu"," await",[132,639,640],{"class":629}," engine",[132,642,116],{"class":138},[132,644,646],{"class":645},"s2Zo4","findMany",[132,648,649],{"class":629},"(",[132,651,159],{"class":138},[132,653,192],{"class":155},[132,655,159],{"class":138},[132,657,658],{"class":138},",",[132,660,496],{"class":138},[132,662,663,667,669,672,674,676,678,680,682,684,686],{"class":134,"line":142},[132,664,666],{"class":665},"swJcz","  populate",[132,668,149],{"class":138},[132,670,671],{"class":629}," [",[132,673,159],{"class":138},[132,675,357],{"class":155},[132,677,159],{"class":138},[132,679,658],{"class":138},[132,681,152],{"class":138},[132,683,453],{"class":155},[132,685,159],{"class":138},[132,687,688],{"class":629},"]\n",[132,690,691,694],{"class":134,"line":165},[132,692,693],{"class":138},"}",[132,695,696],{"class":629},")\n",[109,698,699,700,703,704,706],{},"For ",[113,701,702],{},"findOne()",", the same ",[113,705,115],{}," option applies after loading the base entity.",[708,709,710,718,721,724],"ul",{},[711,712,713,714,717],"li",{},"to-one relations resolve to an entity or ",[113,715,716],{},"null",";",[711,719,720],{},"to-many relations resolve to an array;",[711,722,723],{},"missing relation names throw;",[711,725,726],{},"duplicate keys are deduplicated before related queries.",[118,728,730],{"id":729},"query-behavior","Query behavior",[109,732,733],{},"Each populated relation results in batched adapter queries, not one query per source entity. Many-to-many requires one junction query and one target query.",[735,736,740],"callout",{"color":737,"icon":738,"variant":739},"info","i-tabler-eye","subtle",[109,741,742],{},"Population is explicit so callers can see when a query will perform additional database work.",[109,744,745,746,749,750,752,753,116],{},"Every populated target passes through its own table serialization rules. A\n",[113,747,748],{},"hidden"," password on ",[113,751,192],{},", for example, remains hidden when a user is loaded\nthrough ",[113,754,755],{},"projects.owner",[118,757,759],{"id":758},"current-scope","Current scope",[109,761,762],{},"The resolver does not currently support:",[708,764,765,770,773,776,779],{},[711,766,767,768,717],{},"nested paths such as ",[113,769,755],{},[711,771,772],{},"filters or sorting per populated relation;",[711,774,775],{},"relation-specific pagination;",[711,777,778],{},"field projections;",[711,780,781],{},"automatic recursive loading.",[109,783,784,785,788],{},"PostgreSQL introspection also returns ",[113,786,787],{},"relations: []","; declared relation metadata remains the source of truth.",[790,791,792],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":128,"searchDepth":135,"depth":142,"links":794},[795,796,797,798,799,800,801],{"id":120,"depth":142,"text":121},{"id":244,"depth":142,"text":245},{"id":336,"depth":142,"text":337},{"id":432,"depth":142,"text":433},{"id":115,"depth":142,"text":615},{"id":729,"depth":142,"text":730},{"id":758,"depth":142,"text":759},"Declare direct relationships and load them explicitly in batches.","md",null,{},{"icon":76},{"title":73,"description":802},"X44S7c8W22nrEMyy5ZvpxzTvyo2id8d8wCPjeiW8fSM",[810,812],{"title":68,"path":69,"stem":70,"description":811,"icon":71,"children":-1},"Compose database-independent constraints, sorting, offset and cursor pagination.",{"title":78,"path":79,"stem":80,"description":813,"icon":81,"children":-1},"Detect drift between declared metadata and live PostgreSQL tables.",1783784235117]