EdgeQL如何查询空链接或指定链接匹配的结果
EdgeDB 空关联+属性匹配组合查询异常修复
问题复现
初始Schema定义
module default { type Publisher { required property name -> str; } type Book { required property name -> str; link publisher -> Publisher; } }
测试数据插入语句
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' };
初始查询与执行结果
执行以下三条查询:
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;
实际表现:
- 第一条查询符合预期,返回无出版社关联的《My Unpublished Book》
- 第二条查询符合预期,返回Dundurn Press出版的《Lost Shadow》
- 第三条查询预期同时返回上述两本图书(匹配所有无publisher关联的图书、关联出版社为Dundurn Press的图书),但实际返回结果不符合预期
该需求对应SQL的左连接实现逻辑如下:
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;
问题原因
EdgeDB中直接通过.link.property语法访问关联对象属性时,默认采用内连接语义:所有关联link为空的记录,会在计算.publisher.name表达式的阶段就被过滤掉,根本不会进入后续or not exists .publisher的条件判断流程,因此无出版社的图书会被意外排除。
正确写法
将关联属性的匹配逻辑包裹在exists判断中,避免提前触发内连接过滤,语句如下:
select Book { name } filter exists (.publisher filter .name = 'Dundurn Press') or not exists .publisher;
也可以使用空安全相等运算符?=实现,该运算符在关联link为空时不会触发内连接过滤,会返回空值参与逻辑判断:
select Book { name } filter .publisher ?= assert_single((select Publisher filter .name = 'Dundurn Press')) or not exists .publisher;
两种写法执行后都会正确返回《Lost Shadow》和《My Unpublished Book》两本图书,符合预期。
内容的提问来源于stack exchange,提问作者user4704976
相关产品推荐
相关产品推荐

