Android 在SQLite FTS中,确切的短语优先于任何其他内容?

Android 在SQLite FTS中,确切的短语优先于任何其他内容?,android,sql,sqlite,fts4,Android,Sql,Sqlite,Fts4,假设搜索输入为“what is”。这将匹配“无论是什么”和“是什么”这两个确切的短语。现在,如何在排序中首先生成准确的短语 从昨天开始我就一直在思考这个问题,我不断地提出不同的解决方案,但每种解决方案都有自己的缺陷 下面是我失败的方法(假设输入='what is'): 这一点的问题是,这两种选择并不相互排斥 所以会有重复的 我不能使用UNION,因为它们在秩列和代码段函数上不同(第一个将有START | what is | END,另一个将有START | what | ENDSTART |

假设搜索输入为“what is”。这将匹配“无论是什么”和“是什么”这两个确切的短语。现在,如何在排序中首先生成准确的短语

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

下面是我失败的方法(假设输入='what is'):

  • 这一点的问题是,这两种选择并不相互排斥 所以会有重复的
  • 我不能使用UNION,因为它们在秩列和代码段函数上不同(第一个将有START | what is | END,另一个将有START | what | ENDSTART | is | END)
  • 我也不能使用(我的上一个问题),因为MATCH不能按ORDERBY子句工作(因为生成的表/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*' 
我在这里做的是:

  • 在最里面的SELECT中,我正在进行排序
  • 在下一个SELECT中,我将过滤掉重复的代码(这将起作用,因为我还没有使用snippet)
  • 最后,如果rowId在第二个select中,我将选择代码段
  • 正如您所预料的,这里的问题是,订购完全没有了:(

    编辑:


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

    您必须对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*/;
    
    或者,使用更通用的模式获取所有可能的行,并按以下顺序检查更严格的匹配:

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

    问:您使用的是哪个版本的Sqlite全文搜索?FTS4。另外,我使用的是Android。这很有效。谢谢。但我不太明白GROUP BY docid和MIN(rank)是如何以某种方式组合具有不同片段的重复记录的。在Sqlite 3.7.11或更高版本中,片段来自与MIN()匹配的行。
    SELECT snippet(fts)
    FROM fts
    WHERE body MATCH 'what* NEAR/3 is*'
    ORDER BY NOT (body MATCH '"what is"');