Postgres JSONb einschließlich Array zu XML mit Schlüssel und Wert und Wert

Oct 14 2020

Ich habe eine Tabelle wie folgt:

id  (VARCHAR) | field1 (text) | attributes  (jsonb)     
--------------+---------------+----------------------------------

 123          |   a           |   {"age": "1", "place": "TX"}                 
 456          |   b           |   {"age": "2", "name": "abcdef"}     
 789          |               |       
 098          |   c           |   {"name": ["abc", "def", "ghi"]}     

Möchte es konvertieren in:

 <Company id="123" field="a">
      <CompanyTag tagName="age" tagValue="1"/>
      <CompanyTag tagName="place" tagValue="TX"/>
 </Company>
 <Company id="456" field="b">
      <CompanyTag tagName="age" tagValue="2"/>
      <CompanyTag tagName="name" tagValue="abcdef"/>
 </Company>
 <Company id="789"/>
  <Company id="098" field="c">
      <CompanyTag tagName="name" tagValue="abc"/>
      <CompanyTag tagName="name" tagValue="def"/>
      <CompanyTag tagName="name" tagValue="ghi"/>
 </Company>

Mit Hilfe von @bergi und @Georges konnte Martin unter Post das Nicht-Array mit der folgenden Abfrage konvertieren:

SELECT XMLELEMENT(
  NAME "Company", 
  XMLATTRIBUTES(id AS id, field1 AS field), 
  (SELECT XMLAGG(
    XMLELEMENT(
      NAME "companyTag", 
      XMLATTRIBUTES(
        attr.key AS "tagName", 
        attr.value AS "tagValue"
      )
    )
  ) FROM JSONB_EACH_TEXT(attributes) AS attr)
) FROM comp_emp;

Die Array-Werte werden jedoch wie folgt angezeigt:

 <Company id="098" field="c">
      <CompanyTag tagName="name"tagValue="[&quot;abc&quot;, &quot;def&quot;, &quot;ghi&quot;]"/> 

Ich möchte den Schlüssel ("tagName") nicht speziell in der Abfrage erwähnen, da dies variieren kann. Angenommen, dies wird dadurch verursacht, dass JSONB_EACH_TEXT die äußersten Werte extrahiert. Gibt es eine Alternative?

Bitte führe mich in die richtige Richtung.

Antworten

Bergi Oct 14 2020 at 21:20

jsonb_array_elements_textWenn Sie mit einem Array arbeiten, müssen Sie die Werte zusätzlich extrahieren. Fertig mit einer seitlichen Verbindung:

SELECT XMLAGG(
  XMLELEMENT(
    NAME "CompanyTag", 
    XMLATTRIBUTES(
      attr.key AS "tagName", 
      values.element AS "tagValue"
    )
  )
) FROM jsonb_each(attributes) AS attr,
LATERAL jsonb_array_elements_text(CASE jsonb_typeof(attr.value)
  WHEN 'array' THEN attr.value
  ELSE jsonb_build_array(attr.value)
END) AS values(element)

( Online-Demo mit vollständiger Abfrage)