PostgreSQL में JSONB को छोड़कर


14

मेरे पास एक टेबल है, personsजिसमें दो कॉलम हैं, एक idऔर एक JSONB- आधारित dataकॉलम (यह तालिका सिर्फ पोस्टग्रेजिक के JSON समर्थन के साथ खेलने के लिए प्रदर्शन के उद्देश्यों के लिए बनाई गई है)।

अब, माना जाता है कि इसमें दो रिकॉर्ड हैं:

1, { name: 'John', age: 30 }
2, { name: 'Jane', age: 20 }

अब, माना जाता है कि मैं 25 वर्ष से अधिक आयु के प्रत्येक व्यक्ति का नाम प्राप्त करना चाहता हूं। मैंने जो कोशिश की है वह है:

select data->'name' as name from persons where data->'age' > 25

दुर्भाग्य से, यह एक त्रुटि का परिणाम है। मैं ->>इसके बजाय का उपयोग करके इसे हल कर सकता हूं ->, लेकिन फिर तुलना किसी भी अपेक्षा के अनुसार काम नहीं करती है, क्योंकि संख्याओं की तुलना नहीं की जाती है, लेकिन स्ट्रिंग्स के रूप में उनका प्रतिनिधित्व:

select data->'name' as name from persons where data->>'age' > '25'

फिर मुझे पता चला कि मैं वास्तव में इस मुद्दे को हल करके ->और एक कास्ट को हल कर सकता हूं int:

select data->'name' as name from persons where cast(data->'age' as int) > 25

यह काम करता है, लेकिन यह अच्छा नहीं है कि मुझे वास्तविक प्रकार ( ageJSON दस्तावेज़ का प्रकार numberवैसे भी जानना है, इसलिए PostgreSQL यह पता नहीं लगा सकता है कि अपने आप क्यों?)।

फिर मुझे पता चला कि अगर मैं मैन्युअल रूप textसे ::वाक्यविन्यास का उपयोग करने में परिवर्तित हो जाता हूं , तो सब कुछ अपेक्षा के अनुसार काम करता है, हालांकि - अब हम फिर से तार की तुलना कर रहे हैं।

select data->'name' as name from persons where data->'age'::text > '25'

अगर मैं उम्र के बजाय नाम के साथ यह कोशिश करता हूं, तो यह काम नहीं करता है:

select data->'name' as name from persons where data->'name'::text > 'Jenny'

इसके परिणामस्वरूप त्रुटि होती है:

प्रकार json के लिए अमान्य इनपुट सिंटैक्स

बहुत स्पष्ट रूप से, मुझे यहाँ कुछ नहीं मिलता है। दुर्भाग्य से, PostgreSQL के साथ JSON का उपयोग करने के किसी भी वास्तविक दुनिया के उदाहरणों को खोजना काफी कठिन है।

कोई संकेत?


1
में data->'name'::text, आप 'name'स्ट्रिंग को पाठ में डाल रहे हैं, परिणाम नहीं। आपको एक त्रुटि जब की तुलना में नहीं मिलता है '25'क्योंकि 25एक मान्य JSON शाब्दिक है, लेकिन Jennyनहीं है (हालांकि "Jenny"होगा)।
चिरालू

धन्यवाद, यह समाधान है :-)। मैं उलझन 'Jenny'में था '"Jenny"'
गोलो रोडेन

जवाबों:


15

यह काम नहीं करता है क्योंकि यह एक jsonbमूल्य डालने की कोशिश कर रहा है integer

select data->'name' as name from persons where cast(data->'age' as int) > 25

यह वास्तव में काम करेगा:

SELECT data->'name' AS name FROM persons WHERE cast(data->>'age' AS int) > 25;

या कम:

SELECT data->'name' AS name FROM persons WHERE (data->>'age')::int > 25;

और इस:

SELECT data->'name' AS name FROM persons WHERE data->>'name' > 'Jenny';

दो के साथ भ्रम की तरह लगता है ऑपरेटरों ->और->> और ऑपरेटर पूर्वता । कास्ट ::जोंस (बी) ऑपरेटरों की तुलना में मजबूत बांधता है।

गतिशील रूप से चित्र का प्रकार

यह आपके प्रश्न का अधिक दिलचस्प हिस्सा है:

JSON दस्तावेज़ में आयु का प्रकार वैसे भी संख्या है, इसलिए PostgreSQL यह पता नहीं लगा सकता है कि उसके द्वारा ही क्यों?

एसक्यूएल एक कड़ाई से टाइप की गई भाषा है, यह एक ही अभिव्यक्ति को integerएक पंक्ति में और textअगले में मूल्यांकन करने की अनुमति नहीं देता है । लेकिन जब से आप केवल booleanपरीक्षण के परिणाम में रुचि रखते हैं , आप इस प्रतिबंध के आसपास एक CASEअभिव्यक्ति के साथ प्राप्त कर सकते हैं जो परिणाम के आधार पर कांटे jsonb_typeof():

SELECT data->'name'
FROM   persons
WHERE  CASE jsonb_typeof(data->'age')
        WHEN 'number'  THEN (data->>'age')::numeric > '25' -- treated as numeric
        WHEN 'string'  THEN data->>'age' > 'age_level_3'   -- treated as text
        WHEN 'boolean' THEN (data->>'age')::bool           -- use boolean directly (example)
        ELSE FALSE                                         -- remaining: array, object, null
       END;

>ऑपरेटर के दाईं ओर एक बिना तार वाला स्ट्रिंग शाब्दिक रूप से बाईं ओर के मूल्य के संबंधित प्रकार के लिए मजबूर किया जाता है। यदि आप वहां टाइप टाइप करते हैं, तो टाइप को मैच करना होगा या आपको इसे स्पष्ट रूप से डालना होगा - जब तक कि सिस्टम में पर्याप्त निहित कास्ट दर्ज न हो।

यदि आप जानते हैं कि सभी संख्यात्मक मूल्य वास्तव में हैं integer, तो आप यह भी कर सकते हैं:

... (data->>'age')::int > 25 ...

चयन कथन की उपरोक्त तुलना के लिए sqlalchemy कोर अभिव्यक्ति क्या है। s = select ([मुद्दे])। जहाँ (मुद्दे.c.id == मध्य) .select_from (मुद्दे, ..... आउटरजॉइन (मुद्दे.c.data ['type_id'] == mtypes.c.id) ) ... यहाँ मुद्दों। Cata डेटा प्रकार jatab और पूर्णांक प्रकार के mtypes.c.id के साथ तुलना की जा रही है
user956424
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.