सरणियों को शामिल jsonb कुंजी सॉर्ट क्रम को अनुकूलित करें


9

मेरे पास कुछ डेटा के साथ PostgreSQL में एक तालिका है:

create table t2 (
    key jsonb,
    value jsonb
);

INSERT INTO t2(key, value)
 VALUES
 ('1', '"test 1"')
,('2', '"test 2"')
,('3', '"test 3"')
,('[]', '"test 4"')
,('[1]', '"test 5"')
,('[2]', '"test 6"')
,('[3]', '"test 7"')
,('[1, 2]', '"test 8"')
,('[1, 2, 3]', '"test 9"')
,('[1, 3]', '"test 10"')
,('[1,2,4]', '"test 11"')
,('[1, 2,4]', '"test 12"')
,('[1,3,13]', '"test 13"')
,('[1, 2, 15]', '"test 15"');

और मैं इन पंक्तियों को उस तरह छाँटने की कोशिश करता हूँ:

SELECT key FROM t2 order by key;

परिणाम है:

[]
1
2
3
[1]
[2] <==
[3] <==
[1, 2]
[1, 3] <==
[1, 2, 3]
[1, 2, 4]
[1, 2, 4]
[1, 2, 15]
[1, 3, 13]

लेकिन मुझे क्या चाहिए:

[]
1
2
3
[1]
[1, 2]
[1, 2, 3]
[1, 2, 4]
[1, 2, 4]
[1, 2, 15]
[1, 3] <==
[1, 3, 13]
[2] <==
[3] <==

क्या इसे हासिल करने का कोई तरीका है?


तो क्या आपका जवाब यहाँ है?
इरविन ब्रांडस्टेटर

जवाबों:


8

सबसे पहले, आपका प्रश्न और साथ ही आपके कॉलम का नाम "key"भ्रामक है। स्तंभ कुंजी में कोई JSON कुंजी नहीं है , केवल मान हैं । और हम jsonb_object_keys(jsonb)कुंजियों को निकालने के लिए फ़ंक्शन का उपयोग कर सकते हैं , लेकिन ऐसा नहीं है।

मान लें कि आपके सभी JSON सरणियाँ या तो खाली हैं या प्रदर्शन के अनुसार पूर्णांक संख्या रखती हैं। और स्केलर मान (गैर-सरणियाँ) भी पूर्णांक हैं।

आपका मूल क्रम पोस्टग्रेज integer(या numeric) सरणियों के साथ काम करेगा । मैं सरणियों को पोस्टग्रेज में बदलने के लिए इस छोटे सहायक समारोह का उपयोग करता हूं :jsonbint[]

CREATE OR REPLACE FUNCTION jsonb_arr2int_arr(_js jsonb)
   RETURNS int[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT j::int FROM jsonb_array_elements_text(_js) j)';

स्पष्टीकरण:

फिर यहां jsonb_typeof(jsonb)पहुंचने के लिए जोड़ें :

SELECT key
FROM   t2
ORDER  BY key <> '[]'             -- special case for empty array
        , jsonb_typeof(key) DESC  -- 'number' before 'array'
        , CASE jsonb_typeof(key)  -- sort arrays as converted int[]
            WHEN 'array'  THEN jsonb_arr2int_arr(key)
            WHEN 'number' THEN ARRAY[key::text::int]
          END;

वांछित परिणाम बिल्कुल पैदा करता है।

क्यों?

मैनुअल के लिए jsonbबताते हैं:

btreeके लिए आदेश देने की jsonbडाटुमस महान ब्याज की शायद ही कभी होता है, लेकिन पूर्णता के लिए यह है:

Object > Array > Boolean > Number > String > Null
Object with n pairs > object with n - 1 pairs
Array with n elements > array with n - 1 elements

जोड़े की समान संख्या वाली वस्तुओं की क्रम में तुलना की जाती है:

key-1, value-1, key-2 ...

ध्यान दें कि ऑब्जेक्ट कुंजी की तुलना उनके भंडारण क्रम में की जाती है; विशेष रूप से, चूंकि छोटी चाबियों को लंबे समय तक कुंजी से पहले संग्रहीत किया जाता है, इससे ऐसे परिणाम हो सकते हैं जो अनपेक्षित हो सकते हैं, जैसे:

{ "aa": 1, "c": 1} > {"b": 1, "d": 1}

इसी तरह, तत्वों की समान संख्या वाले सरणियों की तुलना क्रम में की जाती है:

element-1, element-2 ...

बोल्ड जोर मेरा।
इसीलिए jsonb '[2]' < jsonb '[1, 2]'
लेकिन Postgres arrays बस तत्व-दर-तत्व को छांटता है: '{2}'::int[] > '{1, 2}'- ठीक वही जो आप ढूंढ रहे थे।


0

Json पूर्णांक मानों द्वारा अपने परिणामों को आदेश देने के लिए समस्या का संदर्भ लेना। प्रयत्न:

select myjson from mytable order by (myjson->>'some_int')::int;

आपके मामले में यह ऑर्डरिंग कुंजी के लिए एक सरणी प्रतीत होती है। इसलिए पहले अपने "कुंजी" क्षेत्र में मूल्यों को संक्षिप्त करने का प्रयास करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.