- 1 Intro
- 2 Anwendungsgebiete
- 2.1 XSLT - die Programmiersprache im XML Bereich
- 2.2 Aktuelle und vergangene Anwendungen
- 2.3 Professionelle XML Verarbeitung
- 2.4 Technische Dokumentation
- 3 Wichtige Konzepte
- 3.1 Push vs. Pull Stylesheets
- 3.2 Eindeutigkeit der Regelbasis
- 3.3 Namespaces
- 3.4 Schemata
- 3.5 Standards
- 3.5.1 DITA
- 3.5.2 DITA Inhaltsmodell
- 3.5.1 DITA
- 4 Ausgewählte Themen
- 4.1 Transformationen mit XSLT
- 4.1.1 Vortransformationen
- 4.1.2 Komplexe XML-2-XML Transformationen
- 4.1.2.8 Vererbung
- 4.1.2.8 Vererbung
- 4.1.3 XSLT Streaming
- 4.1.3.1 XSLT Akkumulator
- 4.1.3.2 XSLT Iterator
- 4.1.4 Reguläre Ausdrücke
- 4.1.5 Modus vs. Tunnel Lösung
- 4.1.6 Identifikation mit
generate-id()
- 4.1.6.4 XPath-Achsenbereich selektieren
- 4.1.6.4.1 Funktionen und Module
- 4.1.6.4.1 Funktionen und Module
- 4.1.6.4 XPath-Achsenbereich selektieren
- 4.1.7 Webservice Calls mit doc() und unparsed-text()
- 4.1.8 Stylesheet-Parameter auf der Kommandozeile
- 4.1.9 Leerzeichenbehandlung
- 4.1.10 Mit
translate
Zeichen ersetzen
- 4.1.10.1 Spass mit dem Sequenzvergleich
- 4.1.11 Character Mappings in der Ausgabe
- 4.1.12 JSON mit XSLT 1.0 und Python lxml
- 4.1.1 Vortransformationen
- 4.2 Abfragen mit XQuery
- 4.2.5 XQuery als Programmiersprache
- 4.2.5.3
if..then..else
Ausdrücke
- 4.2.5.3.2 SQL Views in MarkLogic
- 4.2.5.3
if..then..else
Ausdrücke
- 4.2.6 Hilfreiche XQuery Schippsel
- 4.2.5 XQuery als Programmiersprache
- 4.3 XML Datenbanken
- 4.3.1 Connector zu Marklogic in Oxygen
- 4.3.2 Bi-Temporale Dokumente
- 4.3.2.1 Anlegen des Testszenarios auf der ML Konsole
- 4.3.2.2 Ausführen einiger Beispiel-Queries
- 4.3.3 Webapps mit MarkLogic
- 4.3.3.5 Wikipedia Scrapper Applikation
- 4.3.3.5 Wikipedia Scrapper Applikation
- 4.3.4 Dokument-Rechte in MarkLogic
- 4.3.5 MarkLogic Tools
- 4.3.5.1 EXPath Konsole
- 4.3.5.2 mlcp - MarkLogic Content Pump
- 4.3.5.3 Deployment-Tools
- 4.4 XSL-FO mit XSLT1.x
- 4.5 Testing
- 4.5.1 Validierung mit Schematron
- 4.5.2 Erste Schritte mit XSpec
- 4.5.1 Validierung mit Schematron
- 4.6 Performanz-Optimierung
- 4.1 Transformationen mit XSLT
- 5 Zusätzliches Know-How
- 5.1 XML Editoren
- 5.2 Quellcode-Versionskontrolle
- 5.2.1 Kurze Geschichte zur Versionskontrolle Test
- 5.2.2 GIT Kommandos
- 5.2.1 Kurze Geschichte zur Versionskontrolle Test
- 5.1 XML Editoren
- 6 Glossary
- 7 Tektur CCMS
4.2.5.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:
<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 hier:
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" ] ]