Search code examples
edgedb

How to get results with empty link OR specific link in EdgeQL?


If I have this schema:

module default {

  type Publisher {
    required property name -> str;
  }

  type Book {
    required property name -> str;
    link publisher -> Publisher;
  }

}

With this data inserted:

insert Publisher { name := 'Dundurn Press' };
insert Book { name := 'Lost Shadow', publisher := assert_single((select Publisher filter .name = 'Dundurn Press')) };
insert Book { name := 'My Unpublished Book' };

Then running the following queries:

select Book { name } filter not exists .publisher;
select Book { name } filter .publisher.name = 'Dundurn Press';
select Book { name } filter .publisher.name = 'Dundurn Press' or not exists .publisher;
  • The first query returns 'My Unpublished Book' as expected
  • The second query returns 'Lost Shadow' as expected
  • However, I intended for the third query to return both books (all books with no publisher, combined with books by one specific publisher)

How should I write the third query to return what is expected?

In SQL, I would do something like this, which would return books with no publisher and books published by 'Dundurn Press':

select b.name
from books b
left join publishers p on p.id = b.publisher_id
where p.name = 'Dundurn Press' or p.id is null;

Solution

  • I found that it's possible to use a with block to select books with no publisher as unpublished_books and select books published by 'Dundurn Press' as dundurn_press_books and then select name from the union of the two sets:

    with
    unpublished_books := (select Book filter not exists .publisher),
    dundurn_press_books := (select Book filter .publisher.name = 'Dundurn Press'),
    select (unpublished_books union dundurn_press_books) { name };