在SQLite FTS中首先是确切的短语吗?

时间:2016-05-29 23:51:11

标签: android sql sqlite fts4

假设搜索输入是'what is'。这将匹配'无论是什么'以及'什么是'哪个是确切的短语。现在,如何在排序中首先制作精确的短语?

我从昨天开始就一直在考虑这个问题,并且我一直在提出不同的解决方案,但每个解决方案都有自己的缺陷。

这是我失败的方法(假设输入='什么是'):

SELECT snippet(fts), 1 as rank
FROM fts
WHERE body MATCH '"what is"'
UNION ALL
SELECT snippet(fts), 2 as rank
FROM fts
WHERE body MATCH 'what* NEAR/3 is*' -- 3 is arbitrary
ORDER BY rank
  • 这个问题是两个SELECT不是互斥的 所以会有重复。
  • 我不能使用UNION,因为它们在排名栏和片段功能上有所不同(首先是START |什么是| END,其他的将有START | what | ENDSTART |是| END)。
  • 我不能也使用this(我之前的问题)因为MATCH在ORDER BY子句中不起作用(因为结果表/ select不是原始的FTS表)。

这是我目前的解决方案:

SELECT snippet(fts)
FROM fts WHERE rowId IN
(
SELECT DISTINCT rowId
FROM 
( 
SELECT rowId, 1 as rank 
FROM fts
WHERE body MATCH '"what is"'
UNION ALL 
SELECT rowId, 2 as rank  
FROM fts
WHERE body MATCH 'what* NEAR/3 is*'
ORDER BY rank
) 
)
WHERE body MATCH 'what* NEAR/3 is*' 

我在这里做的是:

  1. 在最里面的SELECT中,我正在进行排序
  2. 在下一个SELECT中,我将过滤掉重复项(这样可行,因为我还没有使用代码片段。
  3. 最后,如果rowId在第二个选择中,我正在选择片段。
  4. 这里的问题是,如你所料,订购已经完全消失:(。

    编辑:

    我在Android中使用FTS4(我不使用增强的查询语法,因为我不确定Android是否支持)。

1 个答案:

答案 0 :(得分:1)

您必须在FTS表本身上执行所有FTS处理(包括snippet()),然后才将结果合并到最上面的查询中:

SELECT docid,
       snippet,
       MIN(rank) AS rank
FROM (SELECT docid,
             snippet(fts) AS snippet,
             1 AS rank
      FROM fts
      WHERE body MATCH '"what is"'
      UNION ALL
      SELECT docid,
             snippet(fts),
             2
      FROM fts
      WHERE body MATCH 'what* NEAR/3 is*')
GROUP BY docid
ORDER BY MIN(rank) /*, docid*/;

或者,获取具有更一般模式的所有可能行,并检查ORDER BY中更严格的MATCH:

SELECT snippet(fts)
FROM fts
WHERE body MATCH 'what* NEAR/3 is*'
ORDER BY NOT (body MATCH '"what is"');
相关问题