【问题标题】:how to make a fixed-number-of-words-search dynamic in Coldfusion/MySql?如何在 Coldfusion/MySql 中动态进行固定数量的词搜索?
【发布时间】:2012-05-20 19:50:22
【问题描述】:

我正在尝试升级 Coldfusion8/MySQL 站点。该网站有一个复杂的搜索,(在其他标准中)获取文本字符串并在关键字表中搜索这些。

我不想进行 FULLTEXT 搜索,因为完整的查询有很多额外的条件。我正在寻找的是使以下内容更加“动态”,而不是将自己限制在 xy 单词中,从而可能会缩短一点(完整搜索有很多这样的块)。

所以,假设我有一个类似的搜索字符串

I'm looking for something

我目前正在这样做:

<!--- params --->
<cfparam name="s01" default="">
<cfparam name="s02" default="">
<cfparam name="s03" default="">    
<cfparam name="s04" default="">
<cfparam name="s05" default="">

<!--- get length of search string --->
<cfset howManyWords = ListLen(textSearch," ")>

<!--- assign words to params --->
<cfif howManyWords gt 0><cfset s01 = trim(ListGetAt(textSearch, 1," "))></cfif>
<cfif howManyWords gt 1><cfset s02 = trim(ListGetAt(textSearch, 2," "))></cfif>
<cfif howManyWords gt 2><cfset s03 = trim(ListGetAt(textSearch, 3," "))></cfif>
<cfif howManyWords gt 3><cfset s04 = trim(ListGetAt(textSearch, 4," "))></cfif>
<cfif howManyWords gt 4><cfset s05 = trim(ListGetAt(textSearch, 5," "))></cfif>

在我的搜索查询中,我将搜索字符串与三个数据库字段进行匹配:

...
<cfif textSearch neq "">
    <cfif s01 neq "">AND (a.textSearch LIKE "%#s01#%" OR a.textSearch_xl LIKE "%#s01#%" OR a.ean = "#s01#")</cfif>
    <cfif s02 neq "">AND (a.textSearch LIKE "%#s02#%" OR a.textSearch_xl LIKE "%#s02#%" OR a.ean = "#s02#")</cfif>
    <cfif s03 neq "">AND (a.textSearch LIKE "%#s03#%" OR a.textSearch_xl LIKE "%#s03#%" OR a.ean = "#s03#")</cfif>
    <cfif s04 neq "">AND (a.textSearch LIKE "%#s04#%" OR a.textSearch_xl LIKE "%#s04#%" OR a.ean = "#s04#")</cfif>
    <cfif s05 neq "">AND (a.textSearch LIKE "%#s05#%" OR a.textSearch_xl LIKE "%#s05#%" OR a.ean = "#s05#")</cfif>
</cfif>
...

问题:
有没有办法让这更加动态,例如使用循环,所以我不会被 5 个单词困住?在这种情况下,我将如何预设 param 值?

感谢您的帮助!

【问题讨论】:

  • 你考虑过使用 Lucene/Solr 吗?我自己没有做过,但相当肯定它们可以连接到 MySQL 数据库,并会为你处理所有这些单词。
  • 谢谢。我会检查一下!

标签: mysql string search coldfusion parameters


【解决方案1】:

您可以通过在查询中将搜索词作为列表循环来扩展搜索词,您还应该使用查询参数来防止 SQL 注入攻击。

<cfloop list="#textSearch#" index="word" delimiters=" ">
  AND (
    a.textSearch LIKE <cfqueryparam cfsqltype="cfsql_varchar" value="%#word#%"> 
    OR a.textSearch_xl LIKE <cfqueryparam cfsqltype="cfsql_varchar" value="%#word#%">  
    OR a.ean = <cfqueryparam cfsqltype="cfsql_varchar" value="#word#"> 
  )
</cfloop>

【讨论】:

  • 是的。这也是我的想法。无需预先声明所有参数。至于 SQLinjection/query params.... 我有大量的字段要更新:-)。还没有在这个页面上做。仍然想知道为什么最初的开发人员没有这样做。
  • 我很确定 CFBuilder 有一个 CF 扩展,它会为您突出显示所有没有参数的查询。
  • 不仅仅是 CFBuilder,qpscanner 是一个独立的应用程序,还有一个(通用)Eclipse 插件。实际上,CFB extension 看起来仍在使用相当老的 v0.7.0 - the latest 0.7.5 version 有几个错误修复和速度改进。
【解决方案2】:

您可以使用交替构建一个简单的正则表达式,然后使用 MySQL 的 REGEXP 运算符。你会在 SQL 中想要这样的东西:

and (a.textSearch regexp 'a|b|c|...' or a.textSearch_xl regexp 'a|b|c|...' or a.ean regexp 'a|b|c|...')

a, b, c, ... 是您要搜索的内容。虽然我不知道 ColdFushion 方面的事情,但构建正则表达式应该相当简单。

【讨论】:

  • 你想用这种方法转义字符串中可能的正则表达式特殊字符,否则你可能会得到一些奇怪的结果,例如A+可能匹配'A'或'AAAAA'
  • @PhilParsons:我认为这很明显。由于%_ 具有特殊含义,因此您也必须使用 LIKE 来逃避事物。
  • @muistooshort - 我也会考虑一下。虽然...正则表达式不是我的强项...
  • 我不认为正则表达式在这种情况下是正确的工具,但是(供参考)如果你确实想尝试它,你会想要像 &lt;cfset EscapedText = OrigText.replaceAll('[$^*()+\[\]{}.?\\|]','\\$0').replaceAll('\s+','|') /&gt; 这样的东西首先转义相关的元字符和然后用管道替换所有空格。 (假设 OrigText 已经被修剪,如果没有,则需要这样做。)
猜你喜欢
  • 2012-04-20
  • 1970-01-01
  • 2017-07-10
  • 2016-01-06
  • 2011-02-07
  • 1970-01-01
  • 2020-04-14
  • 1970-01-01
  • 2015-05-22
相关资源
最近更新 更多