====== Dgraph ======
===== References =====
* [[https://dgraph.io|Dgraph docs]]
===== Terminology =====
Mutation - adding/removing data
Mutation formats
* RDF (Resource Description Framework)
* JSON (JavaScript Object Notation)
Mutation paterns
* blank UID reference <_:michael>
* explicit UID reference
===== Schema =====
Infer schema
schema(pred: [name, age, friend, owns_pet]) {
type
index
}
Root level node selection
allofterms(name@en, "Peter Jackson")
anyofterms(name@en, "Peter Jackson")
alloftext(name@en, "the man runs")
===== Filters =====
@filter(has(genre)
@filter(ge(age, 27))
@filter(ge(age, 27) AND le(age, 45))
===== Queries =====
{
michael_friends_and_pet(func: eq(name, "Michael")) {
name
age
friend {
name@.
}
owns_pet {
name
}
}
}
Order ''orderasc'', ''orderdesc''. ''offset'' and selecting ''first'' entries
friend (orderasc: age) {}
friend (orderasc: name@., offset: 1, first: 2) {}
Root level filtering. People who have at least ''2'' friends and have ''20 < = age < 30''
lots_of_friends(func: ge(count(friend), 2)) @filter(ge(age,20) AND lt(age,30)) {}
Get nodes that have specific edge (root selector)
have_friends(func: has(friend)) {}
===== Misc =====
Alias
persons_name : name
number_of_friends : count(friend)
Query Variables (it is error to assign a variable and not use it)
A as not_a_real_query(...) {
B as some_edge @filter(...) { # can't use C or B in this filter
C as ... {
# A, B and C here
}
# A, B and C here
}
# A, B and C can be used in any blocks here
}
# A, B and C can be used in any other query block
Value Variables (map from uid to value) can be used with ''max'', ''min'', ''avg'', ''sum'', ''math''
{
q(func: allofterms(name@en, "Ang Lee")) {
director.film {
uid
name@en
num_actors as count(starring)
}
most_actors : max(val(num_actors))
}
}
Expand all
expand(_all_) { expand(_all_)}
===== Directives =====
''@cascade'' directive removes any nodes that don’t have all matching edges in the query. (remove nodes that of which filters return no results)
michael_friends_with_pets(func: allofterms(name, "Michael")) @cascade {}
''@normalize'' returns only edges with alias and flattens result to remove nesting
michael_number_friends(func: allofterms(name, "Michael")) @normalize {}
===== Example queries =====
{
coactors(func:allofterms(name@en, "Jane Campion")) @cascade {
JC_films as director.film { # JC_films = all Jane Campion's films
starting_movie: name@en
starring {
JC_actors as performance.actor { # JC_actors = all actors in all JC films
actor : name@en
actor.film {
performance.film @filter(not uid(JC_films)) {
film_together : name@en
starring {
# find a coactor who has been in some JC film
performance.actor @filter(uid(JC_actors)) {
coactor_name: name@en
}
}
}
}
}
}
}
}
}
Defining variables
{
PJ as var(func:allofterms(name@en, "Peter Jackson")) @normalize @cascade {
F as director.film
}
peterJ(func: uid(PJ)) @normalize @cascade {
name : name@en
actor.film {
performance.film @filter(uid(F)) {
film_name: name@en
}
performance.character {
character: name@en
}
}
}
}
{
var(func: allofterms(name@en, "Taraji Henson")) {
actor.film {
F as performance.film {
G as genre
}
}
}
Taraji_films_by_genre(func: uid(G)) {
genre_name : name@en
films : ~genre @filter(uid(F)) {
film_name : name@en
}
}
}
{
anotherQ(func: allofterms(name@en, "Taraji Henson")) {
actor.film {
performance.film {
film_name: name@en
genre {
name@en
}
}
}
}
}
Returning single node with information instead of a graph
{
ID as var(func: allofterms(name@en, "Steven Spielberg")) {
director.film {
num_actors as count(starring)
}
average as avg(val(num_actors))
}
avs(func: uid(ID)) @normalize {
name : name@en
average_actors: val(average)
num_films: count(director.film)
}
}
Using value variables for filtering and ordering
{
ID as var(func: allofterms(name@en, "Steven")) {
director.film {
num_actors as count(starring)
}
average as avg(val(num_actors))
}
avs(func: uid(ID), orderdesc: val(average)) @filter(ge(val(average), 40)) @normalize {
name : name@en
average_actors : val(average)
num_films : count(director.film)
}
}
{
var(func:allofterms(name@en, "Jean-Pierre Jeunet")) {
name@en
films as director.film {
stars as count(starring)
directors as count(~director.film)
ratio as math(stars / directors)
}
}
best_ratio(func: uid(films), orderdesc: val(ratio)){
name@en
stars_per_director : val(ratio)
num_stars : val(stars)
}
}
Get latest movies for each director and order by date
{
# Get all directors
var(func: has(director.film)) @cascade {
director.film {
date as initial_release_date
}
# Store maxDate as a variable
maxDate as max(val(date))
daysSince as math(since(maxDate)/(24*60*60))
}
# Order by maxDate
me(func: uid(maxDate), orderdesc: val(maxDate), first: 10) {
name@en
days : val(daysSince)
# For each director, sort by release date and get latest movie.
director.film(orderdesc: initial_release_date, first: 1) {
name@en
initial_release_date
}
}
}
Group by
{
var(func:allofterms(name@en, "Steven Spielberg")) {
director.film @groupby(genre) {
a as count(uid)
}
}
byGenre(func: uid(a), orderdesc: val(a)) {
name@en
num_movies : val(a)
}
}