4.3.2  SQL Views in MarkLogic

Es macht nicht immer Sinn über eine Baumstruktur zu suchen. Obwohl das in einer XML Datenbank rasend schnell geht, weil jeder Knoten des Baums initial in einen Index aufgenommen wird. So gibt es doch Anwendungsfälle bei denen man lieber eine relationale Sicht auf die Daten hätte.
In MarkLogic heisst die Lösung dazu SQL Views.
Bspw. benötigt man eine relationale Sicht auf die Daten, wenn über verschiedene Datensätze ein Report generiert werden soll.
Nehmen wir an, es gibt im D- die folgenden Dokumente:
Zzzz
Philip
   
     
     
Tab. 1  Fzhhhhh
<k:kunde>
  <k:id>1</k:id>
  <k:name>Alex</k:name>
  <k:eMail>tekturcms@gmail.com</k:eMail>
</k:kunde>

<k:kunde>
  <k:id>2</k:id>
  <k:name>Horst</k:name>
  <k:eMail>horst@horst.de</k:eMail>
</k:kunde>

<k:kunde>
  <k:id>3</k:id>
  <k:name>Gundula</k:name>
  <k:eMail>gundl@gundula.de</k:eMail>
</k:kunde>

<b:bestellung>
  <b:id>1</b:id>
  <b:datum>02.01.2019</b:datum>
  <b:preis>99.90</b:preis>
  <kunde-id>2</kunde-id>
</b:bestellung>

<b:bestellung>
  <b:id>2</b:id>
  <b:datum>03.01.2019</b:datum>
  <b:preis>68.90</b:preis>
  <b:kunde-id>1</b:kunde-id>
</b:bestellung>
Will man sich alle Kunden anzeigen lassen, die eine Bestellung abgegeben haben - das sind Alex und Horst - so würde man bei einem relationalen Ansatz einen JOIN verwenden, so wie:
SELECT name, datum, preis
FROM kunden k
INNER JOIN bestellungen b
ON k.id = b.kunde_id
In einer relationalen Sicht würde uns das dann die folgende Tabelle liefern:
name, datum, preis
Alex, 03.01.2019, 68.90
Horst, 02.01.2019, 99.90
Um für MarkLogic eine SQL View zu definieren verwendet man einen Mechanismus, der da heisst: Template Driven Extraction ↗↗
Dazu werden Templates in XML deklariert und in die Template Collection eingefügt. Für unser obiges Beispiel würden wir zwei Templates brauchen, die so aussehen:
xquery version "1.0-ml";

import module namespace tde = "http://marklogic.com/xdmp/tde" 
                            at "/MarkLogic/tde.xqy";

let $sql-view-name := 'kunden-view.xml'
let $sql-view := <template xmlns="http://marklogic.com/xdmp/tde">
   <path-namespaces>
      <path-namespace>
         <prefix>k</prefix>
         <namespace-uri>https://tekturcms.de/schema/kunde/1.0</namespace-uri>
      </path-namespace>
   </path-namespaces>
   <context>/k:kunde</context>
   <collections>
      <collections-and>
         <collection>/kunden</collection>
      </collections-and>
   </collections>
   <rows>
      <row>
         <schema-name>kunden_schema</schema-name>
         <view-name>kunden_view</view-name>
         <columns>
            <column>
               <name>id</name>
               <scalar-type>string</scalar-type>
               <val>k:id</val>
               <nullable>true</nullable>
            </column>
            <column>
               <name>datum</name>
               <scalar-type>string</scalar-type>
               <val>k:datum</val>
               <nullable>true</nullable>
            </column>
            <column>
               <name>eMail</name>
               <scalar-type>string</scalar-type>
               <val>k:eMail</val>
               <nullable>true</nullable>
            </column>
         </columns>
      </row>
   </rows>
</template>
return(
  tde:template-insert(concat('/templates/', $sql-view-name), 
                      $sql-view, xdmp:default-permissions())
)
und analog für die Bestellungen:
[...]
   <rows>
      <row>
         <schema-name>bestellungen_schema</schema-name>
         <view-name>bestellungen_view</view-name>
         <columns>
            <column>
               <name>id</name>
               <scalar-type>string</scalar-type>
               <val>b:id</val>
            </column>
            <column>
               <name>datum</name>
               <scalar-type>string</scalar-type>
               <val>b:datum</val>
            </column>
            <column>
               <name>preis</name>
               <scalar-type>string</scalar-type>
               <val>b:preis</val>
            </column>
            <column>
               <name>kunde_id</name>
               <scalar-type>string</scalar-type>
               <val>b:kunde-id</val>
            </column>
         </columns>
      </row>
