我是jsonb请求的新手,但遇到了问题。在“项目”表中,我有“ id”和“数据” jsonb。这是看起来像数据的东西:
[
{
"paramId": 3,
"value": "dog"
},
{
"paramId": 4,
"value": "cat"
},
{
"paramId": 5,
"value": "fish"
},
{
"paramId": 6,
"value": "",
"fields": [
{
"paramId": 3,
"value": "cat"
},
{
"paramId": 4,
"value": "dog"
}
]
},
{
"paramId": 6,
"value": "",
"fields": [
{
"paramId": 5,
"value": "cat"
},
{
"paramId": 3,
"value": "dog"
}
]
}
]
数据中的值始终是内部包含对象的数组,但是有时对象可以具有内部包含对象的“字段”值。最多深一层。
如何选择项目的ID,例如包含“ paramId”:3和“ value”:“ cat”的对象,以及具有“ paramId”:5和“ value”的对象,例如'% ish%'。
我已经找到了一种方法,当对象位于0级时
SELECT i.*
FROM items i
JOIN LATERAL jsonb_array_elements(i.data) obj3(val) ON obj.val->>'paramId' = '3'
JOIN LATERAL jsonb_array_elements(i.data) obj5(val) ON obj2.val->>'paramId' = '5'
WHERE obj3.val->>'valeur' = 'cat'
AND obj5.val->>'valeur' LIKE '%ish%';
但是我不知道如何在字段数组中搜索字段(如果存在)。
在此先感谢您的帮助。
编辑:
看来我的问题不清楚。我会尝试做得更好。
我要做的是在“数据”列中找到与我的搜索条件相匹配的所有“项目”。这无需查看对象是处于第一级还是在对象的“字段”键内。 再举一个例子。如果我搜索,则应选择此记录:
'paramId': 3 AND 'value': 'cat
'paramId': 4 AND 'value': LIKE '%og%'
匹配的对象位于带有'paramId':6的对象的'fields'键中,我不知道该怎么做。
答案 0 :(得分:1)
这可以使用JSON/Path expression表示,而无需取消嵌套
要搜索paramId = 3和value ='cat'
select *
from items
where data @? '$[*] ? ( (@.paramId == 3 && @.value == "cat") || exists( @.fields[*] ? (@.paramId == 3 && @.value == "cat")) )'
$[*]
部分遍历第一级数组的所有元素。要检查fields
数组中的元素,可以使用exists()
运算符来嵌套表达式。 @.fields[*]
遍历fields
数组中的所有元素,并再次应用相同的表达式。我看不出有办法避免重复值的方法。
对于“喜欢”情况,可以使用like_regex:
select *
from items
where data @? '$[*] ? ( (@.paramId == 4 && @.value like_regex ".*og.*") || exists( @.fields[*] ? (@.paramId == 4 && @.value like_regex ".*og.*")) )'
答案 1 :(得分:0)
到目前为止,我已经找到了一种解决方案,但是它并不是很干净,我不知道它在生产1000万条记录时的性能如何。
SELECT i.id, i.data
FROM ( -- A;
select it.id, it.data, i as value
from items it,
jsonb_array_elements(it.data) i
union
select it.id, it.data, f as value
from items it,
jsonb_array_elements(it.data) i,
jsonb_array_elements(i -> 'fields') f
) as i
WHERE (i.value ->> 'paramId' = '5' -- B1;
AND i.value ->> 'value' LIKE '%ish%')
OR (i.value ->> 'paramId' = '3' -- B2;
AND i.value ->> 'value' = 'cat')
group by i.id, i.data
having COUNT(*) >= 2; -- C;
A:我“拉平”第一层和第二层(第二层位于“字段”键中)
B1,B2:这是我的搜索条件
C:我确保所有字段都符合条件。如果3个条件-> COUNT(*)> = 3
对我来说,这看起来确实不干净。它是为开发目的而工作的,但我认为有更好的方法来实现它。
如果有人有一个主意,多谢他/她!