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

How to create jsonb index using GIN on SQLAlchemy?

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

Index("mytable_data_idx_id_key", Mytable.data['id'].astext, postgresql_using='gin')

但是我遇到了这个错误。

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'))"]

有什么方法可以在 SQLAlchemy 上创建索引吗?

http://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#operator-classes 处的 PostgreSQL 特定 SQLAlchemy 文档提到了 postgresql_ops 字典以提供 PostgreSQL 使用的 "operator class",并提供了说明其用法的示例:

Index('my_index', my_table.c.id, my_table.c.data,
                        postgresql_ops={
                            'data': 'text_pattern_ops',
                            'id': 'int4_ops'
                        })

从实验来看,如果要为表达式索引指定 "operator class",似乎需要使用 text() 索引描述。所以,

db.Index(
    'ix_sample',
    sqlalchemy.text("(jsoncol->'values') jsonb_path_ops"),
    postgresql_using="gin")

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

{
  "values": ["first", "second", "third"],
  "other": "fields",
  "go": "here"
}

在 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()

我不知道自从上一个接受的答案以来 sqlalchemy 中的事情是否发生了变化,但在我工作的代码库中,这是通过以下方式完成的:

    __table_args__ = (
        db.Index(
            "index_TABLENAME_on_COLUMN_gin", 
            "COLUMN", 
            postgresql_using="gin",
        ),
    )

这将在 Postgresql 中创建预期的 GIN 索引。