[{"data":1,"prerenderedAt":121},["ShallowReactive",2],{"i-lucide:layers":3,"i-lucide:git-commit-horizontal":8,"i-lucide:refresh-cw":10,"i-lucide:book-open":12,"i-lucide:image":14,"i-lucide:webhook":16,"i-lucide:home":18,"i-lucide:layout-grid":20,"i-lucide:tag":22,"i-lucide:newspaper":24,"i-lucide:map":26,"i-lucide:flask-conical":28,"i-lucide:arrow-right":30,"i-lucide:chevron-right":32,"i-lucide:search":34,"i-lucide:monitor":36,"content:\u002Finternal\u002Farchitecture\u002Fsearch":38,"i-lucide:info":119,"i-lucide:key-round":116,"i-lucide:layers-2":116,"i-lucide:shield-check":116,"i-lucide:box":116,"i-lucide:share-2":116,"i-lucide:clock":116,"i-lucide:building-2":116,"i-lucide:dices":116,"i-lucide:bell":116,"i-lucide:sprout":116,"i-lucide:puzzle":116,"i-lucide:shield-alert":116,"i-lucide:blocks":116,"i-lucide:activity":116},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z\"\u002F>\u003Cpath d=\"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12\"\u002F>\u003Cpath d=\"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"3\"\u002F>\u003Cpath d=\"M3 12h6m6 0h6\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":11},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M3 12a9 9 0 0 1 9-9a9.75 9.75 0 0 1 6.74 2.74L21 8\"\u002F>\u003Cpath d=\"M21 3v5h-5m5 4a9 9 0 0 1-9 9a9.75 9.75 0 0 1-6.74-2.74L3 16\"\u002F>\u003Cpath d=\"M8 16H3v5\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":13},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 5v16m8.001-2A2 2 0 0 0 22 17V5a2 2 0 0 0-1.999-2L16 3.002A5 5 0 0 0 12 5a5 5 0 0 0-4-2H4a2 2 0 0 0-2 2v12a2 2 0 0 0 1.999 2H8a5 5 0 0 1 4 2a5 5 0 0 1 4-2z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":15},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Crect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\"\u002F>\u003Ccircle cx=\"9\" cy=\"9\" r=\"2\"\u002F>\u003Cpath d=\"m21 15l-3.086-3.086a2 2 0 0 0-2.828 0L6 21\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":17},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2\"\u002F>\u003Cpath d=\"m6 17l3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06\"\u002F>\u003Cpath d=\"m12 6l3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":19},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8\"\u002F>\u003Cpath d=\"M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":21},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Crect width=\"7\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\"\u002F>\u003Crect width=\"7\" height=\"7\" x=\"14\" y=\"3\" rx=\"1\"\u002F>\u003Crect width=\"7\" height=\"7\" x=\"14\" y=\"14\" rx=\"1\"\u002F>\u003Crect width=\"7\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":23},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z\"\u002F>\u003Ccircle cx=\"7.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":25},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M15 18h-5m8-4h-8m-6 8h16a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v16a2 2 0 0 1-4 0v-9a2 2 0 0 1 2-2h2\"\u002F>\u003Crect width=\"8\" height=\"4\" x=\"10\" y=\"6\" rx=\"1\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":27},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0zm.894.211v15M9 3.236v15\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":29},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2M6.453 15h11.094M8.5 2h7\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":31},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 12h14m-7-7l7 7l-7 7\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":33},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m9 18l6-6l-6-6\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":35},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"m21 21l-4.34-4.34\"\u002F>\u003Ccircle cx=\"11\" cy=\"11\" r=\"8\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":37},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Crect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\"\u002F>\u003Cpath d=\"M8 21h8m-4-4v4\"\u002F>\u003C\u002Fg>",{"id":39,"title":40,"body":41,"description":109,"extension":110,"eyebrow":111,"hostedOnly":6,"meta":112,"navigation":113,"path":114,"seo":115,"short":116,"stem":117,"__hash__":118},"docs\u002Finternal\u002Farchitecture\u002Fsearch.md","Search",{"type":42,"value":43,"toc":101},"minimark",[44,48,53,56,60,63,67,70,74,88],[45,46,47],"p",{},"Search is the feature most likely to tie an application to one database, because full-text search is where SQLite and Postgres stop looking alike. SQLite has FTS5. Postgres has tsvector and trigram matching. They are different enough that naive code would fork in a dozen places. Since Chronicler is committed to running well on both, search has to be designed so that the split lives in exactly one spot.",[49,50,52],"h2",{"id":51},"one-port-two-engines","One port, two engines",[45,54,55],{},"Search is its own bounded context, and it hides its engine behind a narrow port. The rest of the system asks for results and never names FTS5 or tsvector. Behind the port sit two hand-written implementations, one per database, chosen by dialect when the app is assembled. That is the whole trick: the difference between the engines is a single swap at startup, not a condition scattered through the codebase.",[49,57,59],{"id":58},"fields-have-classes-not-just-values","Fields have classes, not just values",[45,61,62],{},"Search organises into named collections, and each field declares a class from a fixed set: identifier, keyword, name, or prose. The class tells the engine how to treat the field, because you do not match a slug the way you match a paragraph. Naming the intent, rather than hand-tuning each field, is what keeps both engine implementations honest about doing the same thing.",[49,64,66],{"id":65},"the-index-can-always-be-rebuilt","The index can always be rebuilt",[45,68,69],{},"Indexing is driven by projectors reading the event stream, the same way every other read model is built. So the search index is rebuildable from scratch and the engine is swappable, which means a change of search technology is a reindex, not a migration.",[49,71,73],{"id":72},"where-this-connects","Where this connects",[45,75,76,77,82,83,87],{},"Search indexes the same events everything else projects from, described in ",[78,79,81],"a",{"href":80},"\u002Finternal\u002Farchitecture\u002Ffoundations","Foundations",", and its dual-engine approach is the ",[78,84,86],{"href":85},"\u002Finternal\u002Farchitecture\u002Fplatform","Platform"," dual-dialect rule applied to the hardest case.",[89,90,93],"callout",{"title":91,"tone":92},"Read the record for the detail","note",[45,94,95,96,100],{},"This page is the guide. The full record under ",[97,98,99],"code",{},"docs\u002Fadrs"," carries the field-class contract, the per-dialect stores, and the alternatives that were weighed and rejected.",{"title":102,"searchDepth":103,"depth":103,"links":104},"",2,[105,106,107,108],{"id":51,"depth":103,"text":52},{"id":58,"depth":103,"text":59},{"id":65,"depth":103,"text":66},{"id":72,"depth":103,"text":73},"Full-text and fuzzy search kept behind one port, so the two databases can each use their own engine without the rest of the system noticing.","md","Architecture",{},{"title":40},"\u002Finternal\u002Farchitecture\u002Fsearch",{"title":40,"description":109},null,"internal\u002Farchitecture\u002Fsearch","7WCUVk83AMOqc8Omu3KRsTX8i-UbwGpezFcqUMCeYPQ",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":120},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"M12 16v-4m0-4h.01\"\u002F>\u003C\u002Fg>",1788784066571]