如何使用Jsonb从给定日期检索消息?

时间:2016-12-22 22:23:24

标签: sql postgresql jsonb

我有下表:

CREATE TABLE tbl (tbl_id int, messages jsonb);
CREATE INDEX index_tbl ON tbl USING gin (messages);

将JSON消息作为数组:

[{"user_id":1,"created_at":"2016-12-20","content":"Suspendisse accumsan tortor quis turpis. Sed ante."},
 {"user_id":2,"created_at":"2016-12-20","content":"Morbi sem mauris tibulum sagittis sapien."},
 {"user_id":1,"created_at":"2016-10-21","content":"In blandit ultrices enim. Phasellus id sapien in sapien iaculis congue."},
 {"user_id":3,"created_at":"2016-11-20","content":"Quisque ut erat. Curabitur gravida nisi at nibh. In hac habitasse platea dictumst."},
 {"user_id":4,"created_at":"2016-12-21","content":"Nunc rhoncus dui vel sem. Sed sagittis. ectus. Pellentesque at nulla. Suspendisse potenti. Cras in purus eu magna vulputate luctus."},
 {"user_id":6,"created_at":"2016-12-21","content":"Praesent id massa id nisl venenatis lacinia. iaculis congue."}]

如何在一个月内选择用户所在的邮件? 例如,12月份的用户只返回用户2,4和6的消息,因为用户1也在11月份。

1 个答案:

答案 0 :(得分:2)

这将返回所有..

  

用户仅在一个月内的消息

WITH msg AS (
   SELECT tbl_id
        ,(msg->>'user_id')::int                                      AS user_id
        , date_trunc('month', (msg->>'created_at')::timestamp)::date AS created_month
        , msg->>'content'                                            AS content
   FROM   tbl t, jsonb_array_elements(t.messages) msg
   )
SELECT m.*
FROM  (
   SELECT user_id
   FROM   msg 
   GROUP  BY 1
   HAVING count(DISTINCT created_month) = 1
   ) u
JOIN msg m USING (user_id);
  1. 使用jsonb_array_elements()解析JSON数组。

  2. 提取相关键的值。只有日期的月份相关,请使用date_trunc()并将结果投回date

  3. 在步骤 1。 2生成的CTE msg上运行实际查询。识别仅在一个月内发布的用户 - 跨整个表格,而不仅仅是一排。你没有澄清,我选择了这种解释。

  4. 自我加入同一个CTE msg以返回标识用户的所有消息。

  5. GIN索引无济于事,因为您需要以任何方式检查每个数组元素。

    将消息存储在规范化的表格中,对于您的查询来说更简单,更快捷:

    message (user_id int, created_at date, content text)