दिलचस्प पोस्ट
मैं कैसे बता सकता हूँ अगर कोई स्ट्रिंग पायथन में खुद को दोहराता है? कॉफी स्क्रिप्ट लिखते समय AngularJS के लिए मैं वेबस्टॉर्म इंटेलिसेंस को कैसे सक्षम कर सकता हूं Ui-sref में यूआई-राउटर में नियंत्रक से पैरामीटर कैसे निकालें आईफोन ओएस 4.0 में ब्लॉक-आधारित एनीमेशन मैनेजमेंट क्या हैं? क्या एंड्रॉइड 'बंडल में कुछ सीमाएं हैं? एंड्रॉइड लॉक स्क्रीन छवि कैसे सेट करें बस त्रुटि क्या है? बयान ब्लॉक में चर गुंजाइश कुंजी पर आधारित PHP बहुआयामी सरणी को सॉर्ट करें? मेल संलग्नक गलत मीडिया प्रकार जीमेल एपीआई गतिविधि संदर्भ और अनुप्रयोग संदर्भ के बीच का अंतर स्विंग के साथ एक फाइल इन-पेन चुनना ऐप स्टोर पर अपलोड करते समय Xcode त्रुटि: "कोई उपयुक्त अनुप्रयोग रिकॉर्ड नहीं मिला" Emacs – कॉल करने में त्रुटि (सर्वर-प्रारंभ) डॉकर-मशीन में पोर्ट अग्रेषण?

एक JSON सरणी में एक तत्व खोजने के लिए सूचकांक

मेरे पास ऐसी तालिका है जो इस तरह दिखती है:

CREATE TABLE tracks (id SERIAL, artists JSON); INSERT INTO tracks (id, artists) VALUES (1, '[{"name": "blink-182"}]'); INSERT INTO tracks (id, artists) VALUES (2, '[{"name": "The Dirty Heads"}, {"name": "Louis Richards"}]'); 

ऐसे कई अन्य स्तंभ हैं जो इस प्रश्न से संबंधित नहीं हैं। उन्हें JSON के रूप में संग्रहीत करने का एक कारण है।

मैं क्या करने की कोशिश कर रहा हूं, उस ट्रैक को खोजना है जिसमें विशिष्ट कलाकार का नाम है (सटीक मिलान)

मैं इस प्रश्न का उपयोग कर रहा हूं:

 SELECT * FROM tracks WHERE 'ARTIST NAME' IN (SELECT value->>'name' FROM json_array_elements(artists)) 

उदाहरण के लिए

 SELECT * FROM tracks WHERE 'The Dirty Heads' IN (SELECT value->>'name' FROM json_array_elements(artists)) 

हालांकि, यह एक पूर्ण तालिका स्कैन करता है, और यह बहुत तेजी से नहीं है मैंने फ़ंक्शन के names_as_array(artists) उपयोग से एक GIN सूचक बनाने की कोशिश की names_as_array(artists) , और 'ARTIST NAME' = ANY names_as_array(artists) उपयोग किया है 'ARTIST NAME' = ANY names_as_array(artists) , हालांकि सूचकांक का उपयोग नहीं किया जाता है और क्वेरी वास्तव में काफी धीमी है

Solutions Collecting From Web of "एक JSON सरणी में एक तत्व खोजने के लिए सूचकांक"

jsonb में jsonb

नए द्विआधारी JSON डेटा प्रकार jsonb , पोस्टग्रेस 9.4 ने बड़े पैमाने पर बेहतर सूचकांक विकल्प पेश किए। अब आप सीधे jsonb सरणी पर jsonb सूचकांक प्राप्त कर सकते हैं:

 CREATE TABLE tracks (id serial, artists jsonb ); CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists); 

सरणी को रूपांतरित करने के लिए फ़ंक्शन के लिए कोई ज़रूरत नहीं है। यह एक क्वेरी का समर्थन करेगा:

 SELECT * FROM tracks WHERE artists @> '[{"name": "The Dirty Heads"}]'; 

@> नया jsonb "शामिल" ऑपरेटर है , जो GIN सूचकांक का उपयोग कर सकते हैं। (नहीं के लिए प्रकार json , केवल jsonb !)

या आप सूचकांक के लिए अधिक विशिष्ट, गैर-डिफ़ॉल्ट jsonb_path_ops ऑपरेटर वर्ग jsonb_path_ops का उपयोग करते हैं:

 CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists jsonb_path_ops ); 

एक ही क्वेरी


अगर artists केवल उदाहरणों में प्रदर्शित होने वाले नाम धारण करते हैं, तो इससे शुरू करने के लिए कम बेमानी JSON मान को संग्रहित करने के लिए और अधिक कुशल हो जाएगा: केवल पाठ primitives के रूप में मान और अनावश्यक कुंजी स्तंभ नाम में हो सकते हैं

JSON ऑब्जेक्ट्स और आदिम प्रकारों के बीच अंतर को नोट करें:

  • PostgreSQL में जेएसएन सरणी में अनुक्रमणिका का उपयोग करना
 CREATE TABLE tracks (id serial, artistnames jsonb); INSERT INTO tracks VALUES (2, '["The Dirty Heads", "Louis Richards"]'); CREATE INDEX tracks_artistnames_gin_idx ON tracks USING gin (artistnames); 

प्रश्न:

 SELECT * FROM tracks WHERE artistnames ? 'The Dirty Heads'; 

? ऑब्जेक्ट मानों के लिए काम नहीं करता है, बस कुंजियाँ और सरणी तत्व
या (अधिक कुशल अगर नाम अक्सर दोहराया जाता है):

 CREATE INDEX tracks_artistnames_gin_idx ON tracks USING gin (artistnames jsonb_path_ops); 

प्रश्न:

 SELECT * FROM tracks WHERE artistnames @> '"The Dirty Heads"'::jsonb; 

jsonb_path_ops वर्तमान में केवल @> ऑपरेटर को अनुक्रमणित करने का समर्थन करता है।
मैन्युअल में अधिक इंडेक्स ऑप्शंस, विवरण हैं

पोस्टस 9.3+ में जेएसन

यह एक IMMUTABLE फ़ंक्शन के साथ काम करना चाहिए:

 CREATE OR REPLACE FUNCTION json2arr(_j json, _key text) RETURNS text[] LANGUAGE sql IMMUTABLE AS 'SELECT ARRAY(SELECT elem->>_key FROM json_array_elements(_j) elem)'; 

इस कार्यात्मक सूचक को बनाएं:

 CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (json2arr(artists, 'name')); 

और इस तरह एक क्वेरी का उपयोग करें WHERE खंड में अभिव्यक्ति को सूचकांक में एक से मेल करना है:

 SELECT * FROM tracks WHERE '{"The Dirty Heads"}'::text[] <@ (json2arr(artists, 'name')); 

टिप्पणियों में प्रतिक्रिया के साथ अपडेट किया गया जीआईएन सूचकांक का समर्थन करने के लिए हमें सरणी ऑपरेटर का उपयोग करना होगा।
" इस मामले में शामिल" ऑपरेटर <@ इस मामले में

फ़ंक्शन अस्थिरता पर नोट्स

यदि आप json_array_elements() नहीं किया गया है , तो भी आप अपने कार्य को IMMUTABLE घोषित कर सकते हैं।
अधिकांश JSON फ़ंक्शंस केवल IMMUTABLE , IMMUTABLE नहीं IMMUTABLE । हैकर्स की सूची में उस बदलाव को लेकर चर्चा हुई। अधिकांश अब IMMUTABLE हैं इससे जाँच करें:

 SELECT p.proname, p.provolatile FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname = 'pg_catalog' AND p.proname ~~* '%json%'; 

कार्यात्मक अनुक्रमित केवल IMMUTABLE कार्यों के साथ काम करते हैं