【问题标题】:SQLAlchemy filter according to nested keys in JSONBSQLAlchemy 根据 JSONB 中的嵌套键进行过滤
【发布时间】:2015-03-28 18:17:25
【问题描述】:

我有一个有时包含嵌套键的 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")

【问题讨论】:

    标签: python sql postgresql sqlalchemy jsonb


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 太棒了...恕我直言,目前尚不清楚路径索引是嵌套的 JSON,但也许只是我。顺便说一句 - 为了检查一个值,我宁愿使用内部:.filter(TestMetadata.metadata_item[key].astext == value) where key is the tuple
    • 当然,我虽然你的问题更多的是检查存在而不是检查值类型的东西。
    • 你是完全正确的......我需要它们(显然 impl. 是不同的,因为 has_key 不支持元组)
    • 如果the explicit value None存在,如何选择:{'nested_field': None}?
    • @van 知道如何检查顶级键是大于还是小于一个值?此外,对于嵌套键?
    【解决方案2】:

    在提取带有 -> 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-20
      • 2012-05-14
      • 1970-01-01
      • 2022-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多