Cómo analizar correctamente las comillas en las consultas de búsqueda de texto completo


Resumen


La búsqueda de texto completo de SQL Server 7,0 o posterior (FTS) proporciona un amplio conjunto de funciones de búsqueda. Puede usar una cláusula Contains para realizar diversas búsquedas, como:
  • Una palabra o frase.
  • El prefijo de una palabra o frase.
  • Una palabra que está cerca de otra palabra.
  • Una palabra que se genera de forma inflexión desde otra. Por ejemplo, la palabra "Drive" es el tallo inflexión de: drives, condujo, conduciendo y gobernado.
  • Una palabra que tiene una ponderación superior designada que otra palabra.
La sintaxis de Contains requiere comillas dobles para prefijo ("Choc *") y para varias búsquedas de palabras o frases ("el chip de chocolate" o "Oatmeal"). Esto puede ser problemático en términos de diseño de la interfaz de usuario, porque los usuarios no están acostumbrados a tener las comillas correctamente y son propensos a cometer errores cuando lo hacen. Se necesita una función sencilla que los desarrolladores puedan usar para citar correctamente una cadena de consulta antes de transferirla a SQL Server.

Más información


A continuación se repasan los conceptos básicos de la sintaxis de las consultas de texto completo con la palabra clave Contains en la cláusula WHERE (para obtener una sintaxis más completa, consulte los libros en línea de SQL Server 7,0):
  • Término simple:
    WHERE CONTAINS(QuantityPerUnit, 'bottles')
  • Frase en término simple:
    WHERE CONTAINS(ProductName, ' "Sasquatch ale" OR "steeleye stout" ')
  • Término de prefijo:
    WHERE CONTAINS(ProductName, ' "choc*" ')
  • O con prefijo de término:
    WHERE CONTAINS(Description, '"sea*" OR "bread*"')
  • Término de proximidad:
    WHERE CONTAINS(ProductName, 'spread NEAR Boysenberry')
  • Término de generación:
    WHERE CONTAINS(ProductName, ' FORMSOF (INFLECTIONAL, dry) ')
  • Duración ponderada:
    WHERE CONTAINS(Description, 'ISABOUT (spread weight (.8), 1)
Observe que los términos de proximidad, generación y ponderados no usan comillas dobles. Además, tenga en cuenta que:
  • Las palabras y frases individuales pueden ir entre comillas dobles (excepto en proximidad, generación y términos ponderados).
  • Las búsquedas de términos de prefijo deben ir entre comillas dobles.
  • Varias búsquedas de términos y frases deben tener cada palabra o frase entre comillas dobles.
Teniendo en cuenta las reglas anteriores simplificadas, puede crear un analizador simple usando expresiones regulares para colocar correctamente las comillas en las cadenas de búsqueda. El algoritmo que debe usarse es el siguiente:
Replace all double quotes (clears the text and any improper quotations)   If the text string contains one of the key words "NEAR", "FORMSOF", or    "ISABOUT", the parsing is complete   Else      Surround any instances of 'and' or 'and not' with quotes      Surround any instances of 'or' or 'or not' with quotes      Surround the entire string with quotes
La siguiente es una versión de JavaScript:
function fxnParseIt() {// Note: sInputString code for demo purposes only, and should be//   replaced with user's code for getting in string value.var sInputString = 'asp and database';sText = sInputString;sText = sText.replace(/"/g,"");if (sText.search(/(formsof|near|isabout)/i) == -1) {sText = sText.replace(/ (and not|and) /gi,'" $1 "');sText = sText.replace(/ (or not|or) /gi,'" $1 "');sText = '"' + sText + '"';}sInputString = sText;}
A continuación se encuentra una versión de VBScript:
Sub ParseIt()      '// Note: sInputString code for demo purposes only, and should be      '/replaced with user's code for getting in string value.      '// Note: this code could also be easily re-written as a function,      '/        and is written as a sub for demo purposes only.      Dim strIn, RegEx, sInput      sInputString = "asp and database"      strIn = sInput      Set RegEx = New RegExp      If Len(strIn) < 1 Then            MsgBox ("You must enter a search string")      Else            strIn = Replace(strIn, Chr(34), "")            If (InStr(strIn, "formsof") > 0) Or (InStr(strIn, "near") > 0) Or (InStr(strIn, "isabout") > 0) Then                  ParseMe.value = strIn            Else                  RegEx.IgnoreCase = True                  RegEx.Global = True                  RegEx.Pattern = "( and not | and )"                  strIn = RegEx.Replace(strIn, Chr(34) & "$1" & Chr(34))                  RegEx.Pattern = "( or not | or )"                  strIn = RegEx.Replace(strIn, Chr(34) & "$1" & Chr(34))                  strIn = Chr(34) & strIn & Chr(34)                  ParseMe.value = strIn            End If      End IfEnd Sub