春季 JDBC 准备的语句与布尔全文搜索格式问题

huangapple go评论78阅读模式
英文:

spring jdbc prepared statement with boolean fulltext search formatting issues

问题

我有一个使用布尔全文搜索的SQL查询

    SELECT
        *,
        MATCH (job_title) AGAINST ('"product manager"' in boolean mode) AS title_relevance_exact,
        MATCH (job_description) AGAINST ('"product manager"' in boolean mode) AS description_relevance_exact,
        MATCH (job_title) AGAINST ('product manager' in boolean mode) AS title_relevance_part,
        MATCH (job_description) AGAINST ('product manager' in boolean mode) AS description_relevance_part
    FROM
        jobs
    WHERE
        MATCH(job_title, job_description) AGAINST ('product manager') AND
        date_posted >= now() - INTERVAL 30 DAY
    ORDER BY
        job_title LIKE 'product manager' DESC,
        title_relevance_exact DESC,
        description_relevance_exact DESC,
        title_relevance_part DESC,
        description_relevance_part DESC
    LIMIT 300;

即在`'"product manager"'`中的引号是查询中的重要部分。

当我将此查询作为Spring JDBC预准备语句运行时,我必须进行一些处理,以便正确格式化字符串,因为如果我使用`'?'`JDBC不会将其识别为参数

    String queryPrepared =
                    "SELECT\n" +
                    "   *,\n" +
                    "   MATCH (job_title) AGAINST (? in boolean mode) AS title_relevance_exact,\n" +
                    "   MATCH (job_description) AGAINST (? in boolean mode) AS description_relevance_exact,\n" +
                    "   MATCH (job_title) AGAINST (? in boolean mode) AS title_relevance_part,\n" +
                    "   MATCH (job_description) AGAINST (? in boolean mode) AS description_relevance_part\n" +
                    "FROM\n" +
                    "   jobs\n" +
                    "WHERE\n" +
                    "   MATCH(job_title, job_description) AGAINST (?) AND\n" +
                    "   date_posted >= now() - INTERVAL 30 DAY\n" +
                    "ORDER BY\n" +
                    "   job_title LIKE ? DESC,\n" +
                    "   title_relevance_exact DESC,\n" +
                    "   description_relevance_exact DESC,\n" +
                    "   title_relevance_part DESC,\n" +
                    "   description_relevance_part DESC\n" +
                    "LIMIT 500;";
    String param1 = String.format("'%1$s'", searchValue);
    String param2 = String.format("'%1$s'", searchValue);

    List<Map<String, Object>> resultPrepared = jdbcTemplate.queryForList(queryPrepared,
            new Object[] {param1, param1, param2, param2, param2, param2});

以上是您提供的内容的翻译部分。如果您需要更多的帮助或有其他问题,请随时问我。

英文:

I have an sql query that uses boolean fulltext search:

SELECT
*,
MATCH (job_title) AGAINST (&#39;&quot;product manager&quot;&#39; in boolean mode) AS title_relevance_exact,
MATCH (job_description) AGAINST (&#39;&quot;product manager&quot;&#39; in boolean mode) AS description_relevance_exact,
MATCH (job_title) AGAINST (&#39;product manager&#39; in boolean mode) AS title_relevance_part,
MATCH (job_description) AGAINST (&#39;product manager&#39; in boolean mode) AS description_relevance_part
FROM
jobs
WHERE
MATCH(job_title, job_description) AGAINST (&#39;product manager&#39;) AND
date_posted &gt;= now() - INTERVAL 30 DAY
ORDER BY
job_title LIKE &#39;product manager&#39; DESC,
title_relevance_exact DESC,
description_relevance_exact DESC,
title_relevance_part DESC,
description_relevance_part DESC
LIMIT 300;

i.e. the quotation and speech marks in &#39;&quot;product manager&quot;&#39; is important to the query.

When I run this query as a spring jdbc prepared statement, I have to do some work arounds to get the string formatted correctly since if I have &#39;?&#39;, jdbc doesnt recognise this as a parameter:

String queryPrepared =
&quot;SELECT\n&quot; +
&quot;   *,\n&quot; +
&quot;   MATCH (job_title) AGAINST (? in boolean mode) AS title_relevance_exact,\n&quot; +
&quot;   MATCH (job_description) AGAINST (? in boolean mode) AS description_relevance_exact,\n&quot; +
&quot;   MATCH (job_title) AGAINST (? in boolean mode) AS title_relevance_part,\n&quot; +
&quot;   MATCH (job_description) AGAINST (? in boolean mode) AS description_relevance_part\n&quot; +
&quot;FROM\n&quot; +
&quot;   jobs\n&quot; +
&quot;WHERE\n&quot; +
&quot;   MATCH(job_title, job_description) AGAINST (?) AND\n&quot; +
&quot;   date_posted &gt;= now() - INTERVAL 30 DAY\n&quot; +
&quot;ORDER BY\n&quot; +
&quot;   job_title LIKE ? DESC,\n&quot; +
&quot;   title_relevance_exact DESC,\n&quot; +
&quot;   description_relevance_exact DESC,\n&quot; +
&quot;   title_relevance_part DESC,\n&quot; +
&quot;   description_relevance_part DESC\n&quot; +
&quot;LIMIT 500;&quot;;
String param1 = String.format(&quot;&#39;\&quot;%1$s\&quot;&#39;&quot;, searchValue);
String param2 = String.format(&quot;&#39;%1$s&#39;&quot;, searchValue);
List&lt;Map&lt;String, Object&gt;&gt; resultPrepared = jdbcTemplate.queryForList(queryPrepared,
new Object[] {param1, param1, param2, param2, param2, param2});

But the correct result isnt produced from the query, the results are not in the expected order. I can only assume that this happens because of the formatting in the prepared statement parameters. But I can't see what the query looks like after adding the parameters, how can I debug this?

答案1

得分: 1

你需要从你的值中移除单引号。在SQL中,单引号用于界定查询字符串中的字符串字面量。当你设置参数值时,只需要设置字符串值而无需使用单引号。

因此,如果你想要用参数替换字面量 &#39;&quot;product manager&quot;&#39;,你在查询中使用 ?(因此不使用单引号),并设置值为 &quot;product manager&quot;(同样,不使用单引号)。作为Java字符串字面量,它将是 &quot;\&quot;product manager\&quot;&quot;

在作为参数传递的值中使用单引号,相当于使用SQL字符串字面量 &#39;&#39;&#39;&quot;product manager&quot;&#39;&#39;&#39;

英文:

You need to remove the single quotes from your value. Single quotes in SQL delimit a string literal in the query string. When you set a parameter value, you only need to set the string value without the single quotes.

So, if you want to replace the literal &#39;&quot;product manager&quot;&#39; with a parameter, then you use ? in your query (so, without single quotes), and set the value &quot;product manager&quot; (again, without single quotes), which as a Java string literal is &quot;\&quot;product manager\&quot;&quot;.

Using single quotes in the value passed as a parameter would be the equivalent of using the SQL String literal &#39;&#39;&#39;&quot;product manager&quot;&#39;&#39;&#39;.

huangapple
  • 本文由 发表于 2020年9月10日 18:40:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/63827949.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定