Inhalt

DGraph - Teil 4: Schema in Dgraph erstellen

Im ersten Teil dieser Serie habe ich erwähnt, dass Dgraph ohne Schema auskommt. In Teil 3 haben wir eine Anpassung des Schemas gemacht um ein Feld suchbar zu machen. Darüber hinaus gibt es noch weitere Gründe sich mit dem Thema Schema in Dgraph zu befassen, da man für manche Funktionen ohne Schema nicht weiterkommt. Ein Beispiel dafür ist die expand() Funktion. Damit ist es möglich alle Felder eines Datensatzes abzurufen ohne diese explizit anzufordern. Damit das funktioniert müssen wir in Dgraph erst einmal ein Schema definieren.

Schema und Datentypen definieren

Die Schema Definition in Dgraph ist relativ einfach. Mit dem Keyword type teilen wir Dgraph mit, dass eine Typendefinition folgt. Innerhalb der Definition geben wir die Datenfelder / Prädikate an aus denen der Typ bestehen soll.

Im Anschluss an den Datentyp können wir noch die einzelnen Felder genauer definieren.

1
2
3
4
5
6
7
8
9
type Person {
    name
    hometown
    friend_of
}

name: string @index(hash) .
hometown: string .
friend_of: [uid] .

Hier definieren wir das Feld name als Typ string und teilen Dgraph mit, dass dieses Feld indiziert sein soll. Für das Feld friend_of geben wir an, dass es sich um eine Verbindung zu einem anderen Datensatz handelt.

Dgraph verwendet den definierten Knotentyp nicht automatisch und geht nicht davon aus, dass bloß weil ein Knoten alle Felder des Typs Person besitzt, dieser auch vom Knotentyp Person ist. Das bedeutet, dass wir DGraph mitteilen müssen, wenn ein Datensatz eine Person ist:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  set{
    _:Peter <name> "Peter Parker" .
    _:Peter <hometown> "New York" .
    _:Peter <dgraph.type> "Person" .
    _:Mary <name> "Mary Jane Watson" .
    _:Mary <hometown> "New York" .
    _:Mary <friend_of> _:Peter .
    _:Mary <dgraph.type> "Person" .
    _:Harry <name> "Harry Osborne" .
    _:Harry <hometown> "New York" .
    _:Harry <friend_of> _:Peter .
    _:Harry <friend_of> _:Mary .
    _:Harry <dgraph.type> "Person" .
  }
}

Mit dem N-Quad _:Peter <dgraph.type> “Person” . wird z.B. dem Knoten für Peter Parker der Typ *Person zugewiesen. Das funktioniert natürlich auch im JSON Format:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
  "set": [
    {
      "name": "Peter Parker",
      "hometown": "New York",
      "dgraph.type": "Person"
    },
    {
      "name": "Mary Jane Watson",
      "hometown": "New York",
      "dgraph.type": "Person"
     }
  ]
}

Ein paar Funktionen, die sich aus der Schemadefinition ergeben

Dank der Schemadefinition haben wir jetzt Zugriff auf ein paar Standardfunktionen, die ohne Schema nicht möglich wären. Jetzt können wir in Dgraph z.B. gezielt nach dem Typ Person suchen.

1
2
3
4
5
6
{
  persons(func: type(Person)){
    uid
    name
  }
}

Dadurch lassen sich Queries noch gezielter ausführen, da man ja meistens mit recht konkreten Datanstrukturen arbeitet. In einem Bestellsystem hat man Bestellungen, Kunden und so weiter. Diese definiert man als eigene Typen, die man dann gezielt wieder ansprechen kann.

Eine weitere praktische Funktion ist expand:

1
2
3
4
5
6
7
{
  persons(func: type(Person)){
    expand(_all_) {
      expand(_all_)
    }
  }
}

Mit expand lassen sich alle Felder eines Datensatzes ausgeben und müssen nicht einzeln angegeben werden.

Ich habe schon oft gelesen, dass schemalos als Vorteil von Datenbanken angepriesen wird. Das ist ja im Grunde auch gut und richtig, letzten Endes muss man sich aber bei jedem Projekt so oder so Gedanken über die Struktur seiner Daten machen. Im Fall von Dgraph halte ich es für absolut sinnvoll mit einem Schema zu arbeiten. Es ist in Dgraph auch nicht so, dass man sich mit einem Schema die Flexibilität nimmt. Selbst wenn ein Datensatz als Typ angelegt wurde kann man trotzdem beliebige Felder hinzufügen, die nicht in der Typendefinition enthalten sind. Man muss sich nur darüber klar sein, dass man diese Felder dann in einer Query anfordern muss:

1
2
3
4
5
6
7
8
{
  persons(func: type(Person)){
    fieldname
    expand(_all_) {
      expand(_all_)
    }
  }
}

Ich werde wahrscheinlich an dieser Stelle erst einmal mit den Basics aufhören und in den nächsten Beiträgen zeigen wie man mit dem Go Client mit Dgraph interagiert.