Domanda

Al momento sono nel bel mezzo di un'applicazione ragionevolmente grande domanda / risposta basata (un po 'come StackOverflow / answerbag.com) Stiamo utilizzando SQL (Azure) e NHibernate per l'accesso ai dati e MVC per l'applicazione UI.

Finora, lo schema è più o meno lungo le linee del db StackOverflow, nel senso che abbiamo un solo Post tabella (contiene entrambe le domande / risposte)

Probabilmente andando a usare qualcosa lungo le linee del seguente interfaccia repository:

public interface IPostRepository
{
    void PutPost(Post post);
    void PutPosts(IEnumerable<Post> posts);

    void ChangePostStatus(string postID, PostStatus status);

    void DeleteArtefact(string postId, string artefactKey);
    void AddArtefact(string postId, string artefactKey);

    void AddTag(string postId, string tagValue);
    void RemoveTag(string postId, string tagValue);

    void MarkPostAsAccepted(string id);
    void UnmarkPostAsAccepted(string id);

    IQueryable<Post> FindAll();
    IQueryable<Post> FindPostsByStatus(PostStatus postStatus);
    IQueryable<Post> FindPostsByPostType(PostType postType);
    IQueryable<Post> FindPostsByStatusAndPostType(PostStatus postStatus, PostType postType);
    IQueryable<Post> FindPostsByNumberOfReplies(int numberOfReplies);
    IQueryable<Post> FindPostsByTag(string tag);
}

La mia domanda è: Dove / come potrei inserire solr in questo per una migliore interrogazione di questi "messaggi" (Sarò utilizzando solrnet per la comunicazione vero e proprio con Solr)

Idealmente, sarei usando il db SQL come un semplice persistente negozio- La maggior parte di quanto sopra operazioni IQueryable si muoverebbe in una sorta di classe SolrFinder (o qualcosa di simile)

La proprietà Body è quella che causa i problemi attualmente -. È abbastanza grande, e rallenta query su SQL

Il mio problema principale è, per esempio, se qualcuno "aggiornamenti" post - aggiunge un nuovo tag, per esempio, allora che tutto il post sarà bisogno di ri-indicizzazione. Ovviamente, facendo questo richiederà una query come questa:

  

"SELECT * FROM post dove ID = xyz"

Questa sarà ovviamente, essere molto lento. Solrnet ha un NHibernate facility- ma credo che questo sarà lo stesso risultato di cui sopra?

ho pensato a un modo per aggirare questo, che mi piacerebbe vostre opinioni su:

  • Aggiunta l'ID ad una coda (Amazon SQS o qualcosa del genere - mi piace la facilità d'uso con questo)
  • Avere un servizio (o gruppo di servizi) da qualche parte che fare quanto sopra menzionata domanda, costruire il documento, e ri-inserirlo per solr.

Un altro problema che sto avendo con il mio progetto: Dove dovrebbero le "ri-indicizzazione" Metodo (s) essere chiamato da? Il controller MVC? o devo avere una "Postservice" di classe tipo, che avvolge l'istanza di IPostRepository?

Tutti gli indicatori sono notevolmente ricevute su questo!

È stato utile?

Soluzione

Sul sito di e-commerce che per cui lavoro, usiamo Solr per fornire veloce sfaccettatura e la ricerca del catalogo prodotti. (In termini disadattato non Solr, questo significa che il "Schede ATI (34), NVIDIA (23), Intel (5)" stile di link di navigazione che è possibile utilizzare per drill-down attraverso cataloghi di prodotti su siti come Zappos, Amazon, NewEgg e Lowe.)

Questo perché Solr è progettato per fare questo genere di cose in fretta e bene, e cercando di fare questo genere di cose in modo efficiente in un database relazionale tradizionale è, beh, non sta per accadere, a meno che non si desidera avviare aggiunta e la rimozione indici al volo e vanno piena EAV, che è solo tosse Magento tosse stupido. Così il nostro database di SQL Server è l'archivio dati "autorevole", e gli indici Solr sono "proiezioni" di che i dati di sola lettura.

Sei con me fino ad ora perché suona come ci si trova in una situazione simile. Il passo successivo consiste nel determinare se è OK che i dati nell'indice Solr possono essere leggermente stantio. Probabilmente avete accettato il fatto che sarà un po 'stantia, ma le prossime decisioni sono

  • Come stantio è troppo stantio?
  • Quando fare velocità valore I o funzioni di interrogazione nel corso stantio?

