【问题标题】:How to create an index on a nested key of a JSON PostgreSQL column in SQLAlchemy?如何在 SQLAlchemy 中的 JSON PostgreSQL 列的嵌套键上创建索引?
【发布时间】:2016-04-13 10:39:09
【问题描述】:

这是一个棘手的问题,希望有人可以通过发布一个/他们使用 SQLAlchemy 在 PostgreSQL 中的 JSON(或 JSONB)列的嵌套键上创建索引的方法来帮助我们所有人(我特别使用 Flask-SQLAlchemy,但我认为这对答案没有太大影响)。

我已经尝试了以下索引创建的各种排列,并获得了从关键错误到“c”不是属性到该表达式不支持运算符“getitem”的所有内容。

任何帮助将不胜感激。

# Example JSON, the nested property is "level2_A"
{
    'level1': { 
        'level2_A': 'test value', 
    } 
}

class TestThing(db.Model):
    __tablename__ = 'test_thing'

    id = db.Column(db.BigInteger(), primary_key=True)
    data = db.Column(JSONB)

    __table_args__ = (db.Index('ix_1', TestThing.data['level1']['level2_A']), 
            db.Index('ix_2', data['level1']['level2_A'].astext), 
            db.Index('ix_3', "TestThing.c.data['level1']['level2_A'].astext"), 
            db.Index('ix_4', TestThing.c.data['level1']['level2_A'].astext), 
            db.Index('ix_5', "test_thing.c.data['level1']['level2_A']"), 
                      )

# db.Index('ix_1', TestThing.data['level1']['level2_A'])
# db.Index('ix_2_t', "test_thing.data['level1']['level2_A']")
# db.Index('ix_3', "TestThing.c.data['level1']['level2_A'].astext")
# db.Index('ix_4', TestThing.c.data['level1']['level2_A'].astext)
# db.Index('ix_5', "test_thing.c.data['level1']['level2_A']")

【问题讨论】:

  • 您是否尝试过在列中提供默认数据?如果您遇到关键错误,可能是因为 SQLAlchemy 正在尝试索引不存在的数据并且变得混乱。

标签: python json postgresql sqlalchemy flask-sqlalchemy


【解决方案1】:

我找到的解决方案是使用text 创建函数索引。

这里有两个示例索引,具体取决于您是否要将结果转换为文本:

from sqlalchemy.sql.expression import text
from sqlalchemy.schema import Index

class TestThing(db.Model):
    __tablename__ = 'test_thing'

    id = db.Column(db.BigInteger(), primary_key=True)
    data = db.Column(JSONB)

    __table_args__ = (
        Index("ix_6", text("(data->'level1'->'level2_A')")),
        Index("ix_7", text("(data->'level1'->>'level2_A')")),
    )

这会导致以下 SQL 来创建索引:

CREATE INDEX ix_6 ON test_thing(((data -> 'level1'::text) -> 'level2_A'::text) jsonb_ops);
CREATE INDEX ix_7 ON test_thing(((data -> 'level1'::text) ->> 'level2_A'::text) text_ops);

【讨论】:

    【解决方案2】:
    
    class TestThing(db.Model):
        __tablename__ = 'test_thing'
    
        id = db.Column(db.BigInteger(), primary_key=True)
        data = db.Column(JSONB)
    
        __table_args__ = (
            Index("ix_7", "(data->'level1'->>'level2_A')"),
        )
    

    理想情况下,这应该在没有 text() 的情况下工作 因为-> 返回 json(b) 而->> 返回文本:

    将生成的查询将是

    CREATE INDEX ix_7 ON test_thing(((data->'level1')->>'level2_A') text_ops);

    【讨论】:

      猜你喜欢
      • 2014-08-21
      • 1970-01-01
      • 1970-01-01
      • 2017-07-12
      • 1970-01-01
      • 2016-09-20
      • 2019-07-13
      • 2012-09-06
      • 2016-11-18
      相关资源
      最近更新 更多