代码之家  ›  专栏  ›  技术社区  ›  Boaz

根据JSONB中嵌套键的SQLAlchemy筛选器

  •  8
  • Boaz  · 技术社区  · 9 年前

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

    2 回复  |  直到 5 年前
        1
  •  16
  •   FrEaKmAn    5 年前

    使用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}'}
    
        2
  •  1
  •   Erwin Brandstetter    9 年前

    此查询测试嵌套字段是否存在 ? operator ,在使用 -> operator :

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

    请注意,普通GIN索引不支持此查询。你需要一个 expression index 在…上 metadata_item->'nested_field' 让这一切变得更快。

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

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