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