Selecting data

The types used in these queries are defined here.

Select a Movie with associated actors and reviews with their authors:

  1. select Movie {
  2. id,
  3. title,
  4. year,
  5. description,
  6. actors: {
  7. id,
  8. full_name,
  9. },
  10. reviews := .<movie[is Review] {
  11. id,
  12. body,
  13. rating,
  14. author: {
  15. id,
  16. name,
  17. }
  18. },
  19. }
  20. filter .id = <uuid>'09c34154-4148-11ea-9c68-5375ca908326'

Select movies with Keanu Reeves:

  1. select Movie {
  2. id,
  3. title,
  4. year,
  5. description,
  6. }
  7. filter .actors.full_name = 'Keanu Reeves'

Select all actors that share the last name with other actors and include the same-last-name actor list as well:

  1. select Person {
  2. id,
  3. full_name,
  4. same_last_name := (
  5. with
  6. P := detached Person
  7. select P {
  8. id,
  9. full_name,
  10. }
  11. filter
  12. # same last name
  13. P.last_name = Person.last_name
  14. and
  15. # not the same person
  16. P != Person
  17. ),
  18. }
  19. filter exists .same_last_name

The same query can be refactored moving the with block to the top-level:

  1. with
  2. # don't need detached at top-level
  3. P := Person
  4. select Person {
  5. id,
  6. full_name,
  7. same_last_name := (
  8. select P {
  9. id,
  10. full_name,
  11. }
  12. filter
  13. # same last name
  14. P.last_name = Person.last_name
  15. and
  16. # not the same person
  17. P != Person
  18. ),
  19. }
  20. filter exists .same_last_name

Select user names and the number of reviews they have:

  1. select (
  2. User.name,
  3. count(User.<author[is Review])
  4. )

For every user and movie combination, select whether the user has reviewed the movie (beware, in practice this maybe a very large result):

  1. select (
  2. User.name,
  3. Movie.title,
  4. Movie in User.<author[is Review].movie
  5. )

Perform a set intersection of all actors with all directors:

  1. with
  2. # get the set of actors and set of directors
  3. Actor := Movie.actors,
  4. Director := Movie.director,
  5. # set intersection is done via the filter clause
  6. select Actor filter Actor in Director;

To order a set of scalars first assign the set to a variable and use the variable in the order by clause.

  1. select numbers := {3, 1, 2} order by numbers;
  2. # alternatively
  3. with numbers := {3, 1, 2}
  4. select numbers order by numbers;

Selecting free objects.

It is also possible to package data into a free object. Free objects are meant to be transient and used either to more efficiently store some intermediate results in a query or for re-shaping the output. The advantage of using free objects over tuples is that it is easier to package data that potentially contains empty sets as links or properties of the free object. The underlying type of a free object is std::FreeObject.

Consider the following query:

  1. with U := (select User filter .name like '%user%')
  2. select {
  3. matches := U {name},
  4. total := count(U),
  5. total_users := count(User),
  6. };

The matches are potentially {}, yet the query will always return a single free object with results, total, and total_users. To achieve the same using a named tuple, the query would have to be modified like this:

  1. with U := (select User filter .name like '%user%')
  2. select (
  3. matches := array_agg(U {name}),
  4. total := count(U),
  5. total_users := count(User),
  6. );

Without the array_agg() the above query would return {} instead of the named tuple if no matches are found.

See also

EdgeQL > Select

Reference > Commands > Select