PostgreSQL में jsonb सरणी से विशेष वस्तु कैसे प्राप्त करें?


16

मेरे पास 'उपयोगकर्ता' नाम का एक क्षेत्र है जो एक json सरणी रखता है जो मोटे तौर पर इस तरह दिखता है:

"user":

[{ "_id" : "1", "count" : "4" }, { "_id" : "3", "count": "4"}]

अब मुझे एक क्वेरी चाहिए:

select count from tablename where id = "1"

मैं countPostgreSQL 9.4 में json ऑब्जेक्ट्स की एक सरणी से विशेष फ़ील्ड प्राप्त करने में सक्षम नहीं हूं ।

जवाबों:


17

यह सामान्यीकृत स्कीमा में अपने मूल्यों को संग्रहीत करने के लिए बहुत अधिक कुशल होगा। उसने कहा, आप इसे अपने वर्तमान सेटअप के साथ भी काम कर सकते हैं।

मान्यताओं

इस तालिका की परिभाषा मानते हुए:

CREATE TABLE tbl (tbl_id int, usr jsonb);

"उपयोगकर्ता" एक आरक्षित शब्द है और इसे कॉलम नाम के रूप में उपयोग करने के लिए दोहरे उद्धरण की आवश्यकता होगी। ऐसा मत करो। मैं usrइसके बजाय का उपयोग करें ।

सवाल

क्वेरी उतनी तुच्छ नहीं है जितनी (अब हटाई गई) टिप्पणियों से ऐसा लगता है:

SELECT t.tbl_id, obj.val->>'count' AS count
FROM   tbl t
JOIN   LATERAL jsonb_array_elements(t.usr) obj(val) ON obj.val->>'_id' = '1'
WHERE  t.usr @> '[{"_id":"1"}]';

हैं 3 बुनियादी कदम :

1. योग्य पंक्तियों को सस्ते में पहचानें

WHERE t.usr @> '[{"_id":"1"}]'JSON सरणी में मिलान ऑब्जेक्ट के साथ पंक्तियों की पहचान करता है। अभिव्यक्ति jsonbस्तंभ पर एक सामान्य GIN सूचकांक का उपयोग कर सकती है , या अधिक विशिष्ट ऑपरेटर वर्ग के साथ jsonb_path_ops:

CREATE INDEX tbl_usr_gin_idx ON tbl USING gin (usr jsonb_path_ops);

जोड़ा गया WHEREखंड तार्किक रूप से बेमानी है , लेकिन सूचकांक का उपयोग करना आवश्यक है। ज्वाइन क्लॉज में अभिव्यक्ति समान स्थिति को लागू करती है, लेकिन अब तक क्वालीफाई करने वाली प्रत्येक पंक्ति में सरणी को हटा देने के बाद ही । इंडेक्स सपोर्ट के साथ, पोस्टग्रेज केवल उन पंक्तियों को प्रोसेस करता है जिनमें शुरू करने के लिए एक क्वालिफाइंग ऑब्जेक्ट होता है। छोटी तालिकाओं के साथ ज्यादा फर्क नहीं पड़ता है, बड़ी तालिकाओं और केवल कुछ योग्य पंक्तियों के साथ एक बड़ा अंतर बनाता है ।

सम्बंधित:

2. सरणी में मिलान वस्तु (ओं) को पहचानें

के साथ सबसे असामान्य jsonb_array_elements()। ( unnest()केवल पोस्टग्रेज्ड सरणी प्रकारों के लिए अच्छा है।) चूंकि हम केवल वास्तव में मिलान वाली वस्तुओं में रुचि रखते हैं, तुरंत शामिल होने वाली स्थिति में फ़िल्टर करें।

सम्बंधित:

3. नेस्टेड कुंजी के लिए निकालें मूल्य 'count'

योग्यता के बाद वस्तुओं को निकाला गया है, बस obj.val->>'count':।


2
कहाँ से obj(value)आता है? उस पर है LATERAL JOIN, jsonb_array_elementsया कहीं और?
टायलर डेविट

ऐसा लगता है कि फॉर्मेटिंग ने पंगा ले लिया होगा। क्या मैं इसे सही ढंग से पढ़ रहा हूं JOIN LATERAL jsonb_array_elements(t.usr) obj(value) is short for JOIN LATERAL jsonb_array_elements(t.usr) AS obj(value)और obj(value)यह एक तालिका और स्तंभ उपनाम है? इस उदाहरण में, यदि objएक तालिका उर्फ ​​है, तो यह किसके लिए एक अन्य नाम है? सेट से लौटे jsonb_array_elements?
टायलर डेविट

1
हाँ, और हाँ। मैंने अपनी तल्ख टिप्पणी को हटा दिया।
इरविन ब्रान्डेसटेटर

क्या स्तंभ उपनाम का उपयोग करने की आवश्यकता है? मेरे परीक्षण में, JOIN LATERAL jsonb_array_elements(t.usr) obj ON obj->>'_id' = '1'एक ही प्रभाव था (एक बार जब आप का चयन करने के लिए उपयोग valueकरने के लिए कथन का अद्यतन करते हैं val)। ऐसा प्रतीत होता है कि jsonb_array_elements(t.usr)केवल एक कॉलम के साथ एक तालिका लौटाता है। क्या पोस्टग्रैज स्मार्ट हो रहा है और यह महसूस कर रहा obj ->>है कि जैसा है वैसा ही है obj.val ->>?
टायलर डेविट २ '’१

केवल एक कॉलम के साथ, Postgres किसी दिए गए उपनाम का उपयोग तालिका और स्तंभ नाम के रूप में करता है । मैं अभी स्पष्ट हो रहा हूं क्योंकि कई सेट-रिटर्न फ़ंक्शन हैं जो एक से अधिक कॉलम लौटाते हैं।
इरविन ब्रान्डेसटेटर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.