Per esempio, io ho quello che io chiamo il "lavoratore", che è un servizio di Windows che utilizzi Quartz.NET per eseguire C # implementazioni IJob periodicamente. Ogni 3 ore, uno di questi posti di lavoro che viene eseguito è il RefreshSolrIndexesJob, e tutto ciò che di lavoro fa è Ping An HttpWebRequest verso http://solr.example.com/dataimport?command=full-import. Questo è perché usiamo di Solr built-in DataImportHandler effettivamente aspirare i dati dal database di SQL; il lavoro deve solo "touch" che URL periodicamente per fare il lavoro di sincronizzazione. Poiché il DataImportHandler impegna periodicamente i cambiamenti, questo è tutto in modo efficace in esecuzione in background, trasparente per gli utenti del sito Web.

Questo significa che le informazioni nel catalogo prodotti può essere fino a 3 ore stantio. Un utente potrebbe fare clic su un collegamento per "Medium Disponibile (3)" sulla pagina del catalogo (in quanto questo tipo di dati sfaccettato è generato da una query SOLR), ma poi vedi nella pagina di dettaglio del prodotto che nessun medium sono in azione (dal su questo pagina, l'informazione quantità è una delle poche cose che non nella cache o interrogato direttamente contro la base di dati). Questo è fastidioso, ma in genere raro nella nostra particolare situazione (siamo una ragionevolmente piccola impresa e non che ad alto traffico), e sarà fissato in 3 ore ogni modo quando abbiamo ricostruire l'intero indice di nuovo da zero, quindi abbiamo accettato questo come un ragionevole compromesso.

Se si può accettare questo grado di "stantio", allora questo processo di lavoro di fondo è un buon modo per andare. Si potrebbe prendere l'approccio "ricostruire l'intera cosa ogni poche ore", o la vostra repository potrebbe inserire l'ID in una tabella, per esempio, dbo.IdentitiesOfStuffThatNeedsUpdatingInSolr, e quindi un processo in background può periodicamente la scansione attraverso quella tabella e aggiornare solo i documenti in Solr se la ricostruzione l'intero indice da zero non è periodicamente ragionevole date le dimensioni o la complessità del vostro set di dati.

Un terzo approccio è quello di avere il vostro uova repository un thread in background che gli aggiornamenti dell'indice Solr per quanto riguarda quel documento corrente più o meno allo stesso tempo, quindi i dati è stantio solo per pochi secondi:

class MyRepository
{
    void Save(Post post)
    {
         // the following method runs on the current thread
         SaveThePostInTheSqlDatabaseSynchronously(post);

         // the following method spawns a new thread, task,
         // queueuserworkitem, whatevever floats our boat this week,
         // and so returns immediately
         UpdateTheDocumentInTheSolrIndexAsynchronously(post);
    }
}

Ma se questo esplode, per qualche motivo, si potrebbe perdere gli aggiornamenti in Solr, quindi è ancora una buona idea avere Solr fare una periodica "soffiare via tutto e rinfrescare", o di avere un mietitore sfondo servizio di operaio-tipo che i controlli per out-of-date dati in Solr tutti una volta in una luna blu.

Per quanto riguarda l'interrogazione di questi dati da Solr, ci sono alcuni approcci si poteva prendere. Uno è quello di nascondere il fatto che esiste Solr interamente tramite i metodi della Repository. Io personalmente non consiglio questo perché è probabile che lo schema Solr sta per essere spudoratamente su misura per l'interfaccia utente che accederà che i dati; abbiamo già preso la decisione di utilizzare Solr per fornire un facile sfaccettatura, l'ordinamento e visualizzazione rapida delle informazioni, in modo tanto vale usarlo per la sua estensione. Questo significa che lo rende esplicita nel codice quando intendiamo accesso Solr e quando intendiamo per accedere l'oggetto di database up-to-date, non memorizzato nella cache.

Nel mio caso, ho finire con NHibernate per fare l'accesso CRUD (caricamento di un ItemGroup, futzing con le sue norme sui prezzi, e quindi salvare di nuovo), rinunciando al modello repository perché in genere non vedo il suo valore quando NHibernate e le sue mappature sono già astrazione del database. (Questa è una scelta personale.)

Ma quando l'esecuzione di query sui dati, che conosco abbastanza bene, se sto usando per scopi catalogo-oriented (mi importa di velocità e l'esecuzione di query ) o per la visualizzazione in una tabella in un'applicazione amministrativa di back-end (mi importa di valuta ). Per l'interrogazione sul sito web, ho un'interfaccia chiamata ICatalogSearchQuery. Ha un metodo di Search() che accetta un SearchRequest dove mi definisco alcuni parametri - aspetti selezionati, cercare termini, numero di pagina, il numero di articoli per pagina, ecc .-- e restituisce un SearchResult - rimanenti sfaccettature, numero di risultati, i risultati in questa pagina, ecc roba noiosa abbastanza.

