Quill中结合infix与lift进行hstore查询遇列索引错误求助
PostgreSQL HStore字段Quill查询报错及性能优化
问题场景
我用JDBC Postgres驱动搭配Quill开发,需要用PostgreSQL的@>操作符查询HStore字段,写了如下Infix代码:
val q = quote { auditDb.filter(row => infix"${row.rowData} @> 'paper_id=>${lift(paperId)}'".as[Boolean]) }
运行时抛出错误:The column index is out of range: 1, number of columns: 0.
把paperId硬编码后,查询就能正常执行:
auditDb.filter(row => infix"${row.rowData} @> 'paper_id=><some number>'".as[Boolean])
另外,下面这个查询能跑但速度极慢:
auditDb.filter(row => infix"${row.rowData} -> 'paper_id'".as[String] == lift(paperId.toString()))
问题分析与解决
报错原因
你把lift(paperId)放在了单引号包裹的字符串内部,Quill无法识别这个参数占位符,导致生成的SQL里没有正确注入参数,JDBC驱动找不到对应参数位置就抛出了索引越界错误。
正确写法
要把参数从单引号里抽出来,让Quill能正确处理参数绑定:
方式1:字符串拼接构造HStore片段
val q = quote { val hstoreFilter = infix"'paper_id=>' || ${lift(paperId)}".as[String] auditDb.filter(row => infix"${row.rowData} @> $hstoreFilter".as[Boolean]) }
方式2:用PostgreSQL内置函数构造HStore(更安全)
推荐用PostgreSQL的hstore(text, text)函数生成合法的HStore值,避免字符串拼接可能带来的格式问题:
val q = quote { val filterEntry = infix"hstore('paper_id', ${lift(paperId.toString)})".as[your.package.HStoreType] // 替换your.package.HStoreType为项目中对应的HStore类型,比如Quill自带的PostgresHStore auditDb.filter(row => infix"${row.rowData} @> $filterEntry".as[Boolean]) }
慢查询的性能问题解释
->操作符会逐行提取HStore字段中的paper_id值再做等值比较,这种方式无法利用HStore字段上的GIN索引(如果已创建)。而@>操作符是针对HStore的包含查询,能直接命中GIN索引,所以性能差距会非常明显。
内容的提问来源于stack exchange,提问作者Tel
相关产品推荐
相关产品推荐

