简体   繁体   English

Postgres JSONB 查询简化

[英]Postgres JSONB query simplification

I have some working code which pulls records from a forms table where 'mail@example.com' appears as a JSON value in one of the JSONB fields, column_a , column_b , column_c , or column_d .我有一些工作代码从表单表中提取记录,其中 'mail@example.com' 在 JSONB 字段之一、 column_acolumn_bcolumn_ccolumn_d显示为 JSON 值。

SELECT * 
FROM forms f
WHERE exists (SELECT * 
              FROM jsonb_each_text(f.column_a) as e(ky,val)
              WHERE e.val = 'mail@example.com')   
UNION

SELECT * 
FROM forms f
WHERE exists (SELECT * 
              FROM jsonb_each_text(f.column_b) as e(ky,val)
              WHERE e.val = 'mail@example.com')
UNION

SELECT * 
FROM forms f
WHERE exists (SELECT * 
              FROM jsonb_each_text(f.column_c) as e(ky,val)
              WHERE e.val = 'mail@example.com')
UNION

SELECT * 
FROM forms f
WHERE exists (SELECT * 
              FROM jsonb_each_text(f.column_d) as e(ky,val)
              WHERE e.val = 'mail@example.com');

The JSON in the columns is similar to:列中的 JSON 类似于:

{ "xyz":"mail@example.com", "def":"mail2@example.com", "lmn":"mail3@example.com" }

Although the code works, it looks highly repetitive/long-winded.尽管代码有效,但它看起来高度重复/冗长。 Given that I can't change the JSON structure, is there are more concise way of building this query, and what indexes should I be building for those columns for the best performance?鉴于我无法更改 JSON 结构,是否有更简洁的方法来构建此查询,以及我应该为这些列构建哪些索引以获得最佳性能?

Why not use or ?为什么不使用or

SELECT f.* 
FROM forms f
WHERE EXISTS (SELECT * 
              FROM jsonb_each_text(f.column_a) as e(ky,val)
              WHERE e.val = 'mail@example.com'
             ) OR
      EXISTS (SELECT * 
              FROM jsonb_each_text(f.column_b) as e(ky,val)
              WHERE e.val = 'mail@example.com'
             ) OR
      . . .

Presumably, this also eliminates the need for duplicate elimination, so the query should be faster as well.据推测,这也消除了重复消除的需要,因此查询也应该更快。

EDIT:编辑:

If you want the sources, you can use correlated subqueries:如果需要源,可以使用相关子查询:

SELECT f.* 
FROM (SELECT f.*,
             EXISTS (SELECT * 
                     FROM jsonb_each_text(f.column_a) as e(ky,val)
                     WHERE e.val = 'mail@example.com'
                    ) as in_column_a,
             EXISTS (SELECT * 
                     FROM jsonb_each_text(f.column_b) as e(ky,val)
                     WHERE e.val = 'mail@example.com'
                    ) as in_column_b,
             . . .
      FROM forms f
     ) 
WHERE in_column_a OR in_column_b OR . . .

This is not quite as efficient, because it does not short-circuit the evaluation when it finds a match.这不是很有效,因为它在找到匹配时不会短路评估。 On the other hand, it lists all columns that have a match.另一方面,它列出了所有匹配的列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM