Flutter中Drift的intersect机制及多标签关联查询问题求助
Flutter中Drift的intersect机制及多标签关联查询问题求助
嘿,我来帮你排查这个Drift多标签查询的问题!你现在是想通过交集找出同时带有"Acoustic"和"Melancholy"两个标签的歌曲,但用intersect没成功对吧?我来给你分析下可能的问题,再给你两种靠谱的实现方案。
首先,你用intersect的思路本身是对的,但大概率是子查询的构造或者映射环节出了问题。Drift的intersect要求两个子查询返回的列结构完全一致,而且得正确映射到Song对象才行。给你一个正确的intersect写法示例:
Future<List<Song>> complicatedQuery2([bool benchmark = false]) { // 构造获取带"Acoustic"标签的歌曲的子查询 final acousticSongs = select(songs).join([ innerJoin(songTags, songTags.songId.equalsExp(songs.id)), innerJoin(tags, tags.id.equalsExp(songTags.tagId)), ]) ..where(tags.name.equals("Acoustic")) ..map((row) => row.readTable(songs)); // 确保映射到Song对象 // 构造获取带"Melancholy"标签的歌曲的子查询 final melancholySongs = select(songs).join([ innerJoin(songTags, songTags.songId.equalsExp(songs.id)), innerJoin(tags, tags.id.equalsExp(songTags.tagId)), ]) ..where(tags.name.equals("Melancholy")) ..map((row) => row.readTable(songs)); // 取两个子查询的交集 return (acousticSongs.intersect(melancholySongs)).get(); }
你可以自查下之前的代码是不是没做好这几点:比如子查询有没有用map正确读取Song表的数据,或者join的关联条件是不是写错了——比如是不是把songTags.tagId和tags.id的对应关系搞反了?
另外,我更推荐你用分组计数的方式实现这个需求,这种方式代码更简洁,后续加更多标签时扩展性更好,性能也比多次intersect要高:
Future<List<Song>> complicatedQuery2([bool benchmark = false]) { return select(songs).join([ innerJoin(songTags, songTags.songId.equalsExp(songs.id)), innerJoin(tags, tags.id.equalsExp(songTags.tagId)), ]) // 先筛选出带有目标标签之一的歌曲 ..where(tags.name.isIn(["Acoustic", "Melancholy"])) // 按歌曲ID分组 ..groupBy([songs.id]) // 要求分组后的不同标签数量等于目标标签总数(这里是2) ..having(countDistinct(tags.id).equals(2)) // 映射回Song对象 ..map((row) => row.readTable(songs)) ..get(); }
这个逻辑很清晰:先把所有带两个目标标签的歌曲捞出来,然后按歌曲分组,只有当某首歌关联的不同标签数量刚好是2时,才说明它同时拥有这两个标签,这样就精准筛选出了你要的结果。
如果用这个方式还是有问题,你可以检查下这几个点:
songTags表的songId和tagId是不是正确关联了songs.id和tags.id- 有没有可能同一首歌和同一个标签重复关联?如果有的话,
countDistinct就很有必要;要是不会重复,用count(tags.id)也可以 - 标签名称的大小写是不是匹配?比如数据库里存的是"acoustic"但你查的是"Acoustic",这也会导致查不到结果
备注:内容来源于stack exchange,提问作者K.Horst
相关产品推荐
相关产品推荐

