हमारे पास एक विरासत प्रणाली थी जिसे रखने का प्रयास किया गया थाकिसी विशेष दस्तावेज़ के डेटा के सभी संस्करणों का ट्रैक। हमने अपने JSON को मूल रूप से Postgres के कुछ पुराने संस्करण में एक स्ट्रिंग के रूप में संग्रहीत किया है, लेकिन हाल ही में हमने Postgres 9.3 में अपग्रेड किया और हमने JSON कॉलम प्रकार का उपयोग करना शुरू कर दिया।
हमारे पास "संस्करण" नामक एक कॉलम था, और इसमें एक सरणी थी, और किसी विशेष दस्तावेज़ के प्रत्येक सहेजे गए संस्करण को सरणी में संग्रहीत किया गया था, इसलिए इस तरह से एक क्वेरी:
SELECT _data_as_json FROM measurements WHERE id = 3307551
JSON इस तरह लौटा:
{"reports": {}, "versions": [
{"timestamp": "2014-04-28T19:12:31.567415", "user": 11327, "legacy": {}, "vd_version": 1},
{"timestamp": "2014-05-12T18:03:24.417029", "user": 11331, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1},
{"timestamp": "2014-05-12T21:52:50.045758", "user": 10373, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1},
{"timestamp": "2014-05-14T23:34:37.797822", "user": 10380, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1},
{"timestamp": "2014-07-16T14:56:38.667363", "user": 10374, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1},
{"timestamp": "2014-07-16T14:57:47.341541", "user": 10374, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1},
{"timestamp": "2014-07-17T16:32:09.067026", "user": 11331, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1},
{"timestamp": "2014-09-11T14:35:44.436886", "user": 11331, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1},
{"timestamp": "2014-10-15T14:30:50.554932", "user": 10383, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1},
{"timestamp": "2014-10-29T15:36:35.183787", "user": 11331, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1},
{"timestamp": "2014-11-12T22:22:03.892484", "user": 10373, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1}
]}
हमने कालानुक्रमिक क्रम में "संस्करणों" में डेटा संग्रहीत करने का प्रयास किया, लेकिन 99% समय, हमें केवल अंतिम दस्तावेज़ की आवश्यकता है। 9.3 पोस्टग्रेज में, हम अंतिम आइटम प्राप्त करने के लिए इस क्वेरी के साथ आए:
SELECT json_array_elements(_data_as_json->"versions")
FROM measurements
WHERE id = 3307551
LIMIT 1 OFFSET (SELECT json_array_length(_data_as_json->"versions") - 1 FROM measurements WHERE id = 3307551)
यह मूल रूप से काम करता है, लेकिन यह थोड़ा नाजुक है। यदि हम कभी भी संस्करण सरणी में चीजों को सही ढंग से क्रमबद्ध करने में विफल रहते हैं, तो हमें दस्तावेज़ का गलत संस्करण वापस मिल जाता है। अगर मैं ऐसा करने के लिए एक बेहतर तरीका है, तो मैं उत्सुक हूं; मैंने पढ़ा है कि जॉन्सन के साथ काम करने के लिए 9.4 पोस्ट Postgres अधिक कार्य करता है।
आदर्श रूप से, हम "टाइमस्टैम्प" पर ORDER BY कर सकते हैं। क्या यह संभव है?
उत्तर:
उत्तर № 1 के लिए 119.5+ पोस्ट करता है
नौकरी अब आसान है, मैनुअल का हवाला देते हुए:
फ़ील्ड / तत्व / पथ निष्कर्षण ऑपरेटर जो पूर्णांक JSON को स्वीकार करते हैं सरणी सभी समर्थन का समर्थन करता है सरणियों के अंत से नकारात्मक सबस्क्रिप्टिंग.
बोल्ड जोर मेरा। तो या तो के लिए json
या jsonb
:
SELECT _data_as_json->"versions"->>-1
FROM measurements m
WHERE id = 3307551;
पदार्पण 9.4
आप उपयोग करना चाह सकते हैं jsonb
के बजाय json
। उपयोग jsonb_array_elements()
या jsonb_array_length()
तदनुसार।
नए का उपयोग करके मूल सॉर्ट क्रम के अनुसार अंतिम तत्व प्राप्त करने के लिए एक अधिक सामान्य दृष्टिकोण भी है WITH ORDINALITY
(शायद धीमा):
SELECT v
FROM measurements m
, jsonb_array_elements(m._data_as_json->"versions") WITH ORDINALITY v(v, rn)
WHERE m.id = 3307551
ORDER BY v.rn DESC
LIMIT 1;
के लिए विवरण WITH ORDINALITY
(और निहितार्थ JOIN LATERAL
दोनों संस्करणों में):
9.3 पोस्ट करता है
टाइमस्टैम्प मान के अनुसार "अंतिम":
SELECT j.v
FROM measurements m
, json_array_elements(m._data_as_json->"versions") j(v)
WHERE m.id = 3307551
ORDER BY (j.v->>"timestamp")::timestamp DESC
LIMIT 1;
"अंतिम" में क्रमिक स्थिति के अनुसार json
सरणी (तेज):
SELECT _data_as_json->"versions"
->(json_array_length(_data_as_json->"versions") - 1)
FROM measurements
WHERE id = 3307551;
ज़रुरत है - 1
JSON सरणियाँ ऑफसेट 0 से प्रारंभ होती हैं।