2011-08-17 1 views
6

sto usando RavenDB costruire 371 ed ho il seguente modello:Interrogazione di un insieme figlio da più valori in RavenDB

class Product { 
public string Id { get; set; } 
public ProductSpec[] Specs { get; set; } 
} 

class ProductSpec { 
public string Name { get; set; } 
public string Value { get; set; } 
} 

Mi piacerebbe essere in grado di interrogare per i prodotti che hanno un insieme di specifiche. Quando l'interrogazione da una singola specifica:

session.Query<Product>() 
.Where(product => product.Specs.Any(spec => spec.Name == "Color" && spec.Value == "Red")) 
.ToList(); 

I risultati attesi sono restituiti, tuttavia quando viene aggiunto un predicato spec supplementare:

non vengono restituiti anche se i risultati restituiti dalla prima query contengono prodotti con nome specifico "Paese" e valore "US". Lo stesso risultato si osserva quando si utilizza il metodo LuceneQuery. Questo sembra essere un problema simile a this discussion tuttavia non è stato possibile implementare la soluzione suggerita. In particolare, dopo aver creato l'indice suggerito, non so come interrogarlo.

Come posso supportare questo tipo di query in RavenDB?

EDIT

Non riesco ancora a interrogare su valori multipli su un insieme di tipi composti. Invece, ho modificato il modello in modo che una combinazione di specifiche/valori sia una stringa concatenata in modo tale che la raccolta delle specifiche sia una serie di stringhe. Questo può essere interrogato da più valori:

class Product { 
public string Id { get; set; } 
public int CategoryId { get; set; } 
public string[] Specs { get; set; } 
} 

Per riferimento, il modello e query originale funziona utilizzando MongoDB con la loro caratteristica multikeys indice. Il problema molto sorprendente con MongoDB è che l'operazione count() è slow for index queries. Questo tipo di query è essenziale per l'impaginazione e sebbene il conteggio possa essere memorizzato nella cache, vorrei una soluzione che fornisca questo fuori dalla scatola. Inoltre, un altro requisito che ho è la possibilità di aggregare gruppi di specifiche per raccolte arbitrarie di prodotti (ad esempio, per ottenere una raccolta di tutte le combinazioni specifiche/valore per i prodotti in una determinata categoria). In MongoDB questo può essere ottenuto usando la loro funzionalità MapReduce, tuttavia i risultati di un'operazione MapReduce sono statici e devono essere aggiornati manualmente quando i dati di origine cambiano mentre RavenDB aggiorna gli indici MapReduce automaticamente in background. Quindi, anche se dichiarare gli indici MapReduce in RavenDB è più complicato di quanto non sia in MongoDB IMO, l'aggiornamento automatico dello sfondo supera di gran lunga gli svantaggi. Guarderò allo CouchDB dato che anche le loro visualizzazioni vengono aggiornate automaticamente, anche se sembra che siano aggiornate su richiesta, non automaticamente in background, non sono sicuro che questo sarà un problema.

+0

Si può vedere la discussione su come risolvere questo qui: http://groups.google.com/group/ravendb/browse_thread/thread/dd8a77ccf7322c00/ab97561899624c47 –

+0

ho trovato che il suggerimento soluzione funziona per raccolte di tipi semplici come una serie di stringhe, ma non funziona con un tipo composto come ProductSpec. La query non restituisce risultati. – eulerfx

risposta

1

Ho modificato leggermente il modello ed è stato in grado di ottenere il risultato desiderato utilizzando il metodo Project in AbstractIndexCreationTask.Questa è la (semplificato) modello di dati:

public class Product 
{ 
    public string Id { get; set; } 
    public int CategoryId { get; set; } 
    public int TotalSold { get; set; } 
    public Dictionary<string, string> Specs { get; set; } 
} 

Questa è la definizione dell'indice:

public class Products_ByCategoryIdAndSpecs_SortByTotalSold : AbstractIndexCreationTask<Product> 
{ 
    public Products_ByCategoryIdAndSpecs_SortByTotalSold() 
    { 
     this.Map = products => from product in products 
           select new 
           { 
            product.CategoryId, 
            _ = Project(product.Specs, spec => new Field("Spec_" + spec.Key, spec.Value, Field.Store.NO, Field.Index.ANALYZED)), 
            product.TotalSold 
           }; 
    } 
} 

allora posso interrogare in questo modo:

var results = session.Advanced.LuceneQuery<Product, Products_ByCategoryIdAndSpecs_SortByTotalSold>() 
     .WhereEquals("CategoryId", 15920) 
     .AndAlso().WhereEquals("Spec_Class", "3A") 
     .AndAlso().WhereEquals("Spec_Finish", "Plain") 
     .OrderBy("-TotalSold") 
     .ToList(); 

Ciò restituirà i prodotti della categoria "15920" che hanno un valore di specifica "Classe" di "3A" e un valore di specifica "Fine" di "Normale", ordinati in ordine decrescente per le unità totali vendute.

La chiave utilizzava il metodo Project che sostanzialmente crea campi nel documento Lucene per ogni coppia nome-valore specifica.

3

Ho provato diverse cose e non sono riuscito a farlo funzionare. La query specifica che stai cercando di eseguire è risolta in questa query di Lucene da RavenDB (nella versione 426):

"{(Nome: Colore AND Valore: Rosso) AND (Nome: Paese AND Valore: USA)}" che spiega perché non ottieni risultati.

Dopo googling su questo argomento, ho trovato questo post: Lucene Query Syntax

Diverse soluzioni sono suggerite tra le risposte. Spero che questo ti sia d'aiuto. Sono piuttosto curioso per me, se questo non è possibile.