我有一个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"
)
答案 0 :(得分:13)
使用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}'}
答案 1 :(得分:1)
在使用?
operator提取嵌套的JSON对象后,此查询使用->
operator测试嵌套字段是否存在:
SELECT EXISTS (
SELECT 1
FROM testmetadata
WHERE metadata_item->'nested_field' ? 'a simple text'
);
请注意,普通GIN索引不支持此查询。 <{1}} metadata_item->'nested_field'
需要expression index才能快速完成此操作。
CREATE INDEX testmetadata_special_idx ON testmetadata
USING gin ((metadata_item->'nested_field'));
类似案例有example in the manual。