2016-05-29 13 views
2

Angenommen, die Sucheingabe lautet 'Was ist'. Dies entspricht "was auch immer es ist" und auch "was ist", was der genaue Ausdruck ist. Nun, wie mache ich den genauen Satz zuerst in der Sortierung?Exakter Ausdruck zuerst vor allem anderen in SQLite FTS?

Ich habe seit gestern darüber nachgedacht und ich komme immer wieder mit anderen Lösungen, aber jeder hat irgendwie seinen eigenen Fehler. obwohl

Hier mein gescheitert Ansatz sind (Eingang angenommen = ‚was‘):

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 
  • Das Problem an diesem ist, dass die beiden SELECTs schließen sich nicht aus so wird es Duplikate.
  • Ich kann UNION nicht verwenden, da sie sich auf Rang Spalte und Snippet-Funktion unterscheiden (zuerst wird START | was ist | END, andere wird START | was | ENDSTART | ist | END).
  • Ich kann this (meine vorherige Frage) auch nicht verwenden, da MATCH in der ORDER BY-Klausel nicht funktioniert (weil die resultierende Tabelle/select nicht die ursprüngliche FTS-Tabelle ist).

Hier ist meine aktuelle Lösung:

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*' 

Was ich hier mache ist:

  1. Im innersten SELECT, ich mache die Sortier
  2. Im nächsten SELECT Ich filtere die Duplikate aus (das würde funktionieren, weil ich noch kein Snippet verwende.
  3. Schließlich wähle ich das Snippet, wenn rowId in der 2nd ist wählen.

Das Problem hier ist, wie Sie es erwarten, ist Ordnung :(komplett verschwunden

EDIT:.

I FTS4 in Android bin mit (ich die erweiterte Abfragesyntax nicht, weil verwenden ich bin mir nicht sicher, ob Android unterstützt die)

+0

Q: Welche Version von SQLite Volltextsuche verwenden Sie? – paulsm4

+0

FTS4. Außerdem verwende ich Android. –

Antwort

1

Sie müssen alles tun, FTS Verarbeitung (einschließlich snippet()) auf der FTS Tabelle selbst, und erst danach das Ergebnis in der obersten Abfrage zu kombinieren.

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*/; 

Alternativ erhalten alle möglichen Zeilen mit dem allgemeineren Muster, und prüfen, ob die strengeren MATCH in der ORDER BY:

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

Das hat funktioniert. Vielen Dank. Aber ich verstehe nicht wirklich, wie GROUP BY Docid und MIN (Rang) irgendwie die doppelten Datensätze kombiniert haben, die verschiedene Schnipsel haben. –

+0

In SQLite 3.7.11 oder höher stammt das Snippet aus der Zeile, die der MIN() entspricht. –