[...]
In XQuery eingebunden könnte man dann die definierten SQL Views mit dem folgenden Befehl abfragen:
xdmp:sql("SELECT name, datum, preis FROM kunden_view k 
          INNER JOIN bestellungen_view b ON k.id = b.kunde_id")
Folgende ist das komplette Beispiel für eine MarkLogic XQuery Konsolensitzung abgebildet ...
xquery version "1.0-ml";

declare namespace k = 'http://www.tekturcms.de/kunden';
declare namespace b = 'http://www.tekturcms.de/bestellungen';

import module namespace tde = "http://marklogic.com/xdmp/tde" at "/MarkLogic/tde.xqy";

declare function local:loadKunde($id, $name, $eMail)
{
  let $root :=
  <k:kunde>
    <k:id>{ $id }</k:id>
    <k:name>{ $name }</k:name>
    <k:eMail>{ $eMail }</k:eMail>
  </k:kunde>,
  $options :=
  <options xmlns="xdmp:document-insert">  
    <permissions>{ xdmp:default-permissions() }</permissions>
    <collections>
      <collection>/kunden</collection>
    </collections>
  </options>,
  $fname := concat('/kunden/',$id,".xml")
  return xdmp:document-insert($fname,$root,$options)
};

declare function local:loadBestellung($id, $datum, $preis, $kunde-id)
{
  let $root :=
  <b:bestellung>
    <b:id>{ $id }</b:id>
    <b:datum>{ $datum }</b:datum>
    <b:preis>{ $preis }</b:preis>
    <b:kunde-id>{ $kunde-id }</b:kunde-id>
  </b:bestellung>,
  $options :=
  <options xmlns="xdmp:document-insert">  
    <permissions>{ xdmp:default-permissions() }</permissions>
    <collections>
      <collection>/bestellungen</collection>
    </collections>
  </options>,
  $fname := concat('/bestellungen/',$id,".xml")
  return xdmp:document-insert($fname,$root,$options)
};

declare function local:insertKundenSchema()
{
  let $sql-view-name := 'kunden-view.xml',
      $sql-view := <template xmlns="http://marklogic.com/xdmp/tde">
    <path-namespaces>
      <path-namespace>
        <prefix>k</prefix>
        <namespace-uri>http://www.tekturcms.de/kunden</namespace-uri>
       </path-namespace>
    </path-namespaces>
    <context>/k:kunde</context>
     <collections>
       <collections-and>
         <collection>/kunden</collection>
      </collections-and>
     </collections>
     <rows>
       <row>
         <schema-name>kunden_schema</schema-name>
         <view-name>kunden_view</view-name>
         <columns>
            <column>
               <name>id</name>
               <scalar-type>string</scalar-type>
               <val>k:id</val>
            </column>
            <column>
               <name>name</name>
               <scalar-type>string</scalar-type>
               <val>k:name</val>
            </column>
          <column>
             <name>eMail</name>
             <scalar-type>string</scalar-type>
             <val>k:eMail</val>
          </column>
        </columns>
      </row>
    </rows>
  </template>
  return
    tde:template-insert(concat('/templates/', 
                        $sql-view-name), $sql-view, xdmp:default-permissions())
};

declare function local:insertBestellungenSchema()
{
  let $sql-view-name := 'bestellungen-view.xml',
      $sql-view := <template xmlns="http://marklogic.com/xdmp/tde">
    <path-namespaces>
      <path-namespace>
        <prefix>b</prefix>
        <namespace-uri>http://www.tekturcms.de/bestellungen</namespace-uri>
       </path-namespace>
    </path-namespaces>
    <context>/b:bestellung</context>
     <collections>
       <collections-and>
         <collection>/bestellungen</collection>
      </collections-and>
     </collections>
     <rows>
       <row>
         <schema-name>bestellungen_schema</schema-name>
         <view-name>bestellungen_view</view-name>
         <columns>
            <column>
               <name>id</name>
               <scalar-type>string</scalar-type>
               <val>b:id</val>
            </column>
            <column>
               <name>datum</name>
               <scalar-type>string</scalar-type>
               <val>b:datum</val>
            </column>
          <column>
             <name>preis</name>
             <scalar-type>string</scalar-type>
             <val>b:preis</val>
          </column>
          <column>
             <name>kunde_id</name>
             <scalar-type>string</scalar-type>
             <val>b:kunde-id</val>
          </column>
        </columns>
      </row>
    </rows>
  </template>
  return
    tde:template-insert(concat('/templates/', 
                        $sql-view-name), $sql-view, xdmp:default-permissions())
};


local:loadKunde("1","Alex","tekturcms@gmail.com"),

local:loadKunde("2","Horst","horst@horst.de"),

local:loadKunde("3","Gundula","gundl@gundula.de"),

local:loadBestellung("1","02.01.2019","99.90","2"),

local:loadBestellung("2","03.01.2019","68.90","1"),

local:insertKundenSchema(),

local:insertBestellungenSchema(),

xdmp:sql("SELECT name, datum, preis FROM kunden_view k INNER JOIN 
          bestellungen_view b ON k.id = b.kunde_id")
... mit einer schönen tabellarischen Ausgabe im unteren Panel der Query Konsole - oder als JSON:
[
  [
    "k.name", 
    "b.datum", 
    "b.preis"
  ], 
  [
    "Alex", 
    "03.01.2019", 
    "68.90"
  ], 
  [
    "Horst", 
    "02.01.2019", 
    "99.90"
  ]
]
Previous Page Next Page
Version: 92
Dec 26 2020