我目前正在为我们的网站构建基于SQL Server全文索引的搜索功能,并且需要将用户的输入拆分为一组搜索词。一旦术语被拆分,我就需要将它们重新构建为一个字符串,其中包含将针对CONTAINS()或CONTAINSTABLE()全文查询执行的查询。
例如,如果用户输入
Jon Sidnell
进入我们的搜索框,我希望能够将该字符串转换为以下内容:
'("jon*" OR FORMSOF(THESAURUS, jon) OR FORMSOF(INFLECTIONAL, jon)) OR
("sidnell*" OR FORMSOF(THESAURUS, sidnell) OR FORMSOF(INFLECTIONAL, sidnell))'
显然,如果用户输入中有三个单词,则会出现三组“通配符或同义词或变形”字样。
成为一名T-SQL新手(不是新手,但肯定不是大师!)我不确定最好的方法。我已经google了,虽然我遇到了有助于初始字符串拆分的事情,但我还没有真正了解如何最好地利用拆分表示来构造结果字符串。
有人可以帮忙吗?
答案 0 :(得分:1)
我不知道这是否是解决问题的最有效方法,但我想到的是封装逻辑以将输入字符串拆分为表值函数。
调用函数并将结果存储到表变量中。
迭代表变量并将拆分字符串连接到您将用于搜索的最终字符串。
我没有在这里包含函数的代码(为了简洁起见),但在我的情况下,我的函数接受要拆分的字符串和用于拆分字符串的分隔符,并返回一个具有以下结构的表:{{1 }}
一旦你有了这个功能,你就可以将它包含在以下内容中:
Position INT, Value VARCHAR(8000)
输出应该如下所示:
SET NOCOUNT ON
DECLARE @sampleString VARCHAR(500)
SET @sampleString = 'Jon Sidnell Rocks'
DECLARE @delimiter VARCHAR(20);
SET @delimiter = ' '
DECLARE @SplitResults TABLE (
POSITION INT,
VALUE VARCHAR(8000),
fUsed BIT DEFAULT 0)
INSERT INTO @SplitResults ( POSITION, VALUE )
SELECT * FROM dbo.ufn_SplitString(@sampleString, @delimiter)
--Set up a simple loop instead of having to open up a cursor
DECLARE @Value VARCHAR(8000);
DECLARE @Position INT;
SELECT @Value = q.VALUE, @Position = q.Position
FROM (SELECT TOP 1 VALUE, Position FROM @SplitResults WHERE fUsed = 0)q
DECLARE @SearchString VARCHAR(8000)
WHILE @@ROWCOUNT <> 0 AND @Value IS NOT NULL
BEGIN
IF @Position = 1
BEGIN
SET @SearchString = '("' + @Value + '*" OR FORMSOF(THESAURUS, '+ @Value +') OR FORMSOF(INFLECTIONAL, ' + @Value + '))'
END
ELSE
BEGIN
SET @SearchString = @SearchString + ' OR ("' + @Value + '*" OR FORMSOF(THESAURUS, '+ @Value +') OR FORMSOF(INFLECTIONAL, ' + @Value + '))'
END
--Update record so we know we used it
UPDATE @SplitResults SET fUsed = 1
WHERE Position = @Position AND VALUE = @Value
--Get Next Value to Work With
SELECT @Value = q.VALUE, @Position = q.Position
FROM (SELECT TOP 1 VALUE, Position FROM @SplitResults WHERE fUsed = 0)q
END
PRINT @SearchString;
SET NOCOUNT OFF;
答案 1 :(得分:1)
如果您使用SQLCLR用户定义函数来拆分字符串,那么有相当不错的字符串操作方法。您可以使用以下字符串并为每个搜索词应用String.Format方法。它应该足够快,除非有非常高的音量,甚至可能。
“(\”{0} * \“或FORMSOF(THESAURUS,{0})或FORMSOF(INFLECTIONAL,{0}))”
public static SqlString convertStringToFTS(SqlString input)
{
string[] strings = input.ToString().Split(new string[] {" "}, StringSplitOptions.RemoveEmptyEntries);
StringBuilder sb = new StringBuilder();
foreach (string s in strings)
{
if (sb.Length > 0)
{
sb.Append(" OR ");
}
else
{
sb.Append ("(");
}
sb.Append(string.Format("(\"{0}*\" OR FORMSOF(THESAURUS, {0}) OR FORMSOF(INFLECTIONAL, {0}))", s));
}
sb.Append(")");
return sb.ToString();
}
我会说可能有更有效的方法来实现这一目标。
祝你好运。我希望这会有所帮助。