Postgres JSONB:按负数查询
Postgres JSONB: query by negative numbers
我正在尝试基于 lat 和 lng 值进行查询,但是当值存储为负时,返回的行与我的查询不匹配。但是,当我查询正值时,它会按预期工作。我想知道是否需要特定的方式来格式化我的查询。
这里有一些示例查询来证明奇怪的结果:
QUERY 1
=======
db_development=# select address from listing where 'address.coords.latitude' < '40';
no rows returned.
QUERY 2
=======
db_development=# select address from listing where 'address.coords.latitude' > '40';
returned address:
{
"city":"Heathmere",
"state":"VIC",
"coords":{
"latitude":-38.19523969999999,
"longitude":141.6158994
},
"number":"1235",
"street":"Princes Highway",
"country":"Australia",
"zipcode":"3305",
"formatted":"Riversleigh, 1235 Princes Hwy, Heathmere VIC 3305, Australia"
}
如您所见,我正在尝试查找纬度小于 40 的行,但 returns 没有行。但是,当我检查大于 40 时,它 returns 纬度为 -38.19523969999999 的行。
感谢任何帮助。
这不像您预期的那样工作的原因是您正在将 JSON 文本与文本值进行比较。
您应该将 JSON 值转换为适当的类型,即数字,并与数字进行比较。
例如:
select address from listing where ('address.coords.latitude')::numeric < 40;
你有两个问题,或者同一个问题的两个版本更准确。在您的查询中:
select address from listing where 'address.coords.latitude' > '40'
'address.coords.latitude'
是一个字符串字面量,不是进入 address
JSON 的路径; '40'
也是一个字符串文字,而不是数字 40
。因此,您的 WHERE 子句只是比较两个字符串文字,而不是比较 address
列中嵌入的 latitude
与数字 40
。这意味着您的第一个查询中的 WHERE 子句始终为 false:
=> select 'address.coords.latitude' < '40' as correct;
correct
---------
f
(1 row)
并且第二个查询中的 WHERE 子句始终为真:
=> select 'address.coords.latitude' > '40' as confused;
confused
----------
t
(1 row)
如果你想深入了解你的 address
JSON,你想使用 #>>
operator:
#>>
text[]
Get JSON object at specified path as text
所以你会说:
address #>> array['coords', 'latitude']
看嵌入式latitude
;如果您或您的工具不喜欢 #>>
运算符,您也可以使用 jsonb_extract_path_text
function。然后你需要将该 text
值转换为一个数字以使比较正常工作并将该数字与普通(数字)40
:
进行比较
select address
from listing
where (address #>> array['coords', 'latitude'])::numeric > 40
与您的第一个查询类似:
select address
from listing
where (address #>> array['coords', 'latitude'])::numeric < 40
我正在尝试基于 lat 和 lng 值进行查询,但是当值存储为负时,返回的行与我的查询不匹配。但是,当我查询正值时,它会按预期工作。我想知道是否需要特定的方式来格式化我的查询。
这里有一些示例查询来证明奇怪的结果:
QUERY 1
=======
db_development=# select address from listing where 'address.coords.latitude' < '40';
no rows returned.
QUERY 2
=======
db_development=# select address from listing where 'address.coords.latitude' > '40';
returned address:
{
"city":"Heathmere",
"state":"VIC",
"coords":{
"latitude":-38.19523969999999,
"longitude":141.6158994
},
"number":"1235",
"street":"Princes Highway",
"country":"Australia",
"zipcode":"3305",
"formatted":"Riversleigh, 1235 Princes Hwy, Heathmere VIC 3305, Australia"
}
如您所见,我正在尝试查找纬度小于 40 的行,但 returns 没有行。但是,当我检查大于 40 时,它 returns 纬度为 -38.19523969999999 的行。
感谢任何帮助。
这不像您预期的那样工作的原因是您正在将 JSON 文本与文本值进行比较。
您应该将 JSON 值转换为适当的类型,即数字,并与数字进行比较。
例如:
select address from listing where ('address.coords.latitude')::numeric < 40;
你有两个问题,或者同一个问题的两个版本更准确。在您的查询中:
select address from listing where 'address.coords.latitude' > '40'
'address.coords.latitude'
是一个字符串字面量,不是进入 address
JSON 的路径; '40'
也是一个字符串文字,而不是数字 40
。因此,您的 WHERE 子句只是比较两个字符串文字,而不是比较 address
列中嵌入的 latitude
与数字 40
。这意味着您的第一个查询中的 WHERE 子句始终为 false:
=> select 'address.coords.latitude' < '40' as correct;
correct
---------
f
(1 row)
并且第二个查询中的 WHERE 子句始终为真:
=> select 'address.coords.latitude' > '40' as confused;
confused
----------
t
(1 row)
如果你想深入了解你的 address
JSON,你想使用 #>>
operator:
#>>
text[]
Get JSON object at specified path as text
所以你会说:
address #>> array['coords', 'latitude']
看嵌入式latitude
;如果您或您的工具不喜欢 #>>
运算符,您也可以使用 jsonb_extract_path_text
function。然后你需要将该 text
值转换为一个数字以使比较正常工作并将该数字与普通(数字)40
:
select address
from listing
where (address #>> array['coords', 'latitude'])::numeric > 40
与您的第一个查询类似:
select address
from listing
where (address #>> array['coords', 'latitude'])::numeric < 40