我有一个数据库,其中的字段可以包含长词组。我希望能够在这些列中快速搜索关键字或短语,但是当搜索短语时,我希望能够像Google一样搜索短语,返回包含所有指定单词的所有行,但没有特别说明秩序或彼此“接近”。此时,无需按相关性对结果进行排名。
在阅读了有关SQL Server的全文本搜索后,我认为这正是我所需要的:一个基于文本的列中每个单词的可搜索索引。我的最终目标是安全地接受用户输入,并将其转换为利用全文搜索速度的查询,同时保持用户的易用性。
我看到该FREETEXT函数可以使用整个短语,将其分解为“有用的”单词(忽略诸如“ and”,“ or”,“ the”等之类的单词),然后非常快速地返回匹配行的列表,即使使用一个复杂的搜索词。但是,当您尝试使用它时,您可能会注意到AND,它似乎只在进行OR搜索,而不是对每个术语进行搜索。也许有一种方法可以更改其行为,但是我还没有发现任何有用的方法。
FREETEXT
AND
OR
然后是CONTAINS,可以接受布尔查询短语,但有时结果很奇怪。
CONTAINS
查看此表上的以下查询:
PKID Name ----- ----- 1 James Kirk 2 James Cameron 3 Kirk Cameron 4 Kirk For Cameron
Q1: SELECT Name FROM tblName WHERE FREETEXT(Name, 'james') Q2: SELECT Name FROM tblName WHERE FREETEXT(Name, 'james kirk') Q3: SELECT Name FROM tblName WHERE FREETEXT(Name, 'kirk for cameron') Q4: SELECT Name FROM tblName WHERE CONTAINS(Name, 'james') Q5: SELECT Name FROM tblName WHERE CONTAINS(Name, '"james kirk"') Q6: SELECT Name FROM tblName WHERE CONTAINS(Name, '"kirk james"') Q7: SELECT Name FROM tblName WHERE CONTAINS(Name, 'james AND kirk') Q8: SELECT Name FROM tblName WHERE CONTAINS(Name, 'kirk AND for AND cameron')
SELECT Name FROM tblName WHERE FREETEXT(Name, 'james')
返回“ James Kirk”和“ James Cameron”。好吧,让它缩小范围…
SELECT Name FROM tblName WHERE FREETEXT(Name, 'james kirk')
你猜怎么了。现在,您将获得“ James Kirk”,“ James Cameron”和“ Kirk For Cameron”。 Query 3 也会发生同样的事情,所以我们就跳过它。
SELECT Name FROM tblName WHERE CONTAINS(Name, 'james')
与查询1相同的结果。好的。缩小结果也许…?
SELECT Name FROM tblName WHERE CONTAINS(Name, '"james kirk"')
发现有空格后,需要将字符串括在双引号中后,我发现此查询在该特定数据集上可以很好地满足我想要的结果!仅返回“ James Kirk”。精彩的!还是…
SELECT Name FROM tblName WHERE CONTAINS(Name, '"kirk james"')
废话 否。它与该词组完全匹配。嗯…在检查了T-SQL的CONTAINS函数的语法之后,我发现您可以在其中添加布尔关键字,而这似乎可能就是答案。让我们来看看…
SELECT Name FROM tblName WHERE CONTAINS(Name, 'james AND kirk')
整洁的。我得到了所有三个结果,正如预期的那样。现在,我只编写了一个AND在所有单词之间填充单词的函数。完成了吧?现在怎么办…
SELECT Name FROM tblName WHERE CONTAINS(Name, 'kirk AND for AND cameron')
该查询完全知道它要查找的内容,除了某些原因外,没有结果。为什么?在阅读完有关停用词和停用列表的内容之后,我会做出有根据的猜测,因为我要索取索引值的交叉点为“弯折”,“ for”和“ cameron”,而“ for”一词将没有任何结果(将其作为停用词以及所有结果),则与该结果相交的任何结果也为空。它实际上是否像那样起作用对我来说无关紧要,因为这是CONTAINS每次我在其中使用停用词进行布尔搜索时该函数的可观察行为。
所以我需要一个新的解决方案。
NEAR
看起来很有前途。如果我可以接受用户查询并在逗号之间插入逗号,这将…等待,这与AND在CONTAINS查询中使用布尔值相同。但是它是否正确忽略停用词?
SELECT Name FROM tblName WHERE CONTAINS(Name, 'NEAR(kirk, for, cameron)')
没有。没结果。删除单词“ for”,您将再次获得所有三个结果。:(
我正在将ISAbout与THESAURUS,INFLECTIONAL和通配符结合使用 优点是 1-搜索字符串中的单词顺序无关紧要 2-搜索相似的单词(THESAURUS) 3-将运行,运行,运行,运行视为相同(INFLECTIONAL) 4-如果搜索字符串中只有一个元素不在结果字符串中,Near不会返回结果,但是ISAbout将始终返回最理想的结果 5-您可以设置不同单词的权重,这将进一步帮助您优化结果的正确性
SELECT K.RANK, name, Description FROM Diagnosis AS C INNER JOIN CONTAINSTABLE(diagnosis,name,<br> 'isAbout(FORMSOF (THESAURUS, "CHRONIC") weight(1.0),FORMSOF (INFLECTIONAL, "CHRONIC") weight(1.0),CHRONIC* weight(1.0) FORMSOF (THESAURUS, "FAILURE") weight(1.0),FORMSOF (INFLECTIONAL, "FAILURE") weight(1.0),FAILURE* weight(1.0), FORMSOF (THESAURUS, "DIASTOLIC") weight(1.0),FORMSOF (INFLECTIONAL, "DIASTOLIC") weight(1.0),DIASTOLIC* weight(1.0))') AS K ON C.ID = K.[KEY];
我仍在寻找优化方法。 注意:我会以编程方式从搜索字符串中删除停用词。