2011-08-25 17 views
25

Ho guardato molto in giro per vedere come usare MongoDB in combinazione con Solr, e alcune domande qui hanno risposte parziali, ma niente di concreto (più come teorie). Nella mia applicazione, avrò un sacco di documenti archiviati in MongoDB (forse fino a poche centinaia di milioni) e voglio implementare ricerche full-text su alcune proprietà di questi documenti, quindi suppongo che Solr sia il modo migliore per fare Questo.java - MongoDB + Solr spettacoli

Quello che voglio sapere è come devo configurare/eseguire tutto in modo che abbia buone prestazioni? in questo momento, ecco quello che faccio (e so che la sua non ottimale):

1- Quando si inserisce un oggetto in MongoDB, ho quindi aggiungerlo al Solr

SolrServer server = getServer(); 
SolrInputDocument document = new SolrInputDocument(); 
document.addField("id", documentId); 
... 
server.add(document); 
server.commit(); 

2- Quando si aggiorna una proprietà del oggetto, dal momento che Solr non può aggiornare un solo campo, per prima cosa recuperare l'oggetto da MongoDB poi posso aggiornare l'indice Solr con tutte le proprietà di oggetto e quelli nuovi e fare qualcosa di simile

StreamingUpdateSolrServer update = new StreamingUpdateSolrServer(url, 1, 0); 
SolrInputDocument document = new SolrInputDocument(); 
document.addField("id", documentId); 
... 
update.add(document); 
update.commit(); 

3- Quando l'esecuzione di query, prima interrogo Solr e poi quando si recupera l'elenco dei documenti SolrDocumentList I passare attraverso ciascun documento e:

  1. ottenere l'ID del documento
  2. ottenere l'oggetto da MongoDB avere lo stesso ID per essere in grado di recuperare le proprietà da lì

4- Quando eliminazione, beh non ho ancora e non proprio sicuro come farlo in Java

così qualcuno ha suggerimenti su come farlo in modi più efficienti per ciascuno degli scenari descritti qui fatto parte? come il processo per farlo in un modo che non ci vorrà 1 ora per ricostruire l'indice quando si hanno molti documenti in Solr e si aggiunge un documento alla volta? I miei requisiti qui sono che gli utenti potrebbero voler aggiungere un documento alla volta, molte volte e mi piacerebbe che siano in grado di recuperarlo subito dopo

+0

Quanto è grande ogni documento e le proprietà che si desidera indicizzare? –

+0

@JustinThomas - beh ogni documento può avere circa 10 proprietà, alcune di esse possono essere lunghe descrizioni e mi piacerebbe indicizzare per la ricerca full-text sulla descrizione, solo la corrispondenza esatta sugli altri. Questo risponde alla tua domanda? – Guillaume

risposta

14

Il tuo approccio è effettivamente buono. Alcuni framework popolari come Compass eseguono ciò che descrivono a un livello inferiore per rispecchiare automaticamente le modifiche dell'indice che sono state eseguite tramite il framework ORM (vedere http://www.compass-project.org/overview.html).

In aggiunta a ciò che descrivi, vorrei anche periodicamente reindicizzare tutti i dati che vivono in MongoDB per assicurare che sia Solr sia Mongo siano sincronizzati (probabilmente non per tutto il tempo che potresti pensare, a seconda della numero di documenti, numero di campi, numero di token per campo e prestazioni degli analizzatori: spesso creo indici da 5 a 8 milioni di documenti (circa 20 campi, ma i campi di testo sono brevi) in meno di 15 minuti con complessi analizzatori, assicurati che il tuo RAM RAM non sia troppo piccolo e non si impegni/ottimizzi fino a quando non sono stati aggiunti tutti i documenti).

Per quanto riguarda le prestazioni, un impegno è costoso e l'ottimizzazione è molto costosa. In base a ciò che conta di più, è possibile modificare il valore di mergefactor in Solrconfig.xml (valori elevati migliorano le prestazioni di scrittura mentre i valori bassi migliorano le prestazioni di lettura, 10 è un buon valore per iniziare).

Sembra che tu abbia paura del tempo di costruzione dell'indice. Tuttavia, poiché Lucene indicizza lo storage è basato su segmenti, il throughput di scrittura non dovrebbe dipendere troppo dalla dimensione dell'indice (http://lucene.apache.org/java/2_3_2/fileformats.html).Tuttavia, il tempo di riscaldamento aumenterà, così si dovrebbe garantire che

  • ci sono tipiche (in particolare per le specie, al fine di caricare i fieldcaches), ma le query non troppo complesse nei parametri firstSearcher e newSearcher nel vostro solrconfig. file di configurazione XML,
  • useColdSearcher è impostato su
    • falso al fine di avere buone prestazioni di ricerca, o
    • vero se si desidera che le modifiche eseguite per l'indice da prendere velocemente in considerazione al prezzo di una ricerca più lento .

Inoltre, se è accettabile per voi, se i dati diventano ricercabili solo poche X millisecondi dopo che è stato scritto per MongoDB, è possibile utilizzare la funzione di commitWithin UpdateHandler. In questo modo Solr dovrà impegnarsi meno spesso.

Per ulteriori informazioni sui fattori di rendimento Solr, vedere http://wiki.apache.org/solr/SolrPerformanceFactors

Per eliminare i documenti, è possibile eliminare per ID documento (come definito nella schema.xml) o query: http://lucene.apache.org/solr/api/org/apache/solr/client/solrj/SolrServer.html

+0

buon punto sul 'deleteById', in realtà non l'ho visto (non ho nemmeno provato a dire, ho pensato che ci fosse qualcosa di più complicato). Dato che sembri sapere molto su questo, qualche altra domanda se non ti dispiace: 1. quanto costa un buon buffer RAM? 2. Non ho modificato firstSearcher e newSearcher per il file solrconfig.xml di esempio, sono a posto? 3. Infine, ho un'istanza di solr in esecuzione in tomcat, con 5 core. Cambia qualcosa riguardo alle prestazioni per avere più di una istanza di solr in esecuzione? grazie per il vostro aiuto – Guillaume

+0

1. È necessario eseguire alcuni benchmark per trovare la dimensione del buffer migliore per. Vi consiglio di iniziare con 32M e raddoppiare la quantità di memoria disponibile per il buffer RAM ad ogni iterazione, interrompere quando l'aumento della dimensione del buffer di ram non produce alcun miglioramento significativo. – jpountz

+0

2. Non lo sono: il caricamento delle cache di campo (richieste per query di tipo e funzioni tra le altre) richiede tempo con Solr, di conseguenza, la prima query che utilizzerà le cache di campo su un nuovo indice avrà una penalizzazione delle prestazioni, quindi è necessario per inserire query che caricheranno queste cache di campo (basta inserire una query che esegua gli ordinamenti sugli stessi campi dell'applicazione) in newSearcher e firstSearcher. – jpountz

1
  1. Puoi anche aspettare altri documenti e indicizzarli solo ogni X minuti. (Naturalmente questo altamente dipende della vostra applicazione & requisiti)

  2. Se i documenti sono piccole e non hai bisogno di tutti i dati (che sono memorizzate in MongoDB) si può mettere solo il campo è necessario nel Documento Solr da la loro memorizzazione ma non indicizzare

<field name="nameoyourfield" type="stringOrAnyTypeYouuse"indicizzato="false"memorizzati="true"/>