dove si fa interessante è che l'attuazione di tale ICatalogSearchQuery sta usando una lista di ICatalogSearchStrategys sotto. La strategia di default, il SolrCatalogSearchStrategy, colpi Solr direttamente tramite una pianura HttpWebRequest vecchio stile e l'analisi del XML nella HttpWebResponse (che è molto più facile da usare, secondo me, di alcune delle librerie client SOLR, anche se possono avere ottenuto meglio da quando ho Ultimi visti di loro più di un anno fa). Se questa strategia genera un'eccezione o vomita per qualche ragione, allora la DatabaseCatalogSearchStrategy colpisce il database SQL direttamente - anche se ignora alcuni parametri del SearchRequest, come sfaccettatura o la ricerca di testo avanzata, dal momento che è inefficiente da fare lì ed è tutta la ragione stiamo usando Solr in primo luogo. L'idea è che di solito SOLR è rispondere alle mie richieste di ricerca rapidamente in gloria full-optional, ma se qualcosa salta su e SOLR va giù, poi le pagine del catalogo del sito può ancora funzionare in "modalità a funzionalità ridotta" colpendo il database con un servizio limitato situato direttamente. (Dal momento che abbiamo reso esplicito nel codice che si tratta di una ricerca, che la strategia può prendere qualche libertà in ignorando alcuni dei parametri di ricerca, senza preoccuparsi di influenzare i clienti troppo severamente.)

asporto chiave: Ciò che è importante è che la decisione di eseguire una query su un archivio dati, eventualmente-stantio contro l'archivio dati autorevole è stato fatto esplicito - se voglio veloce, possibilmente dati non aggiornati con funzioni di ricerca avanzate, io uso ICatalogSearchQuery. Se voglio, up-to-date di dati lento con l'inserimento / aggiornamento / capacità di eliminazione, io uso query denominate di NHibernate (o un deposito nel tuo caso). E se faccio un cambiamento nel database SQL, so che il servizio dei lavoratori out-of-process aggiornerà Solr alla fine, rendendo le cose alla fine coerente. (E se c'era qualcosa di veramente importante, ho potuto trasmettere un evento o il ping direttamente al negozio SOLR, dicendogli di aggiornamento, possibilmente in un thread in background se dovessi.)

La speranza che ti dà una certa comprensione.

Altri suggerimenti

Usiamo solr per interrogare un database di grandi dimensioni prodotto. Circa 1 milione di prodotti, e 30 negozi.

Quello che abbiamo fatto è che abbiamo usato trigger sul tavolo del prodotto e le tabelle azionari sul nostro server Sql.

Ogni volta che una riga viene cambiato bandiere del prodotto da indicizzato. E abbiamo un servizio di Windows che afferra questi prodotti e li inviamo a Solr ogni 10 secondi. (Con un limite di 100 prodotti per lotto).

E 'super efficiente, informazioni tempo quasi reale per lo stock.

Se si dispone di un campo di testo grande (il tuo campo 'corpo'), allora sì, ri-indice in background. Le soluzioni che hai menzionato (coda o servizio in background periodica) faranno.

controller MVC dovrebbe essere ignaro di questo processo.

Ho notato avete IQueryables nell'interfaccia repository. SolrNet attualmente non un provider LINQ . In ogni caso, se tali operazioni sono tutte si sta andando a che fare con Solr (vale a dire senza sfaccettature), si potrebbe voler considerare l'utilizzo di Lucene.Net invece, che fa hanno un fornitore di LINQ.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top