2016-05-29 39 views
2

假設搜索輸入是'what is'。這將匹配「不管它是什麼」以及「什麼是」這個確切的短語。現在,我如何在排序中首先製作精確的短語?在SQLite FTS的其他任何東西之前的確切短語?

從昨天起我就一直在想這個問題,我一直在想出不同的解決方案,但每個解決方案都有某種缺陷。

這裏是我失敗的方法,但(假設輸入=「什麼是」):在這一個

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,因爲它們在rank列和snippet函數上有所不同(首先會有START |什麼是END,其他會有START | what | ENDSTART | is | END)。
  • 我不能也使用this(我以前的問題),因爲MATCH不會在ORDER BY子句中工作(因爲生成的表/選擇不是原始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位於第二個 選擇。

這裏的問題是,如您所願,排序完全消失:(

編輯:

我在Android中使用FTS4(我不使用增強的查詢語法,因爲我不知道,Android支持)

+0

問:你所使用的是哪個SQLite的全文檢索的版本? – paulsm4

+0

FTS4。另外,我正在使用Android。 –

回答

1

你要做的所有FTS處理(包括snippet())在FTS表本身,只有事後的結果在最上面的查詢合併:

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"'); 
+0

這工作。謝謝。但我並沒有真正瞭解GROUP BY docid和MIN(rank)如何組合具有不同片段的重複記錄。 –

+0

在SQLite 3.7.11或更高版本中,代碼片段來自與MIN()匹配的行。 –

相關問題