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

2024-05-16 01:21:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个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"


Tags: texturl示例fieldstringfooanotherjsonb
2条回答

使用SQLAlchemy,以下内容应适用于测试字符串:

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

根据SQLAlchemy documentation of ^{}(搜索路径索引操作示例):

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}'}

使用^{} operator提取嵌套的JSON对象后,此查询将测试是否存在具有^{} operator的嵌套字段:

SELECT EXISTS (
   SELECT 1 
   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'));

对于类似的情况有一个example in the manual

相关问题 更多 >