【问题标题】:FullTextSearch optional words全文搜索可选词
【发布时间】:2017-03-23 17:10:40
【问题描述】:

使用 MS SQL 2016 全文搜索对表进行搜索,用户搜索“quick brown fox”。这不会返回任何结果,因为所有三个单词都不会出现在任何单个记录中。但是“quick brown”会返回结果,“brown fox”和“quick fox”也是如此。

有没有一种方法可以构造输入查询,使单词是可选的(即用户说“quick brown *fox”来表示 fox 是可选的)或查询本身返回没有所有单词的结果?我不介意运行两个查询,第一个查询所有单词,如果第一个查询没有返回任何行,则再次查询不完整的输入。

string query = String.Concat(@"
    SELECT *
    FROM FullTextSearches AS FT_TBL INNER JOIN
    CONTAINSTABLE(FullTextSearches, (Title, Body), @SearchCondition) AS KEY_TBL
    ON FT_TBL.Id = KEY_TBL.[KEY]
    WHERE (FT_TBL.Accessibility = 0) OR ((FT_TBL.Accessibility & @Roles) > 0)
    ORDER BY KEY_TBL.[RANK] DESC
    OFFSET (@Skip) ROWS FETCH NEXT (@Take) ROWS ONLY");

SqlParameter paramSearch = new SqlParameter("SearchCondition", "\"" + searchTerm + "\"");
SqlParameter paramSkip = new SqlParameter("Skip", pageNumber * pageSize);
SqlParameter paramTake = new SqlParameter("Take", pageSize);
SqlParameter paramRoles = new SqlParameter("Roles", accessibility);
object[] parameters = new object[] { paramSearch, paramSkip, paramTake, paramRoles };
var results = db.FullTextSearch.SqlQuery(query, parameters);

一直在学习。

【问题讨论】:

  • 是否总是排除第三个单词?
  • 可以是任何单词。理想情况下,它将返回所有单词的排名高于仅包含部分单词的记录的记录。例如,当未找到所有单词时,Google 会在其搜索结果中声明“缺失:[单词]”。我没有必须拥有它,只是一个 WIBNI。

标签: c# sql sql-server full-text-search


【解决方案1】:

我认为这样的事情应该能让你到达那里。不是多个查询,而是多个联接。

string searchTerm = "quick brown *fox"
string withOptional = searchTerm.Replace("*", "");
string withoutOptional = Regex.Replace(searchTerm, "[*]\w", "");

string[] options = new string[]{ withOptional, withoutOptional }; 

string query = String.Concat(@"
    SELECT *
    FROM FullTextSearches AS FT_TBL ");

int i = 1;
List<SqlParameter> parameters = new List<SqlParameter>();

foreach(string option in options)
{
    parameters.Add(new SqlParameter("SearchCondition" + (i++).ToString(), "\"" + option + "\""))
    query += $@"LEFT JOIN CONTAINSTABLE(FullTextSearches, (Title, Body), @SearchCondition{i - 1}) AS KEY_TBL{i - 1} ON FT_TBL.Id = KEY_TBL{i - 1}.[KEY] ";
}

SqlParameter paramSkip = new SqlParameter("Skip", pageNumber * pageSize);
SqlParameter paramTake = new SqlParameter("Take", pageSize);
SqlParameter paramRoles = new SqlParameter("Roles", accessibility);
object[] parms = new object[parameters.Length + 3];

for (j = 0; j < parameters.Length; j++)
{
    parms[j] = parameters[j];
}

parms[parms.Length - 3] = paramSkip;
parms[parms.Length - 2] = paramTake;
parms[parms.Length - 1] = paramRoles;

var results = db.FullTextSearch.SqlQuery(query, parms);


string query += String.Concat(@"
    WHERE (FT_TBL.Accessibility = 0) OR ((FT_TBL.Accessibility & @Roles) > 0)
    ORDER BY KEY_TBL.[RANK] DESC
    OFFSET (@Skip) ROWS FETCH NEXT (@Take) ROWS ONLY");

【讨论】:

  • 鉴于 MS SQL FTS 非常复杂,我很惊讶没有(知识)更灵活的搜索词。那好吧。谢谢,这绝对比我第一次尝试要好。
  • 可能有。如果您真的想深入了解它(知识就是力量),也许可以尝试在dba.stackexchange.com 上询问一个查询问题。如果有人要了解 FTS 的全部来龙去脉,可能更有可能在那里。我根据如何从 c# 的角度来回答,因为这比 MS SQL 功能更适合我。如果你决定这样做,我很想知道结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-24
  • 1970-01-01
  • 2014-05-10
  • 1970-01-01
  • 2018-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多