【问题标题】:postgresql: Filter in JSON arraypostgresql:在 JSON 数组中过滤
【发布时间】:2018-12-03 10:02:24
【问题描述】:

假设我们有一个表items,其中包含nameattributes 列:

CREATE TABLE students (
  name VARCHAR(100),
  attributes JSON
)

其中 attributes 是一组(总是结构相同的)JSON 文档,例如

[{"name":"Attribute 1","value":"Value 1"},{"name":"Attribute 2","value":"Value 2"}]

我现在想查找任何属性值与某物匹配的所有学生(例如Foo%)。 Here's a playground example.

我意识到这并不是最直接的设计,但现在它是我必须使用的,尽管这样的搜索性能绝对是非常低效的当然是一个有效的问题。

【问题讨论】:

  • json[] 永远没有意义。最好在 json 列中存储一个“真实”的 JSON 数组。
  • @a_horse_with_no_name 那也可以。我会把问题改成那样。

标签: sql postgresql


【解决方案1】:

你可以使用json_array_elements来访问元素,然后使用 ->> json 操作符来搜索一些值。

select s.*,j from 
  students  s 
   cross join lateral json_array_elements ( attributes ) as j
WHERE j->>'value' like 'Foo%'

Demo

编辑

现在的问题是交叉连接会“复制”行。是 有更好的方法来避免这种情况

使用 WITH ORDINALITY 为每个元素生成 id,然后使用 DISTINCT ON 获取每个学生的第一个/最后一个匹配项。

select DISTINCT ON (name) s.*,j.attr from 
students  s 
cross join lateral json_array_elements ( attributes ) WITH ORDINALITY as j(attr,id)
WHERE j.attr->>'value' like 'Value%'
ORDER BY name,j.id

Demo2

【讨论】:

  • 谢谢!横向交叉连接是我所缺少的(必须查找)。
  • 现在的问题是交叉连接会“复制”行。除了选择一个不同的 ID 列表并将其放入外部查询中,我在其中选择具有这些 ID 的实际行之外,是否有更好的方法来避免这种情况?
  • @IngoBürk :不确定您在说什么重复项,数组中每个 json 元素只有一行。您可以使用基于某些order byDISTINCT ON 将它们限制为每场比赛的最高/最低。您可能应该问另一个有关详细信息的问题。
  • 是的,它返回数组中每个元素的一行,但这不是预期的输出;预期输出是任何元素匹配的学生(即每个学生只有一次)。我对匹配的 JSON 元素不感兴趣,只是至少有一个匹配。我确实有点考虑这个问题的这一部分,因为这就是我提出问题的方式。
  • @IngoBürk :那么,您可以使用GROUP BY /DISTINCT ON 根据订单获取聚合/顶部元素。看我的其他答案。 herethis one
【解决方案2】:

您可能希望在这样的列上使用以下查询,因为我有一个 JSON 列,我使用以下搜索 -

select * from table-name where column-name::text like '%whatever-to-be-searched%'

【讨论】:

  • 这会产生很多误报。
猜你喜欢
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 2021-05-29
  • 2013-01-19
  • 2016-05-24
  • 1970-01-01
  • 2017-11-24
  • 2014-07-05
相关资源
最近更新 更多