PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

Postgres jsonb में सरणियों में संरचनाओं को क्वेरी करने के लिए उचित सूचकांक क्या है?

सबसे पहले, आप इस तरह JSON सरणी मानों तक नहीं पहुंच सकते हैं। किसी दिए गए json मान के लिए

[{"event_slug":"test_1","start_time":"2014-10-08","end_time":"2014-10-12"},
 {"event_slug":"test_2","start_time":"2013-06-24","end_time":"2013-07-02"},
 {"event_slug":"test_3","start_time":"2014-03-26","end_time":"2014-03-30"}]

पहले सरणी तत्व के विरुद्ध एक मान्य परीक्षण होगा:

WHERE e->0->>'event_slug' = 'test_1'

लेकिन आप शायद अपनी खोज को सरणी के पहले तत्व तक सीमित नहीं करना चाहते हैं। jsonb . के साथ Postgres 9.4 में डेटा प्रकार आपके पास अतिरिक्त ऑपरेटर और अनुक्रमणिका समर्थन है। किसी सरणी के तत्वों को अनुक्रमित करने के लिए आपको एक GIN अनुक्रमणिका की आवश्यकता होती है।

GIN इंडेक्स के लिए बिल्ट-इन ऑपरेटर क्लासेस "इससे बड़ा" या "इससे कम" ऑपरेटर्स का समर्थन नहीं करते हैं <स्ट्राइक> > >= < <= . यह jsonb . के लिए सही है साथ ही, जहां आप दो ऑपरेटर वर्गों के बीच चयन कर सकते हैं। प्रति दस्तावेज़:

Name             Indexed Data Type  Indexable Operators
...
jsonb_ops        jsonb              ? ?& ?| @>
jsonb_path_ops   jsonb              @>
   

(jsonb_ops डिफ़ॉल्ट होने के नाते।) आप समानता परीक्षण को कवर कर सकते हैं, लेकिन इनमें से कोई भी ऑपरेटर >= के लिए आपकी आवश्यकता को कवर नहीं करता है। तुलना। आपको एक btree अनुक्रमणिका की आवश्यकता होगी।

मूल समाधान

इंडेक्स के साथ समानता जांच का समर्थन करने के लिए:

CREATE INDEX locations_events_gin_idx ON locations
USING gin (events jsonb_path_ops);

SELECT * FROM locations WHERE events @> '[{"event_slug":"test_1"}]';

यदि फ़िल्टर पर्याप्त रूप से चयनात्मक है तो यह काफी अच्छा हो सकता है।
मान लें कि end_time >= start_time , इसलिए हमें दो चेक की आवश्यकता नहीं है। केवल end_time की जांच की जा रही है सस्ता और समकक्ष है:

SELECT l.*
FROM   locations l
     , jsonb_array_elements(l.events) e
WHERE  l.events @> '[{"event_slug":"test_1"}]'
AND   (e->>'end_time')::timestamp >= '2014-10-30 14:04:06 -0400'::timestamptz;

एक अंतर्निहित JOIN LATERAL का उपयोग करना . विवरण (अंतिम अध्याय):

  • तत्व संख्या के साथ PostgreSQL unnest()

विभिन्न डेटा प्रकारों से सावधान रहें ! आपके पास JSON मान में जो है वह timestamp [without time zone] . जैसा दिखता है , जबकि आपके विधेय timestamp with time zone . का उपयोग करते हैं शाब्दिक। timestamp मान की व्याख्या वर्तमान समय क्षेत्र . के अनुसार की जाती है सेटिंग, जबकि दिया गया timestamptz अक्षर timestamptz . पर डाले जाने चाहिए स्पष्ट रूप से या समय क्षेत्र पर ध्यान नहीं दिया जाएगा! उपरोक्त क्वेरी को वांछित के रूप में काम करना चाहिए। विस्तृत विवरण:

  • रेल और पोस्टग्रेएसक्यूएल में टाइम ज़ोन को पूरी तरह नज़रअंदाज़ करना

jsonb_array_elements() . के लिए अधिक स्पष्टीकरण :

  • JSONB का उपयोग करके PostgreSQL में शामिल होना

उन्नत समाधान

यदि उपरोक्त पर्याप्त नहीं है, तो मैं एक MATERIALIZED VIEW पर विचार करूंगा जो प्रासंगिक विशेषताओं को सामान्यीकृत रूप में संग्रहीत करता है। यह सादे btree अनुक्रमणिका की अनुमति देता है।

कोड मानता है कि आपके JSON मानों का प्रारूप एक समान है जैसा कि प्रश्न में दिखाया गया है।

सेटअप:

CREATE TYPE event_type AS (
 , event_slug  text
 , start_time  timestamp
 , end_time    timestamp
);

CREATE MATERIALIZED VIEW loc_event AS
SELECT l.location_id, e.event_slug, e.end_time  -- start_time not needed
FROM   locations l, jsonb_populate_recordset(null::event_type, l.events) e;

jsonb_populate_recordset() . के लिए संबंधित उत्तर :

  • PostgreSQL 9.4 के jsonb टाइप को फ्लोट में कैसे बदलें
CREATE INDEX loc_event_idx ON loc_event (event_slug, end_time, location_id);

location_id . सहित भी केवल-अनुक्रमणिका स्कैन की अनुमति देने के लिए . (मैन्युअल पेज देखें और विकी पोस्ट करें।)

प्रश्न:

SELECT *
FROM   loc_event
WHERE  event_slug = 'test_1'
AND    end_time  >= '2014-10-30 14:04:06 -0400'::timestamptz;

या, यदि आपको अंतर्निहित locations . से पूर्ण पंक्तियों की आवश्यकता है टेबल:

SELECT l.*
FROM  (
   SELECT DISTINCT location_id
   FROM   loc_event
   WHERE  event_slug = 'test_1'
   AND    end_time  >= '2014-10-30 14:04:06 -0400'::timestamptz
   ) le
JOIN locations l USING (location_id);


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL में तिथियों के साथ कार्य करना

  2. बेंचमार्किंग प्रबंधित PostgreSQL क्लाउड समाधान - Google क्लाउड:भाग तीन

  3. WHERE क्लॉज में एक ही कॉलम को कई बार इस्तेमाल करना

  4. मैं एक कॉलम कैसे जोड़ सकता हूं जो पोस्टग्रेस्क्ल डेटाबेस में नल की अनुमति नहीं देता है?

  5. मैं उसकेोकू पर एक सादा पाठ पोस्टग्रेज डेटाबेस डंप कैसे प्राप्त कर सकता हूं?