Table of Contents

Dgraph

References

Terminology

Mutation - adding/removing data

Mutation formats

Mutation paterns

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)
  }
}