[strapi]修复:关系未按正确顺序返回

2024-05-13 521 views
1
它有什么作用?

在实体中删除或添加关系时,同一内容类型的其他实体会重新排序相同的关系。

原因:我们正在更新其他实体的顺序,而我们应该只更新相反的顺序。

上下文:给定作者 -> 文章之间的双向关系,连接表:

| author_id | article_id | article_order | author_order

- `article_order` is the order of articles in author entities
- `author_order` is the order of authors in article entities

我们保留这两个订单,因为双方都有关系。因此,当更新作者并添加文章关系时,我们不仅更新article_order,而且还更新author_order(反面)。

在更新订单值的 SQL 查询之前是:

UPDATE
  :joinTable: as a,
  (
    SELECT
      id,
      ROW_NUMBER() OVER ( PARTITION BY :joinColumn: ORDER BY :orderColumn:) AS src_order,
      ROW_NUMBER() OVER ( PARTITION BY :inverseJoinColumn: ORDER BY :inverseOrderColumn:) AS inv_order
    FROM :joinTable:
    WHERE :joinColumn: = :id OR :inverseJoinColumn: IN (:inverseRelIds)
  ) AS b
SET :orderColumn: = b.src_order, :inverseOrderColumn: = b.inv_order
WHERE b.id = a.id;

问题是,与:inverseJoinColumn: IN (:inverseRelIds)(使用相同关系的其他实体)的所有匹配也更新了 src_order 。

为了解决这个问题,查询被分成两部分:

-- Update order column
  UPDATE :joinTable: as a,
  (
    SELECT
      id,
      ROW_NUMBER() OVER ( PARTITION BY :joinColumn: ORDER BY :orderColumn:) AS src_order,
    FROM :joinTable:
    WHERE :joinColumn: = :id
  ) AS b
  SET :orderColumn: = b.src_order
  WHERE b.id = a.id;

-- Update inverse order column
  UPDATE :joinTable: as a,
  (
    SELECT
      id,
      ROW_NUMBER() OVER ( PARTITION BY :inverseJoinColumn: ORDER BY :inverseOrderColumn:) AS inv_order
    FROM :joinTable:
    WHERE :inverseJoinColumn: IN (:inverseRelIds)
  ) AS b
  SET :inverseOrderColumn: = b.inv_order
  WHERE b.id = a.id;

我们正在引入另一个数据库请求,但我没有看到解决此问题的任何其他方法。

为什么需要它? 如何测试呢?

参见测试。

相关问题

修复https://github.com/strapi/strapi/issues/16961

回答

7

@jhoward1994我认为这个实现的排序还有另一个问题,我现在正在重构它。

9

@jhoward1994 对于所做的更改感到抱歉,现在应该可以正常工作了。测试没有问题(只是关系在内容管理器 api 中以相反的顺序返回)

我将添加额外的测试,这样这个问题就不会再次发生:)

9

首先,感谢您在这个问题上的工作!

我们正在引入另一个数据库请求,但我没有看到解决此问题的任何其他方法。

由于您已经将其拆分并为其编写了测试,因此这可能是一个有争议的问题,但如果数据库请求的数量确实是一个问题,那么我认为您可以将其保留为 1 个请求,但使用稍微复杂的 WHERE 子句。

旧(破损):

WHERE :joinColumn: = :id OR :inverseJoinColumn: IN (:inverseRelIds)

新的(已修复?):

WHERE :joinColumn: IN (SELECT DISTINCT :joinColumn: FROM :joinTable: WHERE :inverseJoinColumn: IN (:inverseRelIds))

实际上,我认为从可读性的角度来看,将其拆分是正确的事情,但正如我所说,如果数据库请求的数量确实是一个问题,那么上述 SQL 应该可以解决该错误。

3

你好!!喜欢在这里进行数据库查询对话吗?

我将探索您的解决方案,它看起来像是一个干净的解决方案?我唯一担心的是有太多的行点击。我们将重新排序比严格必要的更多的行。

非常感谢您的建议,我会测试和分析!

2

我知道这超出了你的控制范围,马克,但考虑到我们看到的查询不断增加,我真的希望我们能够选择为那些不需要/不想要它的人禁用关系排序。

8

我只能同意你的观点@derrickmehaffy,从后端角度来看,这样做不会有什么大麻烦,@joshuaellis 你认为我们可以以一种干净的方式禁用对整个应用程序的重新排序吗?

使用配置,或者只是查看加载的关系是否具有顺序字段。

我们还有其他计划来减少您可能也喜欢的查询数量!例如仅更新用户更新的字段,而不是整个条目。

1

我只能同意你的观点@derrickmehaffy,从后端角度来看,这样做不会有什么大麻烦,@joshuaellis 你认为我们可以以一种干净的方式禁用对整个应用程序的重新排序吗?

使用配置,或者只是查看加载的关系是否具有顺序字段。

我们已经在 FE 同步中讨论过这一点,我们之前不想支持这一点,因为这感觉就像是必须使用大量细致入微的 ui 功能来处理此问题的一扇门,这些功能最终会使应用程序的管理变得更加复杂。跑步。但是,如果您能够就为什么我们应该使用用户数据/访谈以及应用程序数据提出一个坚实的论据,那么这将为我们提供更有力的论据吗?

4

@joshuaellis 不知道它的技术复杂性。唯一的论据是性能。重新排序极大地增加了我们执行的数据库请求的数量,如果您的资源有限或想要扩展您的应用程序,则需要付出一定的代价。

我想说,如果能够切换该功能,那就太好了,但如果它涉及很大的复杂性,我们可以找到其他方法。

在 V5 中,我们将重构关系,并且肯定会提高重新排序的性能。此外,我们还考虑了其​​他重要的事情,这些事情将进一步提高性能(根据差异而不是完整实体更新实体)

6

@joshuaellis 不知道它的技术复杂性。唯一的论据是性能。重新排序极大地增加了我们执行的数据库请求的数量,如果您的资源有限或想要扩展您的应用程序,则需要付出一定的代价。

我想说,如果能够切换该功能,那就太好了,但如果它涉及很大的复杂性,我们可以找到其他方法。

在 V5 中,我们将重构关系,并且肯定会提高重新排序的性能。此外,我们还考虑了其​​他重要的事情,这些事情将进一步提高性能(根据差异而不是完整实体更新实体)

恕我直言,除非我们有一些可靠的指标来主动采取行动,否则我们应该对此做出反应。我并不完全反对它,只是试图在价值和复杂性之间行走?

是的,随着其他事情的进展,从长远来看这可能不是问题!

7

确实,最大的原因是性能。发布一个小版本来添加新功能在很大程度上是出乎意料的,突然间性能对用户造成了巨大的打击,而且无法关闭它。

我希望 v5 能够让我们解决性能问题,但有人担心,由于维度的复杂性增加,性能会变得更糟。

3

确实,最大的原因是性能。发布一个小版本来添加新功能在很大程度上是出乎意料的,突然间性能对用户造成了巨大的打击,而且无法关闭它。

我希望 v5 能够让我们解决性能问题,但有人担心,由于维度的复杂性增加,性能会变得更糟。

理想情况下,我们应该有某种测试套件来监控性能?这是完全可以理解的担忧领域。

1

发布一个小版本来添加新功能在很大程度上是出乎意料的,突然间性能对用户造成了巨大的打击,而且无法关闭它。

有一种方法来关闭逆关系的关系排序对我们来说比关闭或打开毯子更有帮助。在我们拥有的所有多对多关系中,逆序对我们来说并不重要,因此只会增加代码和 UI 的额外复杂性。

9

@mpuxted 完全,我认为这是一个有效的案例,现在我们计划重构关系,我们将认真考虑这一点。我目前无法给出确切的日期,但这是我们最终会做的事情。