Questa è una continuazione del progetto indicato nella domanda this.Catalogo prodotti query Catalogo RavenDB per aggregazione di specifiche su raccolta arbitraria di prodotti
ho il seguente modello:
class Product {
public string Id { get; set; }
public string[] Specs { get; set; }
public int CategoryId { get; set; }
}
Le "caratteristiche" negozi matrice Theproductspecification coppie valore nome uniti da un carattere speciale. Ad esempio, se un prodotto è colorato in blu, la stringa della specifica sarà "Colore ~ Blu". La rappresentazione delle specifiche in questo modo consente di eseguire query per prodotti con più valori di specifica specificati da una query. Esistono due query principali che desidero supportare:
- Ottenere tutti i prodotti in una determinata categoria.
- Ottieni tutti i prodotti in una determinata categoria che hanno una serie di specifiche specificate.
Questo funziona bene con RavenDB. Tuttavia, oltre ai prodotti che soddisfano una determinata query, desidero restituire un set di risultati che contenga tutte le coppie nome-valore per l'insieme di prodotti specificati dalla query. Le coppie nome-valore della specifica devono essere raggruppate in base al nome e al valore della specifica e contenere un conteggio di prodotti che hanno una specifica coppia nome-valore. Per la query # 1 ho creato la seguente mappa ridurre indice:
class CategorySpecGroups {
public int CategoryId { get; set; }
public string Spec { get; set; }
public int Count { get; set; }
}
public class SpecGroups_ByCategoryId : AbstractIndexCreationTask<Product, CategorySpecGroups>
{
public SpecGroups_ByCategoryId()
{
this.Map = products => from product in products
where product.Specs != null
from spec in product.Specs
select new
{
CategoryId = product.CategoryId,
Spec = spec,
Count = 1
};
this.Reduce = results => from result in results
group result by new { result.CategoryId, result.Spec } into g
select new
{
CategoryId = g.Key.CategoryId,
Spec = g.Key.Spec,
Count = g.Sum(x => x.Count)
};
}
}
Posso quindi interrogare questo indice e ottenere tutte le coppie nome-valore spec in una determinata categoria. Il problema che sto incontrando è quello di ottenere lo stesso set di risultati ma per una query che filtra sia da una categoria che da un insieme di coppie nome-valore della specifica. Quando si utilizza SQL questo set di risultati si otterrebbe facendo un gruppo su un insieme di prodotti filtrati per categoria e specifiche. In generale, questo tipo di query è costoso, ma quando si filtrano sia per categoria che per specifiche, i set di prodotti sono normalmente piccoli, sebbene non abbastanza piccoli da adattarsi a una singola pagina: possono contenere fino a 1000 prodotti. Per riferimento, MongoDB supporta un metodo group che può essere utilizzato per ottenere lo stesso set di risultati. Questo esegue il lato server di raggruppamento ad hoc e le prestazioni sono accettabili.
Come posso ottenere questo tipo di set di risultati utilizzando RavenDB?
Una possibile soluzione è ottenere tutti i prodotti per una query ed eseguire il raggruppamento in memoria e un'altra opzione è creare un indice mapreduce come sopra, sebbene la sfida con questo sarebbe la deduzione di tutte le possibili selezioni di specifiche che possono essere fatte per una determinata categoria e inoltre, questo tipo di indice potrebbe esplodere in termini di dimensioni.
Per un esempio, dare un'occhiata a this fastener category page. L'utente può filtrare la propria selezione selezionando gli attributi. Quando viene selezionato un attributo, restringe la selezione dei prodotti e visualizza gli attributi all'interno del nuovo set di prodotti. Questo tipo di interazione viene in genere chiamato faceted search.
EDIT
Nel frattempo, sarò tentando una soluzione che utilizza Solr come sostengono ricerca sfaccettata, fuori dalla scatola.
EDIT 2
sembra che RavenDB supporta anche faceted search (che ovviamente ha un senso, gli indici vengono memorizzati dal Lucene proprio come Solr). Esplorerò questo e pubblicherò aggiornamenti.
EDIT 3
La funzionalità di ricerca RavenDB sfaccettato funziona come previsto. Conservo un documento di impostazione della faccetta per ogni ID di categoria che viene utilizzato per calcolare le faccette per una query all'interno di una determinata categoria. Il problema che sto avendo ora è la performance. Per una raccolta di prodotti 500k con 4500 categorie distinte che risultano in 4500 documenti di configurazione dei facet, una query per ID categoria impiega circa 16 secondi quando esegue anche query per facet e circa 0,05 secondi quando non esegue query per le faccette. La particolare categoria testata contiene circa 6k prodotti, 23 sfaccettature distinte e 2k distinte combinazioni di nomi. Dopo aver esaminato il codice in FacetedQueryRunner, viene visualizzata una query facet che genererà una query Lucene per ogni combinazione nome-valore di facet per ottenere i conteggi, oltre a una query per ogni nome di facet per ottenere i termini. Un problema con l'implementazione è che recupererà tutti i termini distinti per un determinato nome di facet indipendentemente dalla query, che nella maggior parte dei casi ridurrà significativamente il numero di termini per un facet e quindi ridurrà il numero di query Lucene. Un modo per migliorare le prestazioni qui sarebbe quello di memorizzare un set di risultati calcolati MapReduce (come mostrato sopra) per ciascun documento di impostazione di sfaccettatura, che potrebbe quindi essere interrogato per ottenere tutti i termini distinti quando vengono ulteriormente filtrati per sfaccettature. Tuttavia, le prestazioni generali potrebbero essere ancora troppo lente.
Non credo di aver capito. Qual è la query che vuoi fare? Qual è il risultato previsto? –
Prendiamo ad esempio il set di prodotti definiti da un ID di categoria - tutti i prodotti in una determinata categoria. Ogni prodotto nel set ha un insieme di coppie nome-valore specifiche che possono essere raggruppate per nome e valore contando il numero di prodotti con una data coppia di valori nominali. Questo è il risultato che vorrei ottenere, ma non solo per i prodotti in una determinata categoria, ma anche per le categorie in una categoria filtrata da un insieme di coppie nome-valore specifiche. Questo per consentire di "forare" una selezione di prodotti su un catalogo di prodotti di un sito Web. – eulerfx