如何在SQLAlchemy中的JSON PostgreSQL列的嵌套键上创建索引?

7
这是一件棘手的问题,希望有人能够通过发布创建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正在尝试索引不存在的数据并且变得混乱了。 - jumbopap
2个回答

3

我找到的解决方案是使用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);

0

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);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接