Supporting complex queries with variables

We brainstormed various ways by which we could do complex queries. We think using variables is better; and we have proposed solutions for all these queries. Have a look and give your opinions, @minions.

1. Find movies released after 2016, which have any of hanks or pitt as actors.

Using modified existing syntax

{
	films(gt(film.film.initial_release_date, 2016))
		@filter(intersects([film.film.performance, film.performance.actor], anyof(type.object.name.en, "hanks pitt"))) {
		type.object.name.en
		film.film.initial_release_date
		film.film.performance {
			film.performance.actor {
				type.object.name.en
			}
		}
	}
}

With Variables

{
	F AS var(gt(film.film.initial_release_date, 2016)) {
		film.film.performance {
			film.performance.actor @filter(anyof(type.object.name.en, "hanks pitt"))
		}
	}

	films(F) {
		type.object.name.en
		film.film.initial_release_date
		film.film.performance {
			film.performance.actor {
				type.object.name.en
			}
		}
	}
}

2. Find movies released after 2016, with actors hanks or pitt, and director spielberg or scorsese.

{
	films(gt(film.film.initial_release_date, 2016))
		@filter(intersects([film.film.performance, film.performance.actor], anyof(type.object.name.en, "hanks pitt")) &&
						intersects([film.film.directed_by], anyof(type.object.name.en, "spielberg scorsese")) {
		type.object.name.en
		film.film.initial_release_date
		film.film.performance {
			film.performance.actor {
				type.object.name.en
			}
		}
	}
}

With variables

{
	F AS var(gt(film.film.initial_release_date, 2016)) {
		film.film.performance {
			film.performance.actor @filter(anyof(type.object.name.en, "hanks pitt"))
		}
		film.film.directed_by @filter(anyof(type.object.name.en, "spielberg scorsese"))
	}

	films(F) {
		type.object.name.en
		film.film.initial_release_date
		film.film.performance {
			film.performance.actor {
				type.object.name.en
			}
		}
	}
}

3. Find all actors who acted in any movie after 2016, and were also starring in movies by spielberg or scorsese.

The following doesn’t really give us what we want.

{
	films(gt(film.film.initial_release_date, 2016)) {
		type.object.name.en

		film.film.performance {
			film.performance.actor @filter(intersects[
				film.actor.performance, film.performance.film, film.film.directed_by],
				anyof(type.object.name.en, "spielberg scorsese")) {

				type.object.name.en # Doesn't give us a way to retrieve films this actor has done since 2016.
			}
		}
	}
}

With variables

{
	var(gt(film.film.initial_release_date, 2016)) {
		film.film.performance {
			A AS film.performance.actor
		}
	}

	# Any of these two calculations for B would work.
	var(anyof(type.object.name.en, "spielberg scorsese")) {
		film.director.film {
			film.film.performance {
				B AS film.performance.actor @filter(id(A))
			}
		}
	}

	B AS var(id: A) {
		film.actor.performance {
			film.performance.film {
				film.film.directed_by @filter(anyof(type.object.name.en, "spielberg scorsese"))
			}
		}
	}

	# Actual retrieval.
	actors(B) {
		type.object.name.en
		film.actor.performance {
			film.performance.film @filter(gt(film.film.initial_release_date, 2016)) {
				type.object.name.en
			}
		}
	}
}

4. Countries that Countney and Jennifer has acted in.

{
	var(anyof(type.object.name.en, "Courtney")) {
		film.actor.performance {
			film.performance.film {
				A AS film.film.country
			}
		}
	}

	var(anyof(type.object.name.en, "Jennifer")) {
		film.actor.performance {
			film.performance.film {
				B AS film.film.country
			}
		}
	}

	country(A) @filter(id(B)) {
		type.object.name.en
	}
}

Are the variables limited to representing uid only ? Since scalar values doesn’t have a uid, how about searching for all actors who have same age as Jennifer.

2 Likes

To do that, we’ll have to have variables pick up values as well. That would get a bit complicated; but allow queries like you mention above.

Letting variables pick up values can enable even more complex queries.

In future when we support this, it might not be always possible to cleanly keep variables outside the final query.

Example, find all films where actor was less than 20 years old when the film was released and the film was release after 2016.(datediff function i have written for example sake - doesn’t exist now)

films(id: F) {
		type.object.name.en
	         A: film.film.initial_release_date
		film.film.performance {
			film.performance.actor {
				type.object.name.en
                                film.actor.dob @filter(datediff_lt(A, 20))
			}
		}
}

Similar thing is possible with uids also.

Example: Find all the employees in dgraph who have a colleague with whom he has worked in his previous company.
Where F denotes say lists of employees working at dgraph.

employee(id : F) {
		type.object.name.en
	         A: employee.previous.company
		employee.colleague { 
                     type.object.name.en
                     employee.previous.company @filter(id(A))
                }
}
1 Like

How to use Query variables with mutation blocks. I want to add edge from new node to one of the existing nodes. So I want to get the var reference to already existing node and use it in mutation / set block while creating new node.

@davcdhanesh1: We currently don’t support using variables in mutations. To add a reference to an existing node, you’d have to use its UID. You can file an issue if you think this can be made better (with your example in mind) and we can look into that.

Thanks!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.