Variables
Query Variables
Syntax Examples:
varName as q(func: ...) { ... }varName as var(func: ...) { ... }varName as predicate { ... }varName as predicate @filter(...) { ... }
Types : uid
Nodes (UIDs) matched at one place in a query can be stored in a variable and used elsewhere. Query variables can be used in other query blocks or in a child node of the defining block.
Query variables do not affect the semantics of the query at the point of definition. Query variables are evaluated to all nodes matched by the defining block.
In general, query blocks are executed in parallel, but variables impose an evaluation order on some blocks. Cycles induced by variable dependence are not permitted.
If a variable is defined, it must be used elsewhere in the query.
A query variable is used by extracting the UIDs in it with uid(var-name).
The syntax func: uid(A,B) or @filter(uid(A,B)) means the union of UIDs for variables A and B.
Query Example: The movies of Angelia Jolie and Brad Pitt where both have acted on movies in the same genre. Note that B and D match all genres for all movies, not genres per movie.
- Query
- Go
- Java
- Python
- JavaScript (gRPC)
- JavaScript (HTTP)
- Curl
{
var(func:allofterms(name@en, "angelina jolie")) {
actor.film {
A AS performance.film { # All films acted in by Angelina Jolie
B As genre # Genres of all the films acted in by Angelina Jolie
}
}
}
var(func:allofterms(name@en, "brad pitt")) {
actor.film {
C AS performance.film { # All films acted in by Brad Pitt
D as genre # Genres of all the films acted in by Brad Pitt
}
}
}
films(func: uid(D)) @filter(uid(B)) { # Genres from both Angelina and Brad
name@en
~genre @filter(uid(A, C)) { # Movies in either A or C.
name@en
}
}
}
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"google.golang.org/grpc"
"github.com/dgraph-io/dgo/v230"
"github.com/dgraph-io/dgo/v230/protos/api"
)
func main() {
conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
}
defer conn.Close()
dgraphClient := dgo.NewDgraphClient(api.NewDgraphClient(conn))
ctx := context.Background()
txn := dgraphClient.NewTxn()
defer txn.Discard(ctx)
query := `{
var(func:allofterms(name@en, "angelina jolie")) {
actor.film {
A AS performance.film { # All films acted in by Angelina Jolie
B As genre # Genres of all the films acted in by Angelina Jolie
}
}
}
var(func:allofterms(name@en, "brad pitt")) {
actor.film {
C AS performance.film { # All films acted in by Brad Pitt
D as genre # Genres of all the films acted in by Brad Pitt
}
}
}
films(func: uid(D)) @filter(uid(B)) { # Genres from both Angelina and Brad
name@en
~genre @filter(uid(A, C)) { # Movies in either A or C.
name@en
}
}
}`
resp, err := txn.Query(ctx, query)
if err != nil {
log.Fatal(err)
}
var result map[string]interface{}
json.Unmarshal(resp.Json, &result)
fmt.Printf("%+v\n", result)
}
import io.dgraph.DgraphClient;
import io.dgraph.DgraphGrpc;
import io.dgraph.DgraphProto;
import io.dgraph.Transaction;
import java.util.Map;
public class App {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost", 9080)
.usePlaintext()
.build();
DgraphGrpc.DgraphStub stub = DgraphGrpc.newStub(channel);
DgraphClient dgraphClient = new DgraphClient(stub);
String query = "{
var(func:allofterms(name@en, \"angelina jolie\")) {
actor.film {
A AS performance.film { # All films acted in by Angelina Jolie
B As genre # Genres of all the films acted in by Angelina Jolie
}
}
}
var(func:allofterms(name@en, \"brad pitt\")) {
actor.film {
C AS performance.film { # All films acted in by Brad Pitt
D as genre # Genres of all the films acted in by Brad Pitt
}
}
}
films(func: uid(D)) @filter(uid(B)) { # Genres from both Angelina and Brad
name@en
~genre @filter(uid(A, C)) { # Movies in either A or C.
name@en
}
}
}";
Transaction txn = dgraphClient.newTransaction();
try {
DgraphProto.Response response = txn.query(query);
System.out.println(response.getJson().toStringUtf8());
} finally {
txn.discard();
}
}
}
import grpc
from dgraph import DgraphClient, Txn
def main():
client_stub = DgraphClient("localhost:9080")
client = DgraphClient(client_stub)
query = """{
var(func:allofterms(name@en, "angelina jolie")) {
actor.film {
A AS performance.film { # All films acted in by Angelina Jolie
B As genre # Genres of all the films acted in by Angelina Jolie
}
}
}
var(func:allofterms(name@en, "brad pitt")) {
actor.film {
C AS performance.film { # All films acted in by Brad Pitt
D as genre # Genres of all the films acted in by Brad Pitt
}
}
}
films(func: uid(D)) @filter(uid(B)) { # Genres from both Angelina and Brad
name@en
~genre @filter(uid(A, C)) { # Movies in either A or C.
name@en
}
}
}"""
txn = client.txn()
try:
response = txn.query(query)
print(response.json)
finally:
txn.discard()
if __name__ == "__main__":
main()
const dgraph = require("dgraph-js");
const grpc = require("grpc");
async function main() {
const clientStub = new dgraph.DgraphClientStub(
"localhost:9080",
grpc.credentials.createInsecure()
);
const dgraphClient = new dgraph.DgraphClient(clientStub);
const query = `{
var(func:allofterms(name@en, "angelina jolie")) {
actor.film {
A AS performance.film { # All films acted in by Angelina Jolie
B As genre # Genres of all the films acted in by Angelina Jolie
}
}
}
var(func:allofterms(name@en, "brad pitt")) {
actor.film {
C AS performance.film { # All films acted in by Brad Pitt
D as genre # Genres of all the films acted in by Brad Pitt
}
}
}
films(func: uid(D)) @filter(uid(B)) { # Genres from both Angelina and Brad
name@en
~genre @filter(uid(A, C)) { # Movies in either A or C.
name@en
}
}
}`;
const txn = dgraphClient.newTxn();
try {
const res = await txn.query(query);
const json = res.getJson();
console.log(JSON.stringify(JSON.parse(json), null, 2));
} finally {
await txn.discard();
}
}
main().catch((e) => {
console.error(e);
});
const fetch = require("node-fetch");
async function main() {
const query = `{
var(func:allofterms(name@en, "angelina jolie")) {
actor.film {
A AS performance.film { # All films acted in by Angelina Jolie
B As genre # Genres of all the films acted in by Angelina Jolie
}
}
}
var(func:allofterms(name@en, "brad pitt")) {
actor.film {
C AS performance.film { # All films acted in by Brad Pitt
D as genre # Genres of all the films acted in by Brad Pitt
}
}
}
films(func: uid(D)) @filter(uid(B)) { # Genres from both Angelina and Brad
name@en
~genre @filter(uid(A, C)) { # Movies in either A or C.
name@en
}
}
}`;
const response = await fetch("http://localhost:8080/query", {
method: "POST",
headers: {
"Content-Type": "application/dql"
},
body: query
});
const result = await response.json();
console.log(JSON.stringify(result, null, 2));
}
main().catch((e) => {
console.error(e);
});
curl -X POST http://localhost:8080/query \
-H "Content-Type: application/dql" \
-d '{
var(func:allofterms(name@en, "angelina jolie")) {
actor.film {
A AS performance.film { # All films acted in by Angelina Jolie
B As genre # Genres of all the films acted in by Angelina Jolie
}
}
}
var(func:allofterms(name@en, "brad pitt")) {
actor.film {
C AS performance.film { # All films acted in by Brad Pitt
D as genre # Genres of all the films acted in by Brad Pitt
}
}
}
films(func: uid(D)) @filter(uid(B)) { # Genres from both Angelina and Brad
name@en
~genre @filter(uid(A, C)) { # Movies in either A or C.
name@en
}
}
}'
Value Variables
Syntax Examples:
varName as scalarPredicatevarName as count(predicate)varName as avg(...)varName as math(...)
Types : int, float, String, dateTime, default, geo, bool
Value variables store scalar values. Value variables are a map from the UIDs of the enclosing block to the corresponding values.
It therefore only makes sense to use the values from a value variable in a context that matches the same UIDs - if used in a block matching different UIDs the value variable is undefined.
It is an error to define a value variable but not use it elsewhere in the query.
Value variables are used by extracting the values with val(var-name), or by extracting the UIDs with uid(var-name).
Facet values can be stored in value variables.
Query Example: The number of movie roles played by the actors of the 80's classic "The Princess Bride". Query variable pbActors matches the UIDs of all actors from the movie. Value variable roles is thus a map from actor UID to number of roles. Value variable roles can be used in the totalRoles query block because that query block also matches the pbActors UIDs, so the actor to number of roles map is available.
- Query
- Go
- Java
- Python
- JavaScript (gRPC)
- JavaScript (HTTP)
- Curl
{
var(func:allofterms(name@en, "The Princess Bride")) {
starring {
pbActors as performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(pbActors), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"google.golang.org/grpc"
"github.com/dgraph-io/dgo/v230"
"github.com/dgraph-io/dgo/v230/protos/api"
)
func main() {
conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
}
defer conn.Close()
dgraphClient := dgo.NewDgraphClient(api.NewDgraphClient(conn))
ctx := context.Background()
txn := dgraphClient.NewTxn()
defer txn.Discard(ctx)
query := `{
var(func:allofterms(name@en, "The Princess Bride")) {
starring {
pbActors as performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(pbActors), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}`
resp, err := txn.Query(ctx, query)
if err != nil {
log.Fatal(err)
}
var result map[string]interface{}
json.Unmarshal(resp.Json, &result)
fmt.Printf("%+v\n", result)
}
import io.dgraph.DgraphClient;
import io.dgraph.DgraphGrpc;
import io.dgraph.DgraphProto;
import io.dgraph.Transaction;
import java.util.Map;
public class App {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost", 9080)
.usePlaintext()
.build();
DgraphGrpc.DgraphStub stub = DgraphGrpc.newStub(channel);
DgraphClient dgraphClient = new DgraphClient(stub);
String query = "{
var(func:allofterms(name@en, \"The Princess Bride\")) {
starring {
pbActors as performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(pbActors), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}";
Transaction txn = dgraphClient.newTransaction();
try {
DgraphProto.Response response = txn.query(query);
System.out.println(response.getJson().toStringUtf8());
} finally {
txn.discard();
}
}
}
import grpc
from dgraph import DgraphClient, Txn
def main():
client_stub = DgraphClient("localhost:9080")
client = DgraphClient(client_stub)
query = """{
var(func:allofterms(name@en, "The Princess Bride")) {
starring {
pbActors as performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(pbActors), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}"""
txn = client.txn()
try:
response = txn.query(query)
print(response.json)
finally:
txn.discard()
if __name__ == "__main__":
main()
const dgraph = require("dgraph-js");
const grpc = require("grpc");
async function main() {
const clientStub = new dgraph.DgraphClientStub(
"localhost:9080",
grpc.credentials.createInsecure()
);
const dgraphClient = new dgraph.DgraphClient(clientStub);
const query = `{
var(func:allofterms(name@en, "The Princess Bride")) {
starring {
pbActors as performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(pbActors), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}`;
const txn = dgraphClient.newTxn();
try {
const res = await txn.query(query);
const json = res.getJson();
console.log(JSON.stringify(JSON.parse(json), null, 2));
} finally {
await txn.discard();
}
}
main().catch((e) => {
console.error(e);
});
const fetch = require("node-fetch");
async function main() {
const query = `{
var(func:allofterms(name@en, "The Princess Bride")) {
starring {
pbActors as performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(pbActors), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}`;
const response = await fetch("http://localhost:8080/query", {
method: "POST",
headers: {
"Content-Type": "application/dql"
},
body: query
});
const result = await response.json();
console.log(JSON.stringify(result, null, 2));
}
main().catch((e) => {
console.error(e);
});
curl -X POST http://localhost:8080/query \
-H "Content-Type: application/dql" \
-d '{
var(func:allofterms(name@en, "The Princess Bride")) {
starring {
pbActors as performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(pbActors), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}'
Value variables can be used in place of UID variables by extracting the UID list from the map.
Query Example: The same query as the previous example, but using value variable roles for matching UIDs in the totalRoles query block.
- Query
- Go
- Java
- Python
- JavaScript (gRPC)
- JavaScript (HTTP)
- Curl
{
var(func:allofterms(name@en, "The Princess Bride")) {
starring {
performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(roles), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"google.golang.org/grpc"
"github.com/dgraph-io/dgo/v230"
"github.com/dgraph-io/dgo/v230/protos/api"
)
func main() {
conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
}
defer conn.Close()
dgraphClient := dgo.NewDgraphClient(api.NewDgraphClient(conn))
ctx := context.Background()
txn := dgraphClient.NewTxn()
defer txn.Discard(ctx)
query := `{
var(func:allofterms(name@en, "The Princess Bride")) {
starring {
performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(roles), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}`
resp, err := txn.Query(ctx, query)
if err != nil {
log.Fatal(err)
}
var result map[string]interface{}
json.Unmarshal(resp.Json, &result)
fmt.Printf("%+v\n", result)
}
import io.dgraph.DgraphClient;
import io.dgraph.DgraphGrpc;
import io.dgraph.DgraphProto;
import io.dgraph.Transaction;
import java.util.Map;
public class App {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost", 9080)
.usePlaintext()
.build();
DgraphGrpc.DgraphStub stub = DgraphGrpc.newStub(channel);
DgraphClient dgraphClient = new DgraphClient(stub);
String query = "{
var(func:allofterms(name@en, \"The Princess Bride\")) {
starring {
performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(roles), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}";
Transaction txn = dgraphClient.newTransaction();
try {
DgraphProto.Response response = txn.query(query);
System.out.println(response.getJson().toStringUtf8());
} finally {
txn.discard();
}
}
}
import grpc
from dgraph import DgraphClient, Txn
def main():
client_stub = DgraphClient("localhost:9080")
client = DgraphClient(client_stub)
query = """{
var(func:allofterms(name@en, "The Princess Bride")) {
starring {
performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(roles), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}"""
txn = client.txn()
try:
response = txn.query(query)
print(response.json)
finally:
txn.discard()
if __name__ == "__main__":
main()
const dgraph = require("dgraph-js");
const grpc = require("grpc");
async function main() {
const clientStub = new dgraph.DgraphClientStub(
"localhost:9080",
grpc.credentials.createInsecure()
);
const dgraphClient = new dgraph.DgraphClient(clientStub);
const query = `{
var(func:allofterms(name@en, "The Princess Bride")) {
starring {
performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(roles), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}`;
const txn = dgraphClient.newTxn();
try {
const res = await txn.query(query);
const json = res.getJson();
console.log(JSON.stringify(JSON.parse(json), null, 2));
} finally {
await txn.discard();
}
}
main().catch((e) => {
console.error(e);
});
const fetch = require("node-fetch");
async function main() {
const query = `{
var(func:allofterms(name@en, "The Princess Bride")) {
starring {
performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(roles), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}`;
const response = await fetch("http://localhost:8080/query", {
method: "POST",
headers: {
"Content-Type": "application/dql"
},
body: query
});
const result = await response.json();
console.log(JSON.stringify(result, null, 2));
}
main().catch((e) => {
console.error(e);
});
curl -X POST http://localhost:8080/query \
-H "Content-Type: application/dql" \
-d '{
var(func:allofterms(name@en, "The Princess Bride")) {
starring {
performance.actor {
roles as count(actor.film)
}
}
}
totalRoles(func: uid(roles), orderasc: val(roles)) {
name@en
numRoles : val(roles)
}
}'
Variable Propagation
Like query variables, value variables can be used in other query blocks and in blocks nested within the defining block. When used in a block nested within the block that defines the variable, the value is computed as a sum of the variable for parent nodes along all paths to the point of use. This is called variable propagation.
For example:
{
q(func: uid(0x01)) {
myscore as math(1) # A
friends { # B
friends { # C
...myscore...
}
}
}
}
At line A, a value variable myscore is defined as mapping node with UID 0x01 to value 1. At B, the value for each friend is still 1: there is only one path to each friend. Traversing the friend edge twice reaches the friends of friends. The variable myscore gets propagated such that each friend of friend will receive the sum of its parents values: if a friend of a friend is reachable from only one friend, the value is still 1, if they are reachable from two friends, the value is two and so on. That is, the value of myscore for each friend of friends inside the block marked C will be the number of paths to them.
The value that a node receives for a propagated variable is the sum of the values of all its parent nodes.
This propagation is useful, for example, in normalizing a sum across users, finding the number of paths between nodes and accumulating a sum through a graph.
Query Example: For each Harry Potter movie, the number of roles played by actor Warwick Davis.
- Query
- Go
- Java
- Python
- JavaScript (gRPC)
- JavaScript (HTTP)
- Curl
{
num_roles(func: eq(name@en, "Warwick Davis")) @cascade @normalize {
paths as math(1) # records number of paths to each character
actor : name@en
actor.film {
performance.film @filter(allofterms(name@en, "Harry Potter")) {
film_name : name@en
characters : math(paths) # how many paths (i.e. characters) reach this film
}
}
}
}
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"google.golang.org/grpc"
"github.com/dgraph-io/dgo/v230"
"github.com/dgraph-io/dgo/v230/protos/api"
)
func main() {
conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
}
defer conn.Close()
dgraphClient := dgo.NewDgraphClient(api.NewDgraphClient(conn))
ctx := context.Background()
txn := dgraphClient.NewTxn()
defer txn.Discard(ctx)
query := `{
num_roles(func: eq(name@en, "Warwick Davis")) @cascade @normalize {
paths as math(1) # records number of paths to each character
actor : name@en
actor.film {
performance.film @filter(allofterms(name@en, "Harry Potter")) {
film_name : name@en
characters : math(paths) # how many paths (i.e. characters) reach this film
}
}
}
}`
resp, err := txn.Query(ctx, query)
if err != nil {
log.Fatal(err)
}
var result map[string]interface{}
json.Unmarshal(resp.Json, &result)
fmt.Printf("%+v\n", result)
}
import io.dgraph.DgraphClient;
import io.dgraph.DgraphGrpc;
import io.dgraph.DgraphProto;
import io.dgraph.Transaction;
import java.util.Map;
public class App {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost", 9080)
.usePlaintext()
.build();
DgraphGrpc.DgraphStub stub = DgraphGrpc.newStub(channel);
DgraphClient dgraphClient = new DgraphClient(stub);
String query = "{
num_roles(func: eq(name@en, \"Warwick Davis\")) @cascade @normalize {
paths as math(1) # records number of paths to each character
actor : name@en
actor.film {
performance.film @filter(allofterms(name@en, \"Harry Potter\")) {
film_name : name@en
characters : math(paths) # how many paths (i.e. characters) reach this film
}
}
}
}";
Transaction txn = dgraphClient.newTransaction();
try {
DgraphProto.Response response = txn.query(query);
System.out.println(response.getJson().toStringUtf8());
} finally {
txn.discard();
}
}
}
import grpc
from dgraph import DgraphClient, Txn
def main():
client_stub = DgraphClient("localhost:9080")
client = DgraphClient(client_stub)
query = """{
num_roles(func: eq(name@en, "Warwick Davis")) @cascade @normalize {
paths as math(1) # records number of paths to each character
actor : name@en
actor.film {
performance.film @filter(allofterms(name@en, "Harry Potter")) {
film_name : name@en
characters : math(paths) # how many paths (i.e. characters) reach this film
}
}
}
}"""
txn = client.txn()
try:
response = txn.query(query)
print(response.json)
finally:
txn.discard()
if __name__ == "__main__":
main()
const dgraph = require("dgraph-js");
const grpc = require("grpc");
async function main() {
const clientStub = new dgraph.DgraphClientStub(
"localhost:9080",
grpc.credentials.createInsecure()
);
const dgraphClient = new dgraph.DgraphClient(clientStub);
const query = `{
num_roles(func: eq(name@en, "Warwick Davis")) @cascade @normalize {
paths as math(1) # records number of paths to each character
actor : name@en
actor.film {
performance.film @filter(allofterms(name@en, "Harry Potter")) {
film_name : name@en
characters : math(paths) # how many paths (i.e. characters) reach this film
}
}
}
}`;
const txn = dgraphClient.newTxn();
try {
const res = await txn.query(query);
const json = res.getJson();
console.log(JSON.stringify(JSON.parse(json), null, 2));
} finally {
await txn.discard();
}
}
main().catch((e) => {
console.error(e);
});
const fetch = require("node-fetch");
async function main() {
const query = `{
num_roles(func: eq(name@en, "Warwick Davis")) @cascade @normalize {
paths as math(1) # records number of paths to each character
actor : name@en
actor.film {
performance.film @filter(allofterms(name@en, "Harry Potter")) {
film_name : name@en
characters : math(paths) # how many paths (i.e. characters) reach this film
}
}
}
}`;
const response = await fetch("http://localhost:8080/query", {
method: "POST",
headers: {
"Content-Type": "application/dql"
},
body: query
});
const result = await response.json();
console.log(JSON.stringify(result, null, 2));
}
main().catch((e) => {
console.error(e);
});
curl -X POST http://localhost:8080/query \
-H "Content-Type: application/dql" \
-d '{
num_roles(func: eq(name@en, "Warwick Davis")) @cascade @normalize {
paths as math(1) # records number of paths to each character
actor : name@en
actor.film {
performance.film @filter(allofterms(name@en, "Harry Potter")) {
film_name : name@en
characters : math(paths) # how many paths (i.e. characters) reach this film
}
}
}
}'
Query Example: Each actor who has been in a Peter Jackson movie and the fraction of Peter Jackson movies they have appeared in.
- Query
- Go
- Java
- Python
- JavaScript (gRPC)
- JavaScript (HTTP)
- Curl
{
movie_fraction(func:eq(name@en, "Peter Jackson")) @normalize {
paths as math(1)
total_films : num_films as count(director.film)
director : name@en
director.film {
starring {
performance.actor {
fraction : math(paths / (num_films/paths))
actor : name@en
}
}
}
}
}
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"google.golang.org/grpc"
"github.com/dgraph-io/dgo/v230"
"github.com/dgraph-io/dgo/v230/protos/api"
)
func main() {
conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
}
defer conn.Close()
dgraphClient := dgo.NewDgraphClient(api.NewDgraphClient(conn))
ctx := context.Background()
txn := dgraphClient.NewTxn()
defer txn.Discard(ctx)
query := `{
movie_fraction(func:eq(name@en, "Peter Jackson")) @normalize {
paths as math(1)
total_films : num_films as count(director.film)
director : name@en
director.film {
starring {
performance.actor {
fraction : math(paths / (num_films/paths))
actor : name@en
}
}
}
}
}`
resp, err := txn.Query(ctx, query)
if err != nil {
log.Fatal(err)
}
var result map[string]interface{}
json.Unmarshal(resp.Json, &result)
fmt.Printf("%+v\n", result)
}
import io.dgraph.DgraphClient;
import io.dgraph.DgraphGrpc;
import io.dgraph.DgraphProto;
import io.dgraph.Transaction;
import java.util.Map;
public class App {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost", 9080)
.usePlaintext()
.build();
DgraphGrpc.DgraphStub stub = DgraphGrpc.newStub(channel);
DgraphClient dgraphClient = new DgraphClient(stub);
String query = "{
movie_fraction(func:eq(name@en, \"Peter Jackson\")) @normalize {
paths as math(1)
total_films : num_films as count(director.film)
director : name@en
director.film {
starring {
performance.actor {
fraction : math(paths / (num_films/paths))
actor : name@en
}
}
}
}
}";
Transaction txn = dgraphClient.newTransaction();
try {
DgraphProto.Response response = txn.query(query);
System.out.println(response.getJson().toStringUtf8());
} finally {
txn.discard();
}
}
}
import grpc
from dgraph import DgraphClient, Txn
def main():
client_stub = DgraphClient("localhost:9080")
client = DgraphClient(client_stub)
query = """{
movie_fraction(func:eq(name@en, "Peter Jackson")) @normalize {
paths as math(1)
total_films : num_films as count(director.film)
director : name@en
director.film {
starring {
performance.actor {
fraction : math(paths / (num_films/paths))
actor : name@en
}
}
}
}
}"""
txn = client.txn()
try:
response = txn.query(query)
print(response.json)
finally:
txn.discard()
if __name__ == "__main__":
main()
const dgraph = require("dgraph-js");
const grpc = require("grpc");
async function main() {
const clientStub = new dgraph.DgraphClientStub(
"localhost:9080",
grpc.credentials.createInsecure()
);
const dgraphClient = new dgraph.DgraphClient(clientStub);
const query = `{
movie_fraction(func:eq(name@en, "Peter Jackson")) @normalize {
paths as math(1)
total_films : num_films as count(director.film)
director : name@en
director.film {
starring {
performance.actor {
fraction : math(paths / (num_films/paths))
actor : name@en
}
}
}
}
}`;
const txn = dgraphClient.newTxn();
try {
const res = await txn.query(query);
const json = res.getJson();
console.log(JSON.stringify(JSON.parse(json), null, 2));
} finally {
await txn.discard();
}
}
main().catch((e) => {
console.error(e);
});
const fetch = require("node-fetch");
async function main() {
const query = `{
movie_fraction(func:eq(name@en, "Peter Jackson")) @normalize {
paths as math(1)
total_films : num_films as count(director.film)
director : name@en
director.film {
starring {
performance.actor {
fraction : math(paths / (num_films/paths))
actor : name@en
}
}
}
}
}`;
const response = await fetch("http://localhost:8080/query", {
method: "POST",
headers: {
"Content-Type": "application/dql"
},
body: query
});
const result = await response.json();
console.log(JSON.stringify(result, null, 2));
}
main().catch((e) => {
console.error(e);
});
curl -X POST http://localhost:8080/query \
-H "Content-Type: application/dql" \
-d '{
movie_fraction(func:eq(name@en, "Peter Jackson")) @normalize {
paths as math(1)
total_films : num_films as count(director.film)
director : name@en
director.film {
starring {
performance.actor {
fraction : math(paths / (num_films/paths))
actor : name@en
}
}
}
}
}'
More examples can be found in two Dgraph blog posts about using variable propagation for recommendation engines (post 1, post 2).
Math on value variables
Value variables can be combined using mathematical functions. For example, this could be used to associate a score which is then used to order or perform other operations, such as might be used in building news feeds, simple recommendation systems, and so on.
Math statements must be enclosed within math( <exp> ) and must be stored to a value variable.
The supported operators are as follows:
| Operators | Types accepted | What it does |
|---|---|---|
+ - * / % | int, float | performs the corresponding operation |
min max | All types except geo, bool (binary functions) | selects the min/max value among the two |
< > <= >= == != | All types except geo, bool | Returns true or false based on the values |
floor ceil ln exp sqrt | int, float (unary function) | performs the corresponding operation |
since | dateTime | Returns the number of seconds in float from the time specified |
pow(a, b) | int, float | Returns a to the power b |
logbase(a,b) | int, float | Returns log(a) to the base b |
cond(a, b, c) | first operand must be a Boolean | selects b if a is true else c |
If an integer overflow occurs, or an operand is passed to a math operation (such as ln, logbase, sqrt, pow)
which results in an illegal operation, Dgraph will return an error.
Query Example: Form a score for each of Steven Spielberg's movies as the sum of number of actors, number of genres and number of countries. List the top five such movies in order of decreasing score.
- Query
- Go
- Java
- Python
- JavaScript (gRPC)
- JavaScript (HTTP)
- Curl
{
var(func:allofterms(name@en, "steven spielberg")) {
films as director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
}
TopMovies(func: uid(films), orderdesc: val(score), first: 5){
name@en
val(score)
}
}
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"google.golang.org/grpc"
"github.com/dgraph-io/dgo/v230"
"github.com/dgraph-io/dgo/v230/protos/api"
)
func main() {
conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
}
defer conn.Close()
dgraphClient := dgo.NewDgraphClient(api.NewDgraphClient(conn))
ctx := context.Background()
txn := dgraphClient.NewTxn()
defer txn.Discard(ctx)
query := `{
var(func:allofterms(name@en, "steven spielberg")) {
films as director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
}
TopMovies(func: uid(films), orderdesc: val(score), first: 5){
name@en
val(score)
}
}`
resp, err := txn.Query(ctx, query)
if err != nil {
log.Fatal(err)
}
var result map[string]interface{}
json.Unmarshal(resp.Json, &result)
fmt.Printf("%+v\n", result)
}
import io.dgraph.DgraphClient;
import io.dgraph.DgraphGrpc;
import io.dgraph.DgraphProto;
import io.dgraph.Transaction;
import java.util.Map;
public class App {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost", 9080)
.usePlaintext()
.build();
DgraphGrpc.DgraphStub stub = DgraphGrpc.newStub(channel);
DgraphClient dgraphClient = new DgraphClient(stub);
String query = "{
var(func:allofterms(name@en, \"steven spielberg\")) {
films as director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
}
TopMovies(func: uid(films), orderdesc: val(score), first: 5){
name@en
val(score)
}
}";
Transaction txn = dgraphClient.newTransaction();
try {
DgraphProto.Response response = txn.query(query);
System.out.println(response.getJson().toStringUtf8());
} finally {
txn.discard();
}
}
}
import grpc
from dgraph import DgraphClient, Txn
def main():
client_stub = DgraphClient("localhost:9080")
client = DgraphClient(client_stub)
query = """{
var(func:allofterms(name@en, "steven spielberg")) {
films as director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
}
TopMovies(func: uid(films), orderdesc: val(score), first: 5){
name@en
val(score)
}
}"""
txn = client.txn()
try:
response = txn.query(query)
print(response.json)
finally:
txn.discard()
if __name__ == "__main__":
main()
const dgraph = require("dgraph-js");
const grpc = require("grpc");
async function main() {
const clientStub = new dgraph.DgraphClientStub(
"localhost:9080",
grpc.credentials.createInsecure()
);
const dgraphClient = new dgraph.DgraphClient(clientStub);
const query = `{
var(func:allofterms(name@en, "steven spielberg")) {
films as director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
}
TopMovies(func: uid(films), orderdesc: val(score), first: 5){
name@en
val(score)
}
}`;
const txn = dgraphClient.newTxn();
try {
const res = await txn.query(query);
const json = res.getJson();
console.log(JSON.stringify(JSON.parse(json), null, 2));
} finally {
await txn.discard();
}
}
main().catch((e) => {
console.error(e);
});
const fetch = require("node-fetch");
async function main() {
const query = `{
var(func:allofterms(name@en, "steven spielberg")) {
films as director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
}
TopMovies(func: uid(films), orderdesc: val(score), first: 5){
name@en
val(score)
}
}`;
const response = await fetch("http://localhost:8080/query", {
method: "POST",
headers: {
"Content-Type": "application/dql"
},
body: query
});
const result = await response.json();
console.log(JSON.stringify(result, null, 2));
}
main().catch((e) => {
console.error(e);
});
curl -X POST http://localhost:8080/query \
-H "Content-Type: application/dql" \
-d '{
var(func:allofterms(name@en, "steven spielberg")) {
films as director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
}
TopMovies(func: uid(films), orderdesc: val(score), first: 5){
name@en
val(score)
}
}'
Value variables and aggregations of them can be used in filters.
Query Example: Calculate a score for each Steven Spielberg movie with a condition on release date to penalize movies that are more than 20 years old, filtering on the resulting score.
- Query
- Go
- Java
- Python
- JavaScript (gRPC)
- JavaScript (HTTP)
- Curl
{
var(func:allofterms(name@en, "steven spielberg")) {
films as director.film {
p as count(starring)
q as count(genre)
date as initial_release_date
years as math(since(date)/(365*24*60*60))
score as math(cond(years > 20, 0, ln(p)+q-ln(years)))
}
}
TopMovies(func: uid(films), orderdesc: val(score)) @filter(gt(val(score), 2)){
name@en
val(score)
val(date)
}
}
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"google.golang.org/grpc"
"github.com/dgraph-io/dgo/v230"
"github.com/dgraph-io/dgo/v230/protos/api"
)
func main() {
conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
}
defer conn.Close()
dgraphClient := dgo.NewDgraphClient(api.NewDgraphClient(conn))
ctx := context.Background()
txn := dgraphClient.NewTxn()
defer txn.Discard(ctx)
query := `{
var(func:allofterms(name@en, "steven spielberg")) {
films as director.film {
p as count(starring)
q as count(genre)
date as initial_release_date
years as math(since(date)/(365*24*60*60))
score as math(cond(years > 20, 0, ln(p)+q-ln(years)))
}
}
TopMovies(func: uid(films), orderdesc: val(score)) @filter(gt(val(score), 2)){
name@en
val(score)
val(date)
}
}`
resp, err := txn.Query(ctx, query)
if err != nil {
log.Fatal(err)
}
var result map[string]interface{}
json.Unmarshal(resp.Json, &result)
fmt.Printf("%+v\n", result)
}
import io.dgraph.DgraphClient;
import io.dgraph.DgraphGrpc;
import io.dgraph.DgraphProto;
import io.dgraph.Transaction;
import java.util.Map;
public class App {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost", 9080)
.usePlaintext()
.build();
DgraphGrpc.DgraphStub stub = DgraphGrpc.newStub(channel);
DgraphClient dgraphClient = new DgraphClient(stub);
String query = "{
var(func:allofterms(name@en, \"steven spielberg\")) {
films as director.film {
p as count(starring)
q as count(genre)
date as initial_release_date
years as math(since(date)/(365*24*60*60))
score as math(cond(years > 20, 0, ln(p)+q-ln(years)))
}
}
TopMovies(func: uid(films), orderdesc: val(score)) @filter(gt(val(score), 2)){
name@en
val(score)
val(date)
}
}";
Transaction txn = dgraphClient.newTransaction();
try {
DgraphProto.Response response = txn.query(query);
System.out.println(response.getJson().toStringUtf8());
} finally {
txn.discard();
}
}
}
import grpc
from dgraph import DgraphClient, Txn
def main():
client_stub = DgraphClient("localhost:9080")
client = DgraphClient(client_stub)
query = """{
var(func:allofterms(name@en, "steven spielberg")) {
films as director.film {
p as count(starring)
q as count(genre)
date as initial_release_date
years as math(since(date)/(365*24*60*60))
score as math(cond(years > 20, 0, ln(p)+q-ln(years)))
}
}
TopMovies(func: uid(films), orderdesc: val(score)) @filter(gt(val(score), 2)){
name@en
val(score)
val(date)
}
}"""
txn = client.txn()
try:
response = txn.query(query)
print(response.json)
finally:
txn.discard()
if __name__ == "__main__":
main()
const dgraph = require("dgraph-js");
const grpc = require("grpc");
async function main() {
const clientStub = new dgraph.DgraphClientStub(
"localhost:9080",
grpc.credentials.createInsecure()
);
const dgraphClient = new dgraph.DgraphClient(clientStub);
const query = `{
var(func:allofterms(name@en, "steven spielberg")) {
films as director.film {
p as count(starring)
q as count(genre)
date as initial_release_date
years as math(since(date)/(365*24*60*60))
score as math(cond(years > 20, 0, ln(p)+q-ln(years)))
}
}
TopMovies(func: uid(films), orderdesc: val(score)) @filter(gt(val(score), 2)){
name@en
val(score)
val(date)
}
}`;
const txn = dgraphClient.newTxn();
try {
const res = await txn.query(query);
const json = res.getJson();
console.log(JSON.stringify(JSON.parse(json), null, 2));
} finally {
await txn.discard();
}
}
main().catch((e) => {
console.error(e);
});
const fetch = require("node-fetch");
async function main() {
const query = `{
var(func:allofterms(name@en, "steven spielberg")) {
films as director.film {
p as count(starring)
q as count(genre)
date as initial_release_date
years as math(since(date)/(365*24*60*60))
score as math(cond(years > 20, 0, ln(p)+q-ln(years)))
}
}
TopMovies(func: uid(films), orderdesc: val(score)) @filter(gt(val(score), 2)){
name@en
val(score)
val(date)
}
}`;
const response = await fetch("http://localhost:8080/query", {
method: "POST",
headers: {
"Content-Type": "application/dql"
},
body: query
});
const result = await response.json();
console.log(JSON.stringify(result, null, 2));
}
main().catch((e) => {
console.error(e);
});
curl -X POST http://localhost:8080/query \
-H "Content-Type: application/dql" \
-d '{
var(func:allofterms(name@en, "steven spielberg")) {
films as director.film {
p as count(starring)
q as count(genre)
date as initial_release_date
years as math(since(date)/(365*24*60*60))
score as math(cond(years > 20, 0, ln(p)+q-ln(years)))
}
}
TopMovies(func: uid(films), orderdesc: val(score)) @filter(gt(val(score), 2)){
name@en
val(score)
val(date)
}
}'
Values calculated with math operations are stored to value variables and so can be aggregated.
Query Example: Compute a score for each Steven Spielberg movie and then aggregate the score.
- Query
- Go
- Java
- Python
- JavaScript (gRPC)
- JavaScript (HTTP)
- Curl
{
steven as var(func:eq(name@en, "Steven Spielberg")) @filter(has(director.film)) {
director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
directorScore as sum(val(score))
}
score(func: uid(steven)){
name@en
val(directorScore)
}
}
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"google.golang.org/grpc"
"github.com/dgraph-io/dgo/v230"
"github.com/dgraph-io/dgo/v230/protos/api"
)
func main() {
conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
}
defer conn.Close()
dgraphClient := dgo.NewDgraphClient(api.NewDgraphClient(conn))
ctx := context.Background()
txn := dgraphClient.NewTxn()
defer txn.Discard(ctx)
query := `{
steven as var(func:eq(name@en, "Steven Spielberg")) @filter(has(director.film)) {
director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
directorScore as sum(val(score))
}
score(func: uid(steven)){
name@en
val(directorScore)
}
}`
resp, err := txn.Query(ctx, query)
if err != nil {
log.Fatal(err)
}
var result map[string]interface{}
json.Unmarshal(resp.Json, &result)
fmt.Printf("%+v\n", result)
}
import io.dgraph.DgraphClient;
import io.dgraph.DgraphGrpc;
import io.dgraph.DgraphProto;
import io.dgraph.Transaction;
import java.util.Map;
public class App {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost", 9080)
.usePlaintext()
.build();
DgraphGrpc.DgraphStub stub = DgraphGrpc.newStub(channel);
DgraphClient dgraphClient = new DgraphClient(stub);
String query = "{
steven as var(func:eq(name@en, \"Steven Spielberg\")) @filter(has(director.film)) {
director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
directorScore as sum(val(score))
}
score(func: uid(steven)){
name@en
val(directorScore)
}
}";
Transaction txn = dgraphClient.newTransaction();
try {
DgraphProto.Response response = txn.query(query);
System.out.println(response.getJson().toStringUtf8());
} finally {
txn.discard();
}
}
}
import grpc
from dgraph import DgraphClient, Txn
def main():
client_stub = DgraphClient("localhost:9080")
client = DgraphClient(client_stub)
query = """{
steven as var(func:eq(name@en, "Steven Spielberg")) @filter(has(director.film)) {
director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
directorScore as sum(val(score))
}
score(func: uid(steven)){
name@en
val(directorScore)
}
}"""
txn = client.txn()
try:
response = txn.query(query)
print(response.json)
finally:
txn.discard()
if __name__ == "__main__":
main()
const dgraph = require("dgraph-js");
const grpc = require("grpc");
async function main() {
const clientStub = new dgraph.DgraphClientStub(
"localhost:9080",
grpc.credentials.createInsecure()
);
const dgraphClient = new dgraph.DgraphClient(clientStub);
const query = `{
steven as var(func:eq(name@en, "Steven Spielberg")) @filter(has(director.film)) {
director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
directorScore as sum(val(score))
}
score(func: uid(steven)){
name@en
val(directorScore)
}
}`;
const txn = dgraphClient.newTxn();
try {
const res = await txn.query(query);
const json = res.getJson();
console.log(JSON.stringify(JSON.parse(json), null, 2));
} finally {
await txn.discard();
}
}
main().catch((e) => {
console.error(e);
});
const fetch = require("node-fetch");
async function main() {
const query = `{
steven as var(func:eq(name@en, "Steven Spielberg")) @filter(has(director.film)) {
director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
directorScore as sum(val(score))
}
score(func: uid(steven)){
name@en
val(directorScore)
}
}`;
const response = await fetch("http://localhost:8080/query", {
method: "POST",
headers: {
"Content-Type": "application/dql"
},
body: query
});
const result = await response.json();
console.log(JSON.stringify(result, null, 2));
}
main().catch((e) => {
console.error(e);
});
curl -X POST http://localhost:8080/query \
-H "Content-Type: application/dql" \
-d '{
steven as var(func:eq(name@en, "Steven Spielberg")) @filter(has(director.film)) {
director.film {
p as count(starring)
q as count(genre)
r as count(country)
score as math(p + q + r)
}
directorScore as sum(val(score))
}
score(func: uid(steven)){
name@en
val(directorScore)
}
}'