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

पोस्टग्रेज - आसन्न सूची को नेस्टेड JSON ऑब्जेक्ट में बदलें

WITH RECURSIVE का उपयोग करना (https://www.postgresql.org/docs/current/static/queries-with.html) और JSON फंक्शन्स (https://www.postgresql.org/docs/current/static/functions-json.html) I इस समाधान का निर्माण करें:

डीबी<>बेला

मुख्य कार्यक्षमता:

    WITH RECURSIVE tree(node_id, ancestor, child, path, json) AS  (
      SELECT 
          t1.node_id, 
          NULL::int, 
          t2.node_id,
          '{children}'::text[] || 
             (row_number() OVER (PARTITION BY t1.node_id ORDER BY t2.node_id) - 1)::text,-- C
          jsonb_build_object('name', t2.name, 'children', array_to_json(ARRAY[]::int[])) -- B
      FROM test t1
      LEFT JOIN test t2 ON t1.node_id = t2.parent_node                                   -- A
      WHERE t1.parent_node IS NULL

      UNION

      SELECT
          t1.node_id, 
          t1.parent_node, 
          t2.node_id,
          tree.path || '{children}' || (row_number() OVER (PARTITION BY t1.node_id ORDER BY t2.node_id) - 1)::text, 
          jsonb_build_object('name', t2.name, 'children', array_to_json(ARRAY[]::int[]))
      FROM test t1
      LEFT JOIN test t2 ON t1.node_id = t2.parent_node
      INNER JOIN tree ON (t1.node_id = tree.child)
      WHERE t1.parent_node = tree.node_id                                                -- D
    )
    SELECT                                                                               -- E
        child as node_id, path, json 
    FROM tree 
    WHERE child IS NOT NULL ORDER BY path

प्रत्येक WITH RECURSIVE एक प्रारंभ होता है SELECT और एक रिकर्सन भाग (दूसरा SELECT ) एक UNION . द्वारा संयुक्त .

उ:node_id . के बच्चों को खोजने के लिए तालिका में फिर से शामिल होना .

बी:बच्चे के लिए जेसन ऑब्जेक्ट बनाना जिसे उसके माता-पिता में डाला जा सकता है

सी:पथ का निर्माण जहां बच्चे की वस्तु डाली जानी है (रूट से)। विंडो फ़ंक्शन row_number() (https://www.postgresql.org/docs/current/static/tutorial-window.html) माता-पिता के चिल्ड्रन ऐरे में बच्चे की अनुक्रमणिका तैयार करता है।

डी:रिकर्सन भाग एक अंतर के साथ प्रारंभिक भाग के रूप में काम करता है:यह मूल तत्व की खोज नहीं कर रहा है बल्कि उस तत्व के लिए है जिसमें अंतिम रिकर्सन का मूल नोड है।

ई:बिना किसी बच्चे के सभी तत्वों को पुनरावर्तन और फ़िल्टर करना यह परिणाम देता है:

node_id   path                      json
2         children,0                {"name": "node2", "children": []}
4         children,0,children,0     {"name": "node4", "children": []}
5         children,0,children,1     {"name": "node5", "children": []}
6         children,0,children,2     {"name": "node6", "children": []}
3         children,1                {"name": "node3", "children": []}
7         children,1,children,0     {"name": "node7", "children": []}
8         children,1,children,1     {"name": "node8", "children": []}

हालांकि मुझे रिकर्सन में सभी बच्चों के तत्वों को जोड़ने का कोई तरीका नहीं मिला (मूल जेसन कोई वैश्विक चर नहीं है; इसलिए यह हमेशा प्रत्यक्ष पूर्वजों के परिवर्तनों को जानता है, उनके भाई बहनों को नहीं), मुझे एक सेकंड चरण में पंक्तियों को फिर से शुरू करना पड़ा।

इसलिए मैं फ़ंक्शन का निर्माण करता हूं। वहां मैं वैश्विक चर के लिए पुनरावृत्ति कर सकता हूं। फ़ंक्शन के साथ jsonb_insert मैं सभी परिकलित तत्वों को एक रूट जोंस ऑब्जेक्ट में सम्मिलित कर रहा हूं - परिकलित पथ का उपयोग करके।

CREATE OR REPLACE FUNCTION json_tree() RETURNS jsonb AS $$
DECLARE
    _json_output jsonb;
    _temprow record;
BEGIN
    SELECT 
        jsonb_build_object('name', name, 'children', array_to_json(ARRAY[]::int[])) 
    INTO _json_output 
    FROM test 
    WHERE parent_node IS NULL;

    FOR _temprow IN
        /* Query above */
    LOOP
        SELECT jsonb_insert(_json_output, _temprow.path, _temprow.json) INTO _json_output;
    END LOOP;

    RETURN _json_output;
END;
$$ LANGUAGE plpgsql;

अंतिम चरण फ़ंक्शन को कॉल करना और JSON को अधिक पठनीय बनाना है (jsonb_pretty() )

{
    "name": "node1",
    "children": [{
        "name": "node2",
        "children": [{
            "name": "node4",
            "children": []
        },
        {
            "name": "node5",
            "children": []
        },
        {
            "name": "node6",
            "children": []
        }]
    },
    {
        "name": "node3",
        "children": [{
            "name": "node7",
            "children": []
        },
        {
            "name": "node8",
            "children": []
        }]
    }]
}

मुझे यकीन है कि क्वेरी को अनुकूलित करना संभव है लेकिन एक स्केच के लिए यह काम करता है।




  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. तुलना में बी + ट्री और हैश के साथ संक्षेप में डेटाबेस इंडेक्सिंग

  3. jsonb बनाम jsonb[] एक ग्राहक के लिए एक से अधिक पतों के लिए

  4. समूहवार अधिकतम क्वेरी अनुकूलित करें

  5. लूप के लिए पोस्टग्रेज