重大变更
移除了对嵌套关系过滤的支持
当前示例在 0.28.0
中不起作用:
const usersWithPosts = await db.query.users.findMany({
where: (table, { sql }) => (sql`json_array_length(${table.posts}) > 0`),
with: {
posts: true,
},
});
where
回调中的 table
对象不包含 with
和 extras
中的字段。我们移除了它们,以便能够构建更高效的关系查询,从而提升了行读取和性能。
如果你之前在 where
回调中使用过这些字段,则有几种解决方法:
- 在获取行后,在代码级别手动应用这些过滤器;
- 使用核心 API。
为 mysql2
驱动程序添加了关系查询 mode
配置
Drizzle 关系查询始终只生成一条在数据库上运行的 SQL 语句,并且有一些注意事项。为了给所有数据库提供最佳的支持,我们引入了模式。
Drizzle 关系查询在底层使用子查询的横向连接,目前 PlanetScale 不支持它们。
将“mysql2
”驱动程序与常规 MySQL 数据库一起使用时 - 你应该指定模式:“default”。将“mysql2
”驱动程序与 PlanetScale 一起使用时 - 你需要指定模式:“planetscale”。
import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';
import * as schema from './schema';
const client = await mysql.createConnection({
uri: process.env.PLANETSCALE_DATABASE_URL,
});
const db = drizzle({ client, schema, mode: 'planetscale' });
改进了大型模式的 IntelliSense 性能
我们对一个包含 85 个表、666 个列、26 个枚举、172 个索引和 133 个外键的数据库模式运行了诊断程序。我们优化了内部类型,使 IntelliSense 的速度提高了 430%。
改进了关系查询的性能和读取使用情况
在此版本中,我们彻底改变了关系查询 API 生成查询的方式。
总结一下,我们对查询生成策略进行了以下更改:
-
横向连接:在新版本中,我们利用横向连接(用 “LEFT JOIN LATERAL” 子句表示)高效地从相关表中检索特定数据。对于 PlanetScale 中的 MySQL 和 SQLite,我们使用了简单的子查询选择,从而改进了查询计划并提升了整体性能。
-
选择性数据检索:在新版本中,我们只从表中检索必要的数据。这种有针对性的数据检索减少了获取的不必要信息量,从而减少了需要处理的数据集并提高了执行速度。
-
减少聚合:在新版本中,我们减少了聚合函数的数量(例如 COUNT、json_agg)。通过在横向连接中直接使用 json_build_array,drizzle 可以更简化地聚合数据,从而提高查询性能。
-
简化分组:在新版本中,GROUP BY 子句已被删除,因为横向连接和子查询已经能够更有效地处理数据聚合。
对于此 drizzle 查询
const items = await db.query.comments.findMany({
limit,
orderBy: comments.id,
with: {
user: {
columns: { name: true },
},
post: {
columns: { title: true },
with: {
user: {
columns: { name: true },
},
},
},
},
});
-- Query generated now
select "comments"."id",
"comments"."user_id",
"comments"."post_id",
"comments"."content",
"comments_user"."data" as "user",
"comments_post"."data" as "post"
from "comments"
left join lateral (select json_build_array("comments_user"."name") as "data"
from (select *
from "users" "comments_user"
where "comments_user"."id" = "comments"."user_id"
limit 1) "comments_user") "comments_user" on true
left join lateral (select json_build_array("comments_post"."title", "comments_post_user"."data") as "data"
from (select *
from "posts" "comments_post"
where "comments_post"."id" = "comments"."post_id"
limit 1) "comments_post"
left join lateral (select json_build_array("comments_post_user"."name") as "data"
from (select *
from "users" "comments_post_user"
where "comments_post_user"."id" = "comments_post"."user_id"
limit 1) "comments_post_user") "comments_post_user"
on true) "comments_post" on true
order by "comments"."id"
limit 1
-- Query generated before
SELECT "id",
"user_id",
"post_id",
"content",
"user"::JSON,
"post"::JSON
FROM
(SELECT "comments".*,
CASE
WHEN count("comments_post"."id") = 0 THEN '[]'
ELSE json_agg(json_build_array("comments_post"."title", "comments_post"."user"::JSON))::text
END AS "post"
FROM
(SELECT "comments".*,
CASE
WHEN count("comments_user"."id") = 0 THEN '[]'
ELSE json_agg(json_build_array("comments_user"."name"))::text
END AS "user"
FROM "comments"
LEFT JOIN
(SELECT "comments_user".*
FROM "users" "comments_user") "comments_user" ON "comments"."user_id" = "comments_user"."id"
GROUP BY "comments"."id",
"comments"."user_id",
"comments"."post_id",
"comments"."content") "comments"
LEFT JOIN
(SELECT "comments_post".*
FROM
(SELECT "comments_post".*,
CASE
WHEN count("comments_post_user"."id") = 0 THEN '[]'
ELSE json_agg(json_build_array("comments_post_user"."name"))
END AS "user"
FROM "posts" "comments_post"
LEFT JOIN
(SELECT "comments_post_user".*
FROM "users" "comments_post_user") "comments_post_user" ON "comments_post"."user_id" = "comments_post_user"."id"
GROUP BY "comments_post"."id") "comments_post") "comments_post" ON "comments"."post_id" = "comments_post"."id"
GROUP BY "comments"."id",
"comments"."user_id",
"comments"."post_id",
"comments"."content",
"comments"."user") "comments"
LIMIT 1
在文档中了解更多关于 关系查询 的信息。
使用默认值插入行的可能性所有列的值
你现在可以提供一个空对象或一个空对象数组,Drizzle 会将所有默认值插入数据库。
// Insert 1 row with all defaults
await db.insert(usersTable).values({});
// Insert 2 rows with all defaults
await db.insert(usersTable).values([{}, {}]);