如何在SQLAlchemy上使用GIN创建jsonb索引?

Jon*_*use 9 python postgresql indexing sqlalchemy

这是为JSONB创建索引的当前代码.

Index("mytable_data_idx_id_key", Mytable.data['id'].astext, postgresql_using='gin')
Run Code Online (Sandbox Code Playgroud)

但我得到了这个错误.

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) data type text has no default operator class for access method "gin"
HINT:  You must specify an operator class for the index or define a default operator class for the data type.
 [SQL: "CREATE INDEX event_data_idx_id_key ON event USING gin ((data ->> 'id'))"]
Run Code Online (Sandbox Code Playgroud)

有没有办法在SQLAlchemy上创建索引?

wou*_*lee 6

PostgreSQL 特定的 SQLAlchemy 文档位于http://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#operator-classes提到了一个postgresql_ops字典来提供 PostgreSQL 使用的“运算符类”,并提供了说明其使用的示例:

Index('my_index', my_table.c.id, my_table.c.data,
                        postgresql_ops={
                            'data': 'text_pattern_ops',
                            'id': 'int4_ops'
                        })
Run Code Online (Sandbox Code Playgroud)

text()从实验来看,如果要为表达式索引指定“运算符类”,似乎需要使用索引描述。所以,

db.Index(
    'ix_sample',
    sqlalchemy.text("(jsoncol->'values') jsonb_path_ops"),
    postgresql_using="gin")
Run Code Online (Sandbox Code Playgroud)

...in__table_args__对于 ORM 模型,在jsonb包含字符串数组的字段上指定 GIN 索引,并允许高效查找,即匹配 JSON 数组字段中的任何字符串,如下所示:

{
  "values": ["first", "second", "third"],
  "other": "fields",
  "go": "here"
}
Run Code Online (Sandbox Code Playgroud)

在 PostgreSQL 中使用@>运算符进行查询将如下所示:

import sqlalchemy
from sqlalchemy.dialects import postgresql

query = session.query(MyModel).filter(
    sqlalchemy.type_coerce(MyModel.jsoncol['values'], postgresql.JSONB)
    .contains(sqlalchemy.type_coerce("second", postgresql.JSONB)))
results = query.all()
Run Code Online (Sandbox Code Playgroud)