<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>UQL | Blog</title><description>The best ORM for TypeScript and modern JavaScript designed to be fast, safe, and easy to integrate into any application.</description><link>https://uql-orm.dev/</link><language>en</language><item><title>Semantic Search: Native Vector Similarity in a Multi-Dialect ORM</title><link>https://uql-orm.dev/blog/semantic-search/</link><guid isPermaLink="true">https://uql-orm.dev/blog/semantic-search/</guid><description>UQL 0.3 ships native semantic search across PostgreSQL, MariaDB, SQLite, and MongoDB Atlas — featuring zero-allocation overhead and automatic index migration.

</description><pubDate>Thu, 12 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;AI-powered search is everywhere, but if you use an ORM, you’ve probably hit this wall: the moment you need vector similarity, you’re forced to use raw SQL. Hand-written distance expressions, and dialect-specific quirks — all outside your type-safe query API.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UQL 0.3 changes that.&lt;/strong&gt; Native semantic search is now a first-class citizen, featuring &lt;strong&gt;automatic index migration&lt;/strong&gt; for HNSW/IVFFlat and zero-allocation performance.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-it-looks-like&quot;&gt;What It Looks Like&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;You write&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;results&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; querier.&lt;/span&gt;&lt;span&gt;findMany&lt;/span&gt;&lt;span&gt;(Article, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$select&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;&lt;span&gt;, title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$sort&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { embedding&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { $vector&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; queryEmbedding, $distance&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;cosine&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; } },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$limit&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;UQL generates the right SQL for your database:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;PostgreSQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Article&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ORDER BY&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;embedding&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;=&gt;&lt;/span&gt;&lt;span&gt; $&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;LIMIT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;MariaDB&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;Article&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ORDER BY&lt;/span&gt;&lt;span&gt; VEC_DISTANCE_COSINE(&lt;/span&gt;&lt;span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;embedding&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, ?)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;LIMIT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;SQLite&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;Article&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ORDER BY&lt;/span&gt;&lt;span&gt; vec_distance_cosine(&lt;/span&gt;&lt;span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;embedding&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, ?)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;LIMIT&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;No raw SQL. No dialect checks. Same query everywhere.&lt;/p&gt;
&lt;p&gt;For MongoDB, UQL translates into an Atlas &lt;code dir=&quot;auto&quot;&gt;$vectorSearch&lt;/code&gt; pipeline — same API, zero config:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;MongoDB Atlas&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{ &lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$vectorSearch&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;index&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;embedding_index&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;embedding&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;queryVector&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;numCandidates&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;limit&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt; } }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;entity-setup&quot;&gt;Entity Setup&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Define your vector field and index — UQL handles schema generation, extension creation, and index building:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Entity, Id, Field, Index } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;uql-orm&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Entity&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Index&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;embedding&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;], { type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;hnsw&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;, distance&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;cosine&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;, m&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;&lt;span&gt;, efConstruction&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Article&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Id&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Field&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Field&lt;/span&gt;&lt;span&gt;&lt;span&gt;({ type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;vector&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;, dimensions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;1536&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;embedding&lt;/span&gt;&lt;span&gt;?:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;[];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For Postgres, UQL automatically emits &lt;code dir=&quot;auto&quot;&gt;CREATE EXTENSION IF NOT EXISTS vector&lt;/code&gt;. MariaDB and SQLite just work — no extensions needed.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;key-features&quot;&gt;Key Features&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;distance-projection&quot;&gt;Distance Projection&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Project the computed distance into your results with &lt;code dir=&quot;auto&quot;&gt;$project&lt;/code&gt; — no duplicate computation:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; { WithDistance } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;uql-orm&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;results&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; querier.&lt;/span&gt;&lt;span&gt;findMany&lt;/span&gt;&lt;span&gt;(Article, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$select&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;&lt;span&gt;, title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$sort&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { embedding&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { $vector&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; queryVec, $distance&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;cosine&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;, $project&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;similarity&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; } },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$limit&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}) &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;WithDistance&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Article&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;similarity&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&gt;[];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;results[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;].similarity; &lt;/span&gt;&lt;span&gt;// autocomplete works ✓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;WithDistance&amp;#x3C;E, K&gt;&lt;/code&gt; adds a typed distance property to each result — your IDE autocompletes it, and typos are caught at compile time.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;5-distance-metrics&quot;&gt;5 Distance Metrics&lt;/h3&gt;&lt;/div&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Metric&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Postgres&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MariaDB&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;SQLite&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MongoDB Atlas&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;cosine&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;=&gt;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✅&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✅&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✅ (index-defined)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;l2&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;-&gt;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✅&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✅&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✅ (index-defined)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;inner&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;#&gt;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;—&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;—&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✅ (index-defined)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;l1&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;+&gt;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;—&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;—&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;hamming&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;~&gt;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;—&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✅&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h3 id=&quot;3-vector-types&quot;&gt;3 Vector Types&lt;/h3&gt;&lt;/div&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Type&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Storage&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Use Case&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;&apos;vector&apos;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;32-bit float&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Standard embeddings (OpenAI, etc.)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;&apos;halfvec&apos;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;16-bit float&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;50% storage savings, near-identical accuracy&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;&apos;sparsevec&apos;&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Sparse&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;SPLADE, BM25-style sparse retrieval&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;halfvec&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;sparsevec&lt;/code&gt; are Postgres-only. MariaDB and SQLite transparently map them to their native &lt;code dir=&quot;auto&quot;&gt;VECTOR&lt;/code&gt; type — your entities work everywhere.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;vector-indexes&quot;&gt;Vector Indexes&lt;/h3&gt;&lt;/div&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Type&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Postgres&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MariaDB&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;MongoDB Atlas&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;HNSW&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✅ with &lt;code dir=&quot;auto&quot;&gt;m&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;efConstruction&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;❌&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;❌&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;IVFFlat&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✅ with &lt;code dir=&quot;auto&quot;&gt;lists&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;❌&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;❌&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Native&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;—&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✅ &lt;code dir=&quot;auto&quot;&gt;VECTOR INDEX&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✅ &lt;code dir=&quot;auto&quot;&gt;$vectorSearch&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h2 id=&quot;why-sort&quot;&gt;Why &lt;code dir=&quot;auto&quot;&gt;$sort&lt;/code&gt;?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Vector similarity search is fundamentally sorting by distance. UQL reuses the existing &lt;code dir=&quot;auto&quot;&gt;$sort&lt;/code&gt; API, which composes naturally with &lt;code dir=&quot;auto&quot;&gt;$where&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;$select&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;$limit&lt;/code&gt;, and regular sort fields:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;results&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; querier.&lt;/span&gt;&lt;span&gt;findMany&lt;/span&gt;&lt;span&gt;(Article, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$where&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { category&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;science&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$sort&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { embedding&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { $vector&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; queryVec, $distance&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;cosine&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; }, title&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;asc&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$limit&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;No new concepts to learn. The query API you already know now handles AI search.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;get-started&quot;&gt;Get Started&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;uql-orm&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://uql-orm.dev/querying/semantic-search&quot;&gt;Full documentation →&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/rogerpadilla/uql&quot;&gt;GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’d love to hear how you’re using vector search in your projects — open an issue on &lt;a href=&quot;https://github.com/rogerpadilla/uql&quot;&gt;GitHub&lt;/a&gt; and let us know!&lt;/p&gt;
&lt;hr&gt;

&lt;section id=&quot;giscus-wrapper&quot;&gt; &lt;!-- Content injected via client-side script to support View Transitions --&gt; &lt;/section&gt; </content:encoded><category>release</category><category>semantic-search</category><category>vector</category></item><item><title>In Search of the Fastest TypeScript ORM</title><link>https://uql-orm.dev/blog/in-search-of-the-fastest-typescript-orm/</link><guid isPermaLink="true">https://uql-orm.dev/blog/in-search-of-the-fastest-typescript-orm/</guid><description>Pure SQL generation speed across 7 ORMs and query builders. The slowest was a query builder — not an ORM.

</description><pubDate>Tue, 10 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I kept seeing &lt;em&gt;“just use Drizzle, it’s lightweight”&lt;/em&gt; and &lt;em&gt;“ORMs are slow, use a query builder”&lt;/em&gt; repeated everywhere. So I decided to actually measure it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pure SQL generation speed&lt;/strong&gt; — no database, no network, no connection pool. Just the overhead your ORM adds to every single request.&lt;/p&gt;
&lt;p&gt;7 entries. 8 query types. 3 runs averaged. Apple Silicon M4.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;methodology&quot;&gt;Methodology&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Environment:&lt;/strong&gt; Node.js v24, Apple Silicon M4, 3 runs averaged.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Versions:&lt;/strong&gt; Latest stable of every ORM/QB as of March 2026.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fairness:&lt;/strong&gt; Each ORM uses its most idiomatic API — QueryBuilder for TypeORM/MikroORM, which benefits them by skipping entity overhead.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What’s measured:&lt;/strong&gt; Pure SQL string generation — no database, no I/O, no connection pool. This isolates ORM overhead only.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Why no Prisma?&lt;/strong&gt; Prisma is not a pure TypeScript/JavaScript ORM — only its client is JS/TS. The query engine is a separate Rust binary that builds SQL, making it architecturally incomparable and not even testable this way.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;the-results&quot;&gt;The Results&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;insert--10-rows-in-batch&quot;&gt;INSERT — 10 rows in batch&lt;/h3&gt;&lt;/div&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Entry&lt;/th&gt;&lt;th&gt;ops/sec&lt;/th&gt;&lt;th&gt;vs winner&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;UQL&lt;/td&gt;&lt;td&gt;606K 🥇&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Knex&lt;/td&gt;&lt;td&gt;407K&lt;/td&gt;&lt;td&gt;0.67x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sequelize&lt;/td&gt;&lt;td&gt;202K&lt;/td&gt;&lt;td&gt;0.33x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kysely&lt;/td&gt;&lt;td&gt;197K&lt;/td&gt;&lt;td&gt;0.33x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MikroORM&lt;/td&gt;&lt;td&gt;50K&lt;/td&gt;&lt;td&gt;0.08x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TypeORM&lt;/td&gt;&lt;td&gt;47K&lt;/td&gt;&lt;td&gt;0.08x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Drizzle&lt;/td&gt;&lt;td&gt;13K&lt;/td&gt;&lt;td&gt;0.02x&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h3 id=&quot;update--set--where&quot;&gt;UPDATE — SET + WHERE&lt;/h3&gt;&lt;/div&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Entry&lt;/th&gt;&lt;th&gt;ops/sec&lt;/th&gt;&lt;th&gt;vs winner&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;UQL&lt;/td&gt;&lt;td&gt;1,817K 🥇&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kysely&lt;/td&gt;&lt;td&gt;819K&lt;/td&gt;&lt;td&gt;0.45x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Knex&lt;/td&gt;&lt;td&gt;601K&lt;/td&gt;&lt;td&gt;0.33x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TypeORM&lt;/td&gt;&lt;td&gt;321K&lt;/td&gt;&lt;td&gt;0.18x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sequelize&lt;/td&gt;&lt;td&gt;234K&lt;/td&gt;&lt;td&gt;0.13x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MikroORM&lt;/td&gt;&lt;td&gt;119K&lt;/td&gt;&lt;td&gt;0.07x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Drizzle&lt;/td&gt;&lt;td&gt;81K&lt;/td&gt;&lt;td&gt;0.04x&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h3 id=&quot;upsert--on-conflict-by-id&quot;&gt;UPSERT — ON CONFLICT by id&lt;/h3&gt;&lt;/div&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Entry&lt;/th&gt;&lt;th&gt;ops/sec&lt;/th&gt;&lt;th&gt;vs winner&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;UQL&lt;/td&gt;&lt;td&gt;693K 🥇&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Knex&lt;/td&gt;&lt;td&gt;349K&lt;/td&gt;&lt;td&gt;0.50x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sequelize&lt;/td&gt;&lt;td&gt;334K&lt;/td&gt;&lt;td&gt;0.48x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kysely&lt;/td&gt;&lt;td&gt;334K&lt;/td&gt;&lt;td&gt;0.48x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TypeORM&lt;/td&gt;&lt;td&gt;316K&lt;/td&gt;&lt;td&gt;0.46x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MikroORM&lt;/td&gt;&lt;td&gt;130K&lt;/td&gt;&lt;td&gt;0.19x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Drizzle&lt;/td&gt;&lt;td&gt;38K&lt;/td&gt;&lt;td&gt;0.05x&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h3 id=&quot;delete--simple-where&quot;&gt;DELETE — simple WHERE&lt;/h3&gt;&lt;/div&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Entry&lt;/th&gt;&lt;th&gt;ops/sec&lt;/th&gt;&lt;th&gt;vs winner&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;UQL&lt;/td&gt;&lt;td&gt;3,642K 🥇&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sequelize&lt;/td&gt;&lt;td&gt;1,349K&lt;/td&gt;&lt;td&gt;0.37x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kysely&lt;/td&gt;&lt;td&gt;1,290K&lt;/td&gt;&lt;td&gt;0.35x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Knex&lt;/td&gt;&lt;td&gt;962K&lt;/td&gt;&lt;td&gt;0.26x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TypeORM&lt;/td&gt;&lt;td&gt;542K&lt;/td&gt;&lt;td&gt;0.15x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Drizzle&lt;/td&gt;&lt;td&gt;212K&lt;/td&gt;&lt;td&gt;0.06x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MikroORM&lt;/td&gt;&lt;td&gt;148K&lt;/td&gt;&lt;td&gt;0.04x&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h3 id=&quot;select--1-field&quot;&gt;SELECT — 1 field&lt;/h3&gt;&lt;/div&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Entry&lt;/th&gt;&lt;th&gt;ops/sec&lt;/th&gt;&lt;th&gt;vs winner&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;UQL&lt;/td&gt;&lt;td&gt;3,994K 🥇&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sequelize&lt;/td&gt;&lt;td&gt;3,143K&lt;/td&gt;&lt;td&gt;0.79x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kysely&lt;/td&gt;&lt;td&gt;1,559K&lt;/td&gt;&lt;td&gt;0.39x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Knex&lt;/td&gt;&lt;td&gt;994K&lt;/td&gt;&lt;td&gt;0.25x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TypeORM&lt;/td&gt;&lt;td&gt;817K&lt;/td&gt;&lt;td&gt;0.20x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MikroORM&lt;/td&gt;&lt;td&gt;297K&lt;/td&gt;&lt;td&gt;0.07x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Drizzle&lt;/td&gt;&lt;td&gt;238K&lt;/td&gt;&lt;td&gt;0.06x&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h3 id=&quot;select--where--sort--limit&quot;&gt;SELECT — WHERE + SORT + LIMIT&lt;/h3&gt;&lt;/div&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Entry&lt;/th&gt;&lt;th&gt;ops/sec&lt;/th&gt;&lt;th&gt;vs winner&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;UQL&lt;/td&gt;&lt;td&gt;1,200K 🥇&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Knex&lt;/td&gt;&lt;td&gt;480K&lt;/td&gt;&lt;td&gt;0.40x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kysely&lt;/td&gt;&lt;td&gt;425K&lt;/td&gt;&lt;td&gt;0.35x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sequelize&lt;/td&gt;&lt;td&gt;385K&lt;/td&gt;&lt;td&gt;0.32x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TypeORM&lt;/td&gt;&lt;td&gt;355K&lt;/td&gt;&lt;td&gt;0.30x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Drizzle&lt;/td&gt;&lt;td&gt;60K&lt;/td&gt;&lt;td&gt;0.05x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MikroORM&lt;/td&gt;&lt;td&gt;46K&lt;/td&gt;&lt;td&gt;0.04x&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h3 id=&quot;select--complex-or--operators&quot;&gt;SELECT — Complex $or + operators&lt;/h3&gt;&lt;/div&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Entry&lt;/th&gt;&lt;th&gt;ops/sec&lt;/th&gt;&lt;th&gt;vs winner&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;UQL&lt;/td&gt;&lt;td&gt;644K 🥇&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kysely&lt;/td&gt;&lt;td&gt;218K&lt;/td&gt;&lt;td&gt;0.34x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Knex&lt;/td&gt;&lt;td&gt;199K&lt;/td&gt;&lt;td&gt;0.31x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TypeORM&lt;/td&gt;&lt;td&gt;186K&lt;/td&gt;&lt;td&gt;0.29x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sequelize&lt;/td&gt;&lt;td&gt;152K&lt;/td&gt;&lt;td&gt;0.24x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Drizzle&lt;/td&gt;&lt;td&gt;35K&lt;/td&gt;&lt;td&gt;0.05x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MikroORM&lt;/td&gt;&lt;td&gt;22K&lt;/td&gt;&lt;td&gt;0.03x&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;h3 id=&quot;aggregate--group-by--count--having&quot;&gt;AGGREGATE — GROUP BY + COUNT + HAVING&lt;/h3&gt;&lt;/div&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Entry&lt;/th&gt;&lt;th&gt;ops/sec&lt;/th&gt;&lt;th&gt;vs winner&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;UQL&lt;/td&gt;&lt;td&gt;1,489K 🥇&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sequelize&lt;/td&gt;&lt;td&gt;407K&lt;/td&gt;&lt;td&gt;0.27x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TypeORM&lt;/td&gt;&lt;td&gt;364K&lt;/td&gt;&lt;td&gt;0.24x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Knex&lt;/td&gt;&lt;td&gt;284K&lt;/td&gt;&lt;td&gt;0.19x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kysely&lt;/td&gt;&lt;td&gt;227K&lt;/td&gt;&lt;td&gt;0.15x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Drizzle&lt;/td&gt;&lt;td&gt;77K&lt;/td&gt;&lt;td&gt;0.05x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MikroORM&lt;/td&gt;&lt;td&gt;64K&lt;/td&gt;&lt;td&gt;0.04x&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;📊 &lt;strong&gt;&lt;a href=&quot;https://rogerpadilla.github.io/ts-orm-benchmark/chart.html&quot;&gt;Interactive charts →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;three-things-that-surprised-me&quot;&gt;Three Things That Surprised Me&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;1. The “lightweight” query builder is the slowest thing in the benchmark.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Drizzle — marketed as lightweight — is slower than Sequelize (a full ORM from 2014) in every single category. The functional expression-tree approach creates more intermediate objects than Sequelize’s simple string concatenation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Standalone query builders can’t beat a well-designed ORM.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Knex and Kysely have zero entity/relation overhead. They’re just SQL string builders. Yet UQL — a full ORM with entities, relations, and migrations — is faster than both in all 8 categories. This &lt;strong&gt;4x-40x overhead advantage&lt;/strong&gt; demonstrates that the conventional wisdom (“ORMs are slow”) doesn’t hold when the ORM is designed for performance with a &lt;strong&gt;Zero-Allocation&lt;/strong&gt; architecture from day one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. MikroORM pays double.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;MikroORM uses Knex internally as its SQL generator. So every query goes through two compilation layers: MikroORM → Knex → SQL string. The result? MikroORM averages 4-5x slower than Knex alone. That’s the cost of layering abstractions.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;how-uql-gets-there&quot;&gt;How UQL Gets There&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I got curious why the gap was so large, so I dug into the approach. Most ORMs figure out your schema at query time: &lt;em&gt;“What table does &lt;code dir=&quot;auto&quot;&gt;User&lt;/code&gt; map to? What column is &lt;code dir=&quot;auto&quot;&gt;companyId&lt;/code&gt;? Is it nullable?”&lt;/em&gt; — they answer these questions on every single query.&lt;/p&gt;
&lt;p&gt;UQL answers them once at startup. Field-to-column mappings, table names, relation paths — all pre-computed into lookup tables before the first query runs. At query time, generating SQL is just reading from a cache.&lt;/p&gt;
&lt;p&gt;The other difference is allocation. When TypeORM builds a SELECT, it creates a QueryBuilder, then an expression tree, then walks the tree to produce SQL. UQL pushes SQL fragments directly into a string buffer — no intermediate objects, no garbage collection pressure.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;does-this-matter-in-production&quot;&gt;Does This Matter in Production?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Database latency is 1-50ms. ORM overhead is microseconds. So who cares?&lt;/p&gt;
&lt;p&gt;You care at scale. If you’re running a moderately busy API — say 1,000 req/s:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UQL adds &lt;strong&gt;1 CPU-second&lt;/strong&gt; of ORM overhead&lt;/li&gt;
&lt;li&gt;MikroORM adds &lt;strong&gt;20 CPU-seconds&lt;/strong&gt; — for the same queries&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s 20x more CPU burned on generating SQL strings — pure waste before a single byte hits the network. In serverless (where you pay per ms), that’s your bill. In containers, that’s your horizontal scaling cost.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;reproduce-it&quot;&gt;Reproduce It&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Full disclosure: I’m the author of UQL. That’s exactly why I built the benchmark as an independent repo anyone can audit and reproduce.&lt;/p&gt;
&lt;p&gt;The full benchmark is open source — clone it, audit it, run it, share results. No database needed, finishes in seconds. See how UQL maintains its &lt;a href=&quot;https://uql-orm.dev/comparison#performance&quot;&gt;4x-40x performance lead&lt;/a&gt; across every modern TypeScript environment.&lt;/p&gt;
&lt;p&gt;Repo: &lt;a href=&quot;https://github.com/rogerpadilla/ts-orm-benchmark&quot;&gt;ts-orm-benchmark&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section id=&quot;giscus-wrapper&quot;&gt; &lt;!-- Content injected via client-side script to support View Transitions --&gt; &lt;/section&gt; </content:encoded><category>benchmark</category><category>performance</category><category>typescript</category><category>orm</category></item><item><title>In Search of the Perfect TypeScript ORM</title><link>https://uql-orm.dev/blog/in-search-of-the-perfect-orm/</link><guid isPermaLink="true">https://uql-orm.dev/blog/in-search-of-the-perfect-orm/</guid><description>What makes a perfect ORM? I evaluated the top 5 features every TypeScript ORM should have — and why the existing ones fall short.

</description><pubDate>Sat, 15 Jun 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href=&quot;https://medium.com/@rogerpadillac/in-search-of-the-perfect-orm-e01fcc9bce3d&quot;&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-is-an-orm&quot;&gt;What is an ORM?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;An ORM provides a simpler way to interact with databases in an app — it allows developers to work with data using objects.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-is-a-perfect-orm-for-typescript&quot;&gt;What is a Perfect ORM for TypeScript?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Below are the ideal features a TypeScript ORM should have, why such features are the most important ones, and how the existing ORMs fall short in most of these areas.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The top 5 features a perfect TypeScript ORM should have are:&lt;/strong&gt;&lt;/p&gt;
&lt;img src=&quot;https://uql-orm.dev/_astro/once-upon-a-time.rrA8_mq6_ZFAYNj.webp&quot; alt=&quot;Once upon a time — handwritten&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;322&quot;&gt;
&lt;div&gt;&lt;h3 id=&quot;1-serializable-queries&quot;&gt;1. Serializable Queries&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The ability to transport queries between the layers of a system is great for flexibility and simplicity. For example, via HTTP requests, APIs, websockets, or even the frontend/client (optional) could transmit the queries to the backend/server using the same (ORM) syntax and avoid the need for an additional syntax layer like what happens with GraphQL in the flow &lt;code dir=&quot;auto&quot;&gt;GraphQL =&gt; ORM =&gt; Database&lt;/code&gt;. The flow could instead be simplified as &lt;code dir=&quot;auto&quot;&gt;ORM =&gt; Database&lt;/code&gt;; with the following advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keep away from the need for pseudo-languages to define the queries (context-switching). Instead, use standard JSON as the syntax for the queries so they are entirely declarative and serializable.&lt;/li&gt;
&lt;li&gt;Avoid additional servers and steps in the build process of the app.&lt;/li&gt;
&lt;li&gt;Native support of the editors/IDEs for the queries without any custom plugins/extensions.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;2-native-typescript&quot;&gt;2. Native TypeScript&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Squeeze TypeScript’s power with JSON, classes, and decorators.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Type-safe queries and models that are natively validated by the same language that you use to write your app.&lt;/li&gt;
&lt;li&gt;Context-aware queries allow auto-completion of the appropriate operators and fields according to the different parts of a query.&lt;/li&gt;
&lt;li&gt;Entity definition with standard classes and decorators to avoid the need for proprietary DSLs (as happens with Prisma), extra steps in the build process, and custom extensions for the editors.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;3-multi-level-operators&quot;&gt;3. Multi-level Operators&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Operations such as filter, sort, limit, project, and others work on any level of the queries (including relations and their fields).&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;4-consistent-api-across-databases&quot;&gt;4. Consistent API Across Databases&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Write the queries for any database in a consistent way and then transparently optimize these queries for the configured database dialect.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;5-universal-syntax-language-agnostic&quot;&gt;5. Universal Syntax (Language Agnostic)&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The ability to write queries in any language opens the door to many possibilities, even porting the ORM to other languages. For example, JSON is a first-class citizen format on almost any modern language out there, including Python, Rust, and others (besides JavaScript).&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;why-do-the-current-top-3-typescript-orms-fall-short&quot;&gt;Why Do the Current Top 3 TypeScript ORMs Fall Short?&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;what-does-typeorm-lack-to-be-a-perfect-orm&quot;&gt;What does TypeORM lack to be a perfect ORM?&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;1. Lack of 100% serializable queries:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Notice how the &lt;code dir=&quot;auto&quot;&gt;LessThan&lt;/code&gt; operator is a function that has to be imported and called — this precludes any capability to serialize the query.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { LessThan } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;typeorm&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;loadedPosts&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; dataSource.&lt;/span&gt;&lt;span&gt;getRepository&lt;/span&gt;&lt;span&gt;(Post).&lt;/span&gt;&lt;span&gt;findBy&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;likes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LessThan&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;2. Lack of Native TypeScript:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The query dissolves into strings because &lt;code dir=&quot;auto&quot;&gt;relations&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;where&lt;/code&gt; can accept any string, thus any invalid string can be put there.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;posts&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; connection.manager.&lt;/span&gt;&lt;span&gt;find&lt;/span&gt;&lt;span&gt;(Post, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;relations&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;&amp;#x3C; anything can go here &gt;&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;3. Lack of consistent API across databases:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the section that TypeORM has for MongoDB, there is a self-explanatory warning about this.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Lack of Universal Syntax (language agnostic):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It relies on closures to support advanced queries (and not every language out there supports closures).&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h3 id=&quot;what-does-prisma-lack-to-be-a-perfect-orm&quot;&gt;What does Prisma lack to be a perfect ORM?&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;1. Lack of Native TypeScript:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Context-switching between the custom DSL and TypeScript makes this process obtrusive.&lt;/li&gt;
&lt;li&gt;Extra steps in the build process to generate the corresponding files from the custom DSL.&lt;/li&gt;
&lt;li&gt;It is required to install a custom extension for VS Code to get (basic) autocompletion from the editor for the DSL, which is far from being as good and reliable as with TypeScript.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;datasource&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;db&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;provider &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;postgresql&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;url      &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;env&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;DATABASE_URL&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;generator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;provider &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;prisma-client-js&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;id        &lt;/span&gt;&lt;span&gt;Int&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;@id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@default&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;autoincrement&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;createdAt &lt;/span&gt;&lt;span&gt;DateTime&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@default&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;email     &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;@unique&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name      &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;role      &lt;/span&gt;&lt;span&gt;Role&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;@default&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;USER&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;posts     &lt;/span&gt;&lt;span&gt;Post&lt;/span&gt;&lt;span&gt;[]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;2. Lack of consistent API across databases:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Prisma exposes low-level details about MongoDB that could be encapsulated by the ORM.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;id &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@default&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;span&gt;()) &lt;/span&gt;&lt;span&gt;@map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;_id&quot;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;@db.ObjectId&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// Other fields&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;3. Lack of Universal Syntax (language agnostic):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It relies on its own proprietary DSL to define the models.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h3 id=&quot;what-does-mikroorm-lack-to-be-a-perfect-orm&quot;&gt;What does MikroORM lack to be a perfect ORM?&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;1. Lack of 100% serializable queries:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Notice how that query uses two separate methods, one for the update and another for the where — this disallows the serialization of its queries.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;qb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; orm.em.&lt;/span&gt;&lt;span&gt;createQueryBuilder&lt;/span&gt;&lt;span&gt;(Author);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;qb.&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;&lt;span&gt;({ name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;test 123&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;, type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; PublisherType.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;GLOBAL&lt;/span&gt;&lt;span&gt; }).&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;123&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; PublisherType.&lt;/span&gt;&lt;span&gt;LOCAL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;2. Lack of Native TypeScript:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Dissolves into strings — any string can go inside the &lt;code dir=&quot;auto&quot;&gt;fields&lt;/code&gt; array, so the query loses the possibility of being type-safe.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; em.&lt;/span&gt;&lt;span&gt;findOne&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Author,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fields&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;books.title&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;books.author&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;books.price&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;3. Lack of Multi-level operators:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;What if you need to filter the records of a relation or sort them? This seems unachievable in a type-safe way from what can be seen in the MikroORM docs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Lack of consistent API across databases:&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { EntityManager } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;@mikro-orm/mongodb&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;em&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; orm.em &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;EntityManager&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;qb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; em.&lt;/span&gt;&lt;span&gt;aggregate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;/* ... */&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;MikroORM exposes low-level details about MongoDB that could be encapsulated by the ORM.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;why-is-uql-the-closest-to-a-perfect-orm&quot;&gt;Why is UQL the Closest to a Perfect ORM?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In short, because it was designed from the beginning with all of the above foundations. Let’s see how.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;1-100-serializable-queries&quot;&gt;1. 100% Serializable Queries&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Even the insert and update operations have a fully serializable API.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lastUsers&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; querier.&lt;/span&gt;&lt;span&gt;findMany&lt;/span&gt;&lt;span&gt;(User, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$select&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;&lt;span&gt;, name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;&lt;span&gt;, email&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$sort&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { createdAt&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$limit&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;2-native-typescript-with-truly-type-safe-queries&quot;&gt;2. Native TypeScript with Truly Type-safe Queries&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Every operator and field is validated according to the context. For example, the possible values for the &lt;code dir=&quot;auto&quot;&gt;$select&lt;/code&gt; operator will automatically depend on the level.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lastUsersWithProfiles&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; querier.&lt;/span&gt;&lt;span&gt;findMany&lt;/span&gt;&lt;span&gt;(User, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$select&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;profile&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$select&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;&lt;span&gt;, picture&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$required&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$sort&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { createdAt&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$limit&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;3-multi-level-operators-1&quot;&gt;3. Multi-level Operators&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The operators work on any level. For example, &lt;code dir=&quot;auto&quot;&gt;$sort&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;$where&lt;/code&gt; can be applied to the relations and their fields in a type-safe and context-aware way.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;items&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; querier.&lt;/span&gt;&lt;span&gt;findMany&lt;/span&gt;&lt;span&gt;(Item, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$select&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;measureUnit&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$select&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;&lt;span&gt;, name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$where&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { $ne&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;unidad&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; } },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$required&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;tax&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { $select&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { id&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;&lt;span&gt;, name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; } },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$where&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;salePrice&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { $gte&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1000&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { $istartsWith&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$sort&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;tax&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;measureUnit&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; { name&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;createdAt&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;$limit&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;4-consistent-api-across-databases-1&quot;&gt;4. Consistent API Across Databases&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Its API is unified across different databases — it does the magic under the hood so the same entities and queries could transparently work on any supported database. This makes it easier to switch from a Document to a Relational database (or vice-versa).&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;5-universal-syntax-across-languages&quot;&gt;5. Universal Syntax Across Languages&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Its syntax is 100% standard JSON, opening the door for many possibilities with other languages — like interoperation or even creating versions of UQL in other languages such as Python or Rust with ease.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;See more at &lt;strong&gt;&lt;a href=&quot;https://uql-orm.dev&quot;&gt;uql-orm.dev&lt;/a&gt;&lt;/strong&gt;. Please star it ⭐ on &lt;strong&gt;&lt;a href=&quot;https://github.com/rogerpadilla/uql&quot;&gt;GitHub&lt;/a&gt;&lt;/strong&gt; if you like the idea!&lt;/p&gt;
&lt;hr&gt;

&lt;section id=&quot;giscus-wrapper&quot;&gt; &lt;!-- Content injected via client-side script to support View Transitions --&gt; &lt;/section&gt; </content:encoded><category>orm</category><category>typescript</category><category>architecture</category></item></channel></rss>