我正在使用posttgres 9.4。我有一个名为"数据"的JSON类型列。 in" list"表和存储在其中的数据格式为
{
"pages":[
{
"pageName" : "test",
"components" : [
{
"name" : "comp1",
"type" : "text",
"value" : "val1"
},
{
"name" : "comp2",
"type" : "grade",
"value" : 7
}
]
}
]
}
我需要查询具有" grade"类型的组件的所有列表的所有组件值。 我目前使用此查询:
select avg((comp->>'value')::int)
from list,
jsonb_array_elements(data->'pages') as page ,
jsonb_array_elements(page->'components') as comp
where comp @> '{"type":"grade"}' and (comp->>'value') IS NOT NULL;
问题是我认为这是一个效率非常低的问题,而且从解释中可以看出,它没有使用我在数据列上设置的任何索引作为使用GIN(数据jsonb_path_ops);
是否有更有效的方法来查询双嵌套对象?
答案 0 :(得分:0)
来自docs:
jsonb
的默认GIN运算符类支持@>
,?
,?&
和?|
运算符的查询。
因此,jsonb_array_elements
的使用不会使用任何索引(无论如何都不能使用它,因为它是一组返回函数)。
您可以做的是使用data @> '{"pages":[{"components":[{"type": "grade"}]}]}'
从表中预先过滤您的行(BTW:data
是一个关键字,请不要使用它作为专栏名称。)
但您仍需要comp @> '{"type":"grade"}'
过滤器来排除同一行中包含至少一个成绩类型对象的任何非等级类型对象。
此外,您不需要(comp->>'value') IS NOT NULL
:avg()
在结果中不会计算NULL
。但是,您可能需要进行类型检查jsonb_typeof(comp->'value') = 'number'
,因为当comp->>'value'
不表示数字时,数字转换可能会抛出异常(JSON的数字的适当类型为{{ 1}} - 或numeric
- 在PostgreSQL中)
decimal