You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过FunctionContributor实现MATCH() AGAINST()函数?

实现MySQL风格的MATCH AGAINST自定义SQL函数

我已经能实现ST_Y(?)或ST_DISTANCE_SPHERE(?,?)这类简单SQL函数,示例代码如下:

class StYFunction extends StandardSQLFunction {

    private static final BasicTypeReference<Double> RETURN_TYPE = new BasicTypeReference<Double>("double", double.class, SqlTypes.DOUBLE);

    public StYFunction(String name) {
        super(name, true, RETURN_TYPE);
    }

    @Override
    public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, ReturnableType<?> returnType, SqlAstTranslator<?> translator) {
        if (sqlAstArguments.size() != 1) {
            throw new IllegalArgumentException("Function " + getName() + " requires exactly 1 argument");
        }
        sqlAppender.append("ST_Y(");
        sqlAstArguments.get(0).accept(translator);
        sqlAppender.append(")");
    }
}

但我需要实现MySQL中的MATCH(?) AGAINST(?)函数,它有两种使用场景:

  • 简单场景:MATCH(?,?)
  • 带匹配模式的场景:
MATCH (title,body) AGAINST ('database' IN NATURAL LANGUAGE MODE);

或者

MATCH (title,body) AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);

实现思路

MATCH AGAINST的结构和普通函数不同,它是MATCH(列列表) AGAINST(搜索字符串 [匹配模式])的形式,需要支持2个或3个参数:

  1. 第一个参数是列名列表(支持单个或多个列)
  2. 第二个参数是搜索字符串
  3. 可选第三个参数是匹配模式(如IN NATURAL LANGUAGE MODE)

完整实现代码

class MatchAgainstFunction extends StandardSQLFunction {

    // MATCH AGAINST返回相关性得分,使用Double类型
    private static final BasicTypeReference<Double> RETURN_TYPE = new BasicTypeReference<Double>("double", double.class, SqlTypes.DOUBLE);

    public MatchAgainstFunction(String name) {
        super(name, true, RETURN_TYPE);
    }

    @Override
    public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, ReturnableType<?> returnType, SqlAstTranslator<?> translator) {
        int argCount = sqlAstArguments.size();
        if (argCount < 2 || argCount > 3) {
            throw new IllegalArgumentException("Function " + getName() + " requires 2 or 3 arguments");
        }

        // 拼接MATCH(列列表)部分
        sqlAppender.append("MATCH(");
        sqlAstArguments.get(0).accept(translator);
        sqlAppender.append(") AGAINST(");

        // 拼接搜索字符串
        sqlAstArguments.get(1).accept(translator);

        // 若有第三个参数,拼接匹配模式
        if (argCount == 3) {
            sqlAppender.append(" ");
            sqlAstArguments.get(2).accept(translator);
        }

        sqlAppender.append(")");
    }
}

使用示例

  • 简单场景调用:MATCH_AGAINST([title, body], 'database'),最终生成SQL:MATCH(title,body) AGAINST('database')
  • 带布尔模式的调用:MATCH_AGAINST([title, body], '+MySQL -YourSQL', 'IN BOOLEAN MODE'),最终生成SQL:MATCH(title,body) AGAINST('+MySQL -YourSQL' IN BOOLEAN MODE)

注意事项

  • 确保第一个参数能被正确解析为多列表达式(比如传入逗号分隔的列集合)
  • 匹配模式的字符串需和MySQL原生语法一致,关键字不区分大小写
  • 参数数量校验覆盖了2个或3个参数的合法情况,非法参数数会抛出异常

内容的提问来源于stack exchange,提问作者hurelhuyag

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 11:22:06