【问题标题】:SQL Server full-text search for Latex contentSQL Server 全文搜索 Latex 内容
【发布时间】:2017-10-19 06:07:55
【问题描述】:

我有一个网络应用程序,允许用户将 Latex 内容保存到 SQL Server 2012 数据库。我正在运行如下全文查询来搜索 Latex 表达式。

SELECT MessageID, Message FROM Messages m  WHERE CONTAINS (m.Message, N'2x-4=0');

我在上面的查询中面临的问题是上面查询返回的一些消息不包含乳胶表达式2x-4=0。例如,上面的查询也返回了一条保存值如下的消息。您可以清楚地看到该消息中没有包含 2x-4=0。

<p>Another example of inline Latex is \$x=34\$.</p>
<p>What are the roots of following equation: \$x^2 - 2x + 1 = 0\$?</p>

问题

为什么会发生这种情况?在进行全文搜索以查找乳胶表达式2x-4 = 0 时,有没有办法返回正确的记录?我已尝试重新填充正在使用的表的全文搜索数据,但没有效果。

更新 1

奇怪,但是下面的 Latex 表达式过滤器总是返回完全匹配的结果。我现在正在寻找$2x-4=0$ 而不是2x-4=0

SELECT MessageID, Message FROM Messages m  WHERE CONTAINS (m.Message, N'$2x-4=0$');

我的应用程序中有两种类型的乳胶表达式分隔符:$$ 用于段落显示和\$ 用于乳胶表达式的内联显示,因此数据库中存储的乳胶表达式周围总会有一个 $ 符号,虽然尾随分隔符可能是\$,但全文搜索似乎忽略了反斜杠字符。

我不清楚为什么这个修改后的查询返回完全匹配。

更新 2

答案中提到了另一种有效的方法。下面提到了对此的完整查询。因此,LIKE 运算符最终只扫描由全文搜索查询选择的那些行。

WITH x AS
  (SELECT MessageID,
          Message
   FROM Messages m
   WHERE CONTAINS (m.Message,
                   N'2x-4=0') )
SELECT MessageID,
       Message
FROM x
WHERE x.Message LIKE "%2x-4=0%"

【问题讨论】:

    标签: sql sql-server sql-server-2012 full-text-search latex


    【解决方案1】:

    要了解它发生的原因,您可以运行以下查询(1033 是英语语言 ID):

    select * from sys.dm_fts_parser('2x-4=0', 1033, 0,1)
    

    在我的例子中,它会返回以下结果:

    注意,除了2x,搜索条件的所有其他部分都被视为干扰词。因此,我怀疑您的全文索引根本没有完整的2x-4=0 字符串,而是您得到2x 出现的结果。

    我尝试将2x-4=0 添加到我自己的 FTS 索引中,CONTAINS 能够将其作为CONTAINS(col, '2x-4=0')CONTAINS(col, '"2x-4=0"') 的最佳结果。但是,部分匹配也包含在完全匹配之后。

    请注意,当在搜索词中的 = 周围添加额外的空格时,FTS 解析器将不会接受它并抱怨语法错误。

    【讨论】:

    • “并且CONTAINS 能够找到它”:问题在于CONTAINS 发现太多,而不是太少。
    • @Thomas 我想强调的是,在搜索词周围添加 " 不会切断不匹配的结果。相反,它会在顶部列出完全匹配,在下面列出其他部分匹配。
    • @andrews,感谢您的回答。通常我的应用程序的用户会经常保存 Latex 内容,在这种情况下,是否可以强制执行您在完整的 Latex 表达式中提到的 FTS 索引?
    • @Sunil,Latex 表达式包含很多格式字符。 SQLServer FTS 可能无法将这些表达式正确理解为一个术语。您可以检查select * from sys.fulltext_system_stopwords where language_id=1033 以查看系统中还定义了哪些其他停用词,并查看是否有太多 Latex 控制字符。老实说,我喜欢 Thomas 提出的解决方案,尝试使用 CONTAINS 缩小搜索结果,然后从初始 FTS 搜索结果中获得与 LIKE 完全匹配的结果。
    • @Sunil,我认为这是错误的方式。尝试使用 CONTAINS 和进一步的 LIKE 专注于 CTE。在您的原始查询中,您是否得到至少一个与 2x-4=0 完全匹配的结果?
    【解决方案2】:

    CONTAINS 更像是最终用户搜索操作,支持NEARANDOR 等关键字。尝试在引号中添加引号,以强制使用确切的搜索词:

    SELECT MessageID, Message FROM Messages m WHERE CONTAINS (m.Message, N'"2x-4=0"');
    

    这在documentation 中称为&lt;simple-term&gt;

    你也可以试试LIKE operator:

    SELECT MessageID, Message FROM Messages m WHERE m.Message LIKE '%2x-4=0%';
    

    但请注意,这可能比CONTAINS 慢,因为它不使用全文搜索索引。如果速度太慢,也许你甚至可以将两者结合在一个查询中,所以CONTAINS 用于使用索引将结果集过滤为非噪声词,然后LIKE 应用最终匹配。

    【讨论】:

    • 我用这个查询尝试过,但仍然得到相同的结果。 SELECT MessageID,Message FROM Messages m WHERE CONTAINS(m.Message, N'"2x-4=0"')
    • 那么,您是在建议使用全文搜索查询的 CTE,然后使用 LIKE 运算符添加另一个对该 CTE 起作用的查询?
    猜你喜欢
    • 2010-09-06
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多