2010-11-23 7 views
22

Ich bin auf der Suche nach einem Beispiel für die Implementierung und Verwendung von Map-Reduce im RavenDB .NET Client.RavenDB Map-Reduce Beispiel mit .NET Client

Ich möchte es auf ein bestimmtes Szenario anwenden: Generierung von eindeutigen und gesamten Besucherzahlen.

Ein Beispieldokument, das in RavenDB gespeichert würde:

public class StatisticsEntry 
{ 
    public string Id { get; set; } 
    public string UserId { get; set; } 
} 

ich herausfinden, wie ein Standard-Index mit Map erstellen, aber ich bin verloren, wie tatsächlich die Funktion reduzieren, verwenden und dann die Ergebnisse abrufen.

Leider erklärt die example provided on the RavenDB Site nicht, was los ist, so dass ich verstehen kann, wie man es über die .NET-API verwendet, und die Beispiele scheinen dies überhaupt nicht mit der .NET-API zu implementieren.

+0

Was möchten Sie erreichen? Möchten Sie die Datumszeit in irgendeiner Weise verwenden? (Pro Tag, pro Monat, pro Jahr ein bisschen Dinge?) –

+0

Derzeit nicht. Ich kann zu einem späteren Zeitpunkt zusätzliche Indizes mit diesem Feld haben. Im Moment werde ich es aus der Klasse entfernen, um es zu vereinfachen. Was "Ich will erreichen" betrifft - Ich möchte Statistiken erstellen, die a) Gesamtanzahl von StatisticsEntry und b) Unique Users anzeigen. –

+0

Okay - weil Sie in dieser Art von Szenario eine Karte/Reduzierungsindex pro "Gruppierung" benötigen würden - Antwort im Handumdrehen –

Antwort

38

Ein Map Reduce Index ist nur eine andere Art zu sagen "Ich will eine Gruppe machen durch", nur die Gruppe nach ist vor RavenDB wird es im Hintergrund effizient abarbeiten, so dass Sie zur Abfragezeit ein vorberechnetes Ergebnis suchen.

Betrachten Sie das folgende als Antwort als eine gewöhnliche Gruppe von (für Unique User)

var results = from doc in docs 
group doc by doc.UserId into g 
select new 
{ 
     g.UserId, 
     g.Count() 
} 

Ignorieren der tatsächlichen Inhalt des Arrays erstellt haben, können wir die Gesamtergebnisse erhalten, indem für

fragen
results.Length 

wie Sie es erwarten würden.

In RavenDB, können Sie diese Funktion in eine Karte aufgespalten und eine Reduce, und Sie am Ende mit

public class UniqueVisitorsResult 
{ 
    public string UserId { get; set; } 
    public int Count { get; set; } 
} 

public class UniqueVisitorsIndex : AbstractIndexCreationTask<StatisticsEntry, UniqueVisitorsResult> 
{ 
    public UniqueVisitorsIndex() 
    { 
     Map = docs=> from doc in docs 
         select new 
         { 
          UserId = doc.UserId, 
          Count = 1 
         }; 
     Reduce = results => from result in results 
         group result by result.UserId into g 
         select new 
         { 
          UserId = g.Key, 
          Count = g.Sum(x=>x.Count) 
         }; 
    } 
} 

Im Wesentlichen ist dies das gleiche wie die oben - aber du hast es in eine einge MapReduce Funktion ;-)

session.Query<StatisticEntry, UniqueVisitorsIndex>().Count(); 

geben Sie die Gesamtzahl der Besucher, Graf angenommen wurde ordnungsgemäß in der LINQ-Provider implementiert (iirc ich denke, es hat)

die Gesamt Anzahl der Einträge ist einfach

session.Query<StatisticEntry>().Count(); 

Wie man erwarten würde (keine Karte/reduziert erforderlich)

Hinweis: Dieser Index kann auch verwendet werden, die Anzahl der Treffer von einem bestimmten Benutzer zu sehen, wie der Graf Wird im Index berechnet, wenn Sie sich nicht um die Anzahl kümmern, dann diesen Teil der MapReduce fallen lassen und tun

+0

Awesome. Danke für die Erklärung. –

+0

Im ersten Beispiel geben Sie 'Count = g.Sum (x => x.Count)' - das gibt mir einen Kompilierungsfehler, da 'x' vom Typ' StatisticsEntry' ist - woher soll das kommen? –

+1

Oh, definieren Sie eine Ausgabeform, lassen Sie mich das Beispiel ändern :) –

18

Hier ist, wie Sie einen Index für Besucher aufbauen können:

public class Statistics_UniqueVisitors : AbstractIndexCreationTask<StatisticsEntry> 
{ 
    public Statistics_UniqueVisitors() 
    { 
     Map = entries => from entry in entries 
         select new { entry.UserId, Count = 1 }; 
     Reduce = results => from result in results 
          group result by result.UserId into g 
          select new { UserId = g.Key, Count = g.Sum(x=>x.Count) }; 
    } 
} 

können Sie dann abfragen, dies mit:

var numberOfUniqueVisitors = s.Query<StatisticEntry, Statistics_UniqueVisitors>().Count(); 

Für Gesamtzahl der Besucher, die Sie verwenden können:

var numberOfVisitors = s.Query<StatisticEntry>().Count();