2009-12-10 12 views
9

Vorrei implementare una ricerca a testo completo in un'applicazione iPhone. Ho i dati memorizzati in un database SQLite a cui accedo tramite il framework Core Data. Usare solo predicati e ORing un gruppo di frasi "contiene [cd]" per ogni parola e colonna di ricerca non funziona affatto.Ricerca full text nel Core Data Framework di Apple

Che cosa hai fatto che sembra funzionare bene?

+1

Questo è molto vicino alla tua domanda precedente: http://stackoverflow.com/questions/1862771/sqlite-indexing-performance-advice –

+2

Sì, ma stavo ottenendo risposte meno legate ai dati principali e più correlate a sqlite . Ho deciso di fare un altro che è più specifico per i dati di base. – getWeberForStackExchange

risposta

9

Abbiamo FTS3 che funziona molto bene su oltre 150.000 record. Stiamo ottenendo secondarie volte la query restituendo oltre 200 risultati su una singola query di parole chiave.

Attualmente l'unico modo per far funzionare Sqlite FTS3 su iPhone è compilare il proprio file binario e collegarlo al progetto. Per quanto ne so, il file binario incluso nel tuo progetto non funzionerà con Core Data. Forse Apple accenderà l'opzione del compilatore FTS3 in una versione futura?

È ancora possibile collegare il proprio binario Sqlite FTS3 e utilizzarlo solo per ricerche di testo completo. Questo sarebbe molto simile al modo in cui Sphinx o Lucene sono usati negli ambienti delle app Web. Nota che dovrai ancora aggiornare l'indice di ricerca a un certo punto per mantenere la sincronicità con gli archivi di Core Data.

Buona fortuna !!

+1

Grazie crunchyt, spero che abilitino questa opzione. – getWeberForStackExchange

0

Io uso contains[cd] nel mio predicato e questo funziona correttamente. Forse potresti pubblicare il tuo predicato e potremmo vedere se c'è un errore evidente.

+0

Scusa volevo dire che non funziona bene, come per le prestazioni. Pubblicherò il predicato quando torno a casa dal lavoro. Grazie! – getWeberForStackExchange

1

Suppongo che per "non funzioni bene" intendi "recita male". La ricerca full-text è sempre relativamente lenta, soprattutto in ambienti con memoria o spazi ristretti. Potresti essere in grado di velocizzare le cose assicurandoti che gli attributi a cui stai cercando siano indicizzati e utilizzando BEGINSWITH[cd] anziché CONTAINS[cd]. Il mio ricordo (non riesco a trovare il post di cocoa-dev in questo momento) è che SQLite userà l'indice per la corrispondenza del prefisso, ma tornerà alla ricerca lineare per le ricerche infisso.

+0

Ok questo ha senso. Ci provo. – getWeberForStackExchange

+2

Barry Wark sez "La ricerca full-text è sempre relativamente lenta" Questo non è corretto, forse a causa di incomprensioni su cos'è una ricerca a testo integrale? Le ricerche di sottostringa che si traducono in un'istruzione SQL LIKE sono lente perché ogni riga deve essere sottoposta a scansione. Solitamente questa non è indicata come "ricerca a tutto testo" Una ricerca di testo completo (ovvero l'utilizzo di un indice di testo completo) è spesso veloce, decisamente più veloce delle istruzioni SQL LIKE. Metterò più dettagli in una risposta qui sotto. :) – pchap10k

0

Sqlite ha il proprio modulo di testo completo indicizzazione: http://sqlite.org/fts3.html

Bisogna avere il pieno controllo della SQL si invia al db (non so come funziona Core Data), ma utilizzando l'indicizzazione testo completo Il modulo è la chiave per velocizzare l'esecuzione e la semplicità nelle istruzioni SQL SELECT che eseguono la ricerca full-text.

L'utilizzo di CONTAINS va bene se non è necessaria l'esecuzione rapida, ma le selezioni effettuate con esso non possono fare uso di indici regolari, quindi sono destinati ad essere lenti e quanto più grande è il database tanto più lento sarà. L'utilizzo dell'indicizzazione full text reale consente lo stesso tipo di ricerche che puoi fare con 'CONTAINS', ma le cose sono indicizzate per risultati veloci anche con db di grandi dimensioni.

0

Ho lavorato su questo stesso problema e sono appena riuscito a seguire su my post about this from a few weeks ago. Invece di usare CONTAINS, ho creato un'entità separata con un'istanza per ogni parola canonizzata. Ho aggiunto un indice sulle parole (nel builder del modello XCode) e posso quindi utilizzare un operatore BEGINSWITH per sfruttare l'indice. Tuttavia, poiché I just posted a few minutes ago, il tempo di interrogazione è ancora molto lento anche per insiemi di dati di piccole dimensioni.

Ci deve essere un modo migliore! Dopotutto, vediamo questa sorta di ricerca a testo integrale in molte app!

+0

Questa sembra la strada da percorrere. Ci provo. – getWeberForStackExchange

+0

Hey dk, hai avuto qualche successo nell'accelerare la tua ricerca? Ho fatto la stessa cosa che hai fatto sopra ed era ancora piuttosto lento, come hai detto tu. – getWeberForStackExchange

+0

Weber, ho trovato il successo rimuovendo la relazione inversa, che ha modificato lo schema e velocizzato notevolmente le ricerche. Ma non ho ancora testato su un DB completamente caricato e sono preoccupato per il bloat a causa del nuovo schema. Vedi i commenti nell'articolo collegato sopra. –

Problemi correlati