首页
Preview

Prisma Preview Features:relationJoins功能的现状与挑战

Prisma发出的查询

在我们的项目中,我们使用Prisma作为ORM来操作数据库。遇到的问题是,当尝试获取多个表的数据时,Prisma发出了多个查询,而非预期的单个联合查询。以下是一个简单的示例:

await this.prisma.company.findUnique({
  where: { id },
  include: {
    shop: true,
  },
});

许多人可能会期望发出如下的SQL查询:

SELECT *
FROM company c
JOIN shop s ON c.id = s.company_id
WHERE c.id = @id;

然而,实际发出的查询是分为两个单独的查询:

SELECT
    company.id,
    company.name,
    company.created_at,
    company.updated_at
FROM company
WHERE company.id = @id
LIMIT 1;

SELECT
    shop.id,
    shop.name,
    shop.created_at,
    shop.updated_at
FROM shop
WHERE shop.company_id IN (@company_id);

虽然这些查询能完成任务,但相比之下,使用JOIN的查询会更高效。

项目中的GraphQL使用

在我们的项目中,前端通过GraphQL与后端进行通信。虽然GraphQL与REST API相比,联合查询多个表的情况较少,但考虑到服务的未来发展和扩展性,这一问题不容忽视。

使用Raw Query绕过问题

为了规避这种不理想的查询方式,我们可以使用原生SQL查询。然而,随着2024年1月10日,Prisma预览功能推出了relationJoins,这为我们提供了更优的解决方案。

什么是relationJoins

relationJoins是Prisma的新功能,允许我们选择是否将查询联合起来。通过启用此功能,我们能够以更高效的方式处理多个表的查询。此功能已在以下版本中推出:

  • PostgreSQL: v5.8.0(自2024年1月10日起)
  • MySQL: v5.10.0(自2024年2月21日起)

如何使用relationJoins

要启用relationJoins,首先需要在prisma.schema文件中配置该功能,然后运行npx prisma generate来生成客户端代码:

generator client {
  provider        = "prisma-client-js"
  engineType      = "binary"
  previewFeatures = ["relationJoins"]
}

启用后,您可以设置relationLoadStrategyjoin,并通过Prisma发出JOIN查询。

await this.prismaService.company.findUnique({
  relationLoadStrategy: "join",
  where: { databaseId },
  include: {
    shop: true,
  },
});

此时,Prisma会发出以下SQL查询:

SELECT `t1`.`id`,`t1`.`name`,`t1`.`created_at` AS `createdAt`,`t1`.`updated_at` AS `updatedAt`,
    (
        SELECT COALESCE(JSON_ARRAYAGG(`__prisma_data__),CONVERT('[]', JSON)) AS `__prisma_data__`
        FROM (
            SELECT `t4`.`__prisma_data__`
            FROM (
                SELECT JSON_OBJECT('id',`t3`.`id`,'name',`t3`.`name`,'createdAt',`t3`.`created_at`,'updatedAt',`t3`.`updated_at`) AS `__prisma_data__`
                FROM(
                    SELECT `t2`.*
                    FROM `shop` AS `t2`
                    WHERE `t1`.`id` = `t2`.`company_id`
                ) AS `t3`
            ) AS `t4`
        ) AS `t5`
    ) AS `shops`
FROM `company` AS `t1`
WHERE (`t1`.`id` = @id)
LIMIT 1;

虽然发出的查询比我们预期的要复杂,但它通过嵌套的子查询而非传统的JOIN方式来获取数据。

发布计划

尽管relationJoins功能的实际查询行为与预期有所偏差,Prisma团队仍计划对其进行进一步优化。

根据2024年11月14日的讨论,Prisma团队尚未宣布正式版本发布的具体计划,但该功能的改进工作已经提上日程,且将优先处理。

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
puzzled
Just do it.

评论(0)

添加评论