2016-09-18 73 views
0

我想基於經緯度和lng值進行查詢,但返回的行與價值存儲爲負值時的查詢不匹配。但是,當我查詢正值它按預期工作。我想知道是否有特定的方式我需要格式化我的查詢。Postgres JSONB:負數查詢

這裏有一些例子查詢證明怪異的結果:

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,但沒有返回行。但是,當我檢查大於40時,它將返回緯度爲-38.19523969999999的那一行。

任何幫助表示讚賞。

回答

3

你有兩個問題,或者是兩個版本的同一問題的更準確。在您的查詢:

select address from listing where 'address.coords.latitude' > '40' 

'address.coords.latitude'是一個字符串文字,而不是爲address JSON路徑; '40'也是一個字符串文字,而不是數字40。因此,您的WHERE子句僅僅比較兩個字符串文字,它並不比較嵌入在address列中的latitude和編號40。這意味着,在第一個查詢的WHERE子句中始終是假的:

=> 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:在specifie

#>>text[]
獲取JSON對象文字d路徑

所以你會說:

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 
+0

很好的答案!謝謝 – zlwaterfield

0

這是不正常的原因,因爲您正在比較JSON文本和文本值。

您應該將JSON值轉換爲適當的數字類型,並與數字進行比較。

例如:

select address from listing where ('address.coords.latitude')::numeric < 40; 
+0

但是''address.coords.latitude''仍然只是一個字符串,而不是JSON的路徑。 –