在Postgres中索引和加入JSON数据

时间:2015-05-28 20:30:41

标签: json postgresql join indexing

我们有一个数据表,如下所示:

CREATE TABLE objects (
  id BIGSERIAL NOT NULL,  
  typeid BIGINT NOT NULL,   
  fullobject JSON,
  PRIMARY KEY (id),  
...  
);

CREATE TABLE types (
  id BIGSERIAL NOT NULL,     
  type VARCHAR(255),
  PRIMARY KEY (id), 
...    
);
在objects.fullobject列中的

是用户和组织的JSON数据,如:

// id: 1
{
 ...
"type":"1",   // user
"orgs":[
   {"id":"2", "position":"foo"},
   {"id":"2", "position":"bar"},
   {"id":"3", "position":"foo"},
  ]
}

// id: 2
{
 ...
"type":"2",  // org
"name":"Org 1"
}

// id: 3
{
 ...
"type":"2",  // org
"name":"Org 2"
}

问题是,如果我想根据组织名称找到用户,我该如何进行加入?

我不确定是否可以在用户内的组织数据上创建正确的索引。

我能想到的两个解决方案是:

  1. 创建一个单独的文本属性,其中包含用户的组织ID,然后根据该组织进行连接(例如" searchableOrg":" | org1 | org2 | &#34)。
  2. 然后查询如下:

    SELECT * from objects user
    INNER JOIN types usertype ON usertype.id = user.typeid
    INNER JOIN objects org ON json_extract_path(user.fullobject, 'searchableOrg') LIKE '%|' || org.id || '|%'
    INNER JOIN types usertype ON usertype.id = user.typeid
    WHERE json_extract_path(org.fullobject, 'name') LIKE '%whatever%'
    AND usertype.type = 'user'
    AND orgtype.type = 'org'
    

    这里我可以在json_extract_path(user.fullobject,' searchableOrg')和json_extract_path(org.fullobject,' name')上建立索引。

    但是,如果我们向用户的组织成员身份添加诸如开始日期或结束日期之类的内容,并且需要进一步过滤此加入,则此功能无效。

    1. 创建一个触发器,当用户被创建/更新/删除时,修改包含用户组织成员资格的表(userorgtable)并进行联接。
    2. 我还没有看过触发器,但希望查询类似于:

      SELECT * from objects user
      INNER JOIN userorgtable userorg ON user.id = userorg.userid
      INNER JOIN types usertype ON usertype.id = user.typeid
      INNER JOIN objects org ON userorg.orgid = org.id
      INNER JOIN types orgtype ON orgtype.id = org.typeid
      WHERE json_extract_path(org.fullobject, 'name') LIKE '%whatever%'
      AND usertype.type = 'user'
      AND orgtype.type = 'org'
      

      在这种情况下,如果我们需要向连接添加更多属性(例如开始日期和结束日期),我们可以将它们放在userorgtable中并添加条件,如:

      AND userorg.startdate < CURRENT_DATE()
      

      还有其他选择吗?也许使用更多的Postgres JSON函数?

      提前致谢

0 个答案:

没有答案