postgresql SQLAlchemy根据JSONB中的嵌套键进行过滤

8xiog9wr  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(2)|浏览(138)

我有一个JSONB字段,它有时有嵌套的键。示例:

{"nested_field": {"another URL": "foo", "a simple text": "text"},
 "first_metadata": "plain string",
 "another_metadata": "foobar"}

如果我做了

.filter(TestMetadata.metadata_item.has_key(nested_field))

我得到了这张唱片。
如何搜索嵌套键的存在?("a simple text"

0mkxixxg

0mkxixxg1#

对于SQLAlchemy,以下内容应该适用于您的测试字符串:

class TestMetadata(Base):
    id = Column(Integer, primary_key=True)
    name = Column(String)
    metadata_item = Column(JSONB)

根据JSONB的SQLAlchemy文档(搜索 Path index operations 示例):

expr = TestMetadata.metadata_item[("nested_field", "a simple text")]
q = (session.query(TestMetadata.id, expr.label("deep_value"))
     .filter(expr != None)
     .all())

它应该生成下面的SQL

SELECT  testmetadata.id AS testmetadata_id, 
        testmetadata.metadata_item #> %(metadata_item_1)s AS deep_value
FROM    testmetadata
WHERE  (testmetadata.metadata_item #> %(metadata_item_1)s) IS NOT NULL
-- @params: {'metadata_item_1': u'{nested_field, a simple text}'}
a11xaf1n

a11xaf1n2#

更新Postgres 12+

使用jsonpath运算符**@?**:

SELECT EXISTS (
   SELECT FROM testmetadata
   WHERE  metadata_item @? '$.nested_field."a simple text"'
   );

如果(且仅当)jsonb值具有嵌套键,则返回true
可以通过jsonb列(metadata_item)上的普通GIN索引或更专门的jsonb_path_ops索引来支持。参见:

  • 查询JSON数组元素中的键
  • Postgres动态值的jsonb查询

老版本原始答案

此查询在使用-> operator提取嵌套JSON对象后,使用**?**运算符测试嵌套字段是否存在:

SELECT EXISTS (
   SELECT FROM testmetadata
   WHERE  metadata_item -> 'nested_field' ? 'a simple text'
   );

请注意,普通GIN索引不支持此查询。您需要在metadata_item->'nested_field'上使用expression index来加快速度。

CREATE INDEX testmetadata_special_idx ON testmetadata
USING gin ((metadata_item->'nested_field'));

手册中有一个类似案例的例子。

相关问题