2012-04-13 5 views
17

Genauer gesagt in Raven DB, ich möchte eine generische Methode mit einer Signatur wie erstellen;Raven DB: Wie kann ich alle Dokumente eines bestimmten Typs löschen

public void Clear<T>() {... 

Dann Raven DB löschen Sie alle Dokumente des angegebenen Typs.

Ich verstehe von anderen Beiträgen von Ayende zu ähnlichen Fragen, dass Sie einen Index an Ort und Stelle benötigen würden, um dies als Batch zu tun.

Ich denke, das würde bedeuten, einen Index zu erstellen, der jeden Dokumententyp abbildet - das scheint eine Menge Arbeit zu sein.

Kennt jemand eine effiziente Methode zum Erstellen einer Methode wie dem oben genannten, die ein Set löschen direkt in der Datenbank tun?

Antwort

9

Nach vielen Experimenten ich die Antwort gefunden ganz einfach zu sein, obwohl bei weitem nicht offensichtlich;

public void Clear<T>() 
{ 
    session.Advanced.DocumentStore.DatabaseCommands.PutIndex(indexName, new IndexDefinitionBuilder<T> 
    { 
     Map = documents => documents.Select(entity => new {}) 
    }); 

    session.Advanced.DatabaseCommands.DeleteByIndex(indexName, new IndexQuery()); 
} 

Natürlich kann man fast sicher nicht Ihren Index definieren und in einem Rutsch Ihre löschen tun, habe ich dies als eine einzige Methode zum Zweck der Kürze stellen.

Meine eigene Implementierung definiert die Indizes für den Anwendungsstart, wie von der Dokumentation empfohlen.

Wenn Sie diesen Ansatz verwenden möchten, um eine Eigenschaft von T zu indizieren, dann müssten Sie T einschränken. Zum Beispiel, wenn ich eine IEntity habe, von der alle meine Dokumentklassen erben und diese Klasse eine Eigenschaft Id spezifiziert. Dann würde Ihnen ein "where T: IEntity" erlauben, diese Eigenschaft im Index zu verwenden.

Es ist an anderen Stellen gesagt worden, aber es ist auch erwähnenswert, dass, wenn Sie einen statischen Index Raven definieren wird es wahrscheinlich verwenden, kann dies Ihre Anfragen verursachen scheinbar keine Daten zurückzugeben, die Sie eingefügt haben:

RavenDB Saving to disk query

+1

Als RavenDB-Mitwirkender empfehle ich diesen Weg nicht, da du unnötig einen Index erstellst. Stattdessen empfehle ich die Antwort von @ alexn: http://StackOverflow.com/a/13049179/536 –

4

Sie können das tun mit: http://blog.orangelightning.co.uk/?p=105

+0

Hallo Ayende, Ihre Antwort war wirklich nützlich, aber nicht ganz das, was ich gesucht habe. Nach vielem Experimentieren und Lernen über Raven fand ich die Lösung, die ich suchte. Ich werde die Antwort hier kurz für andere veröffentlichen. –

+0

Ich fand dies die einfachste nicht-programmatische Lösung. – Keith

+0

Ich habe den in diesem Blog erwähnten Reset-Befehl nie gefunden. Beendet mit einem Index, der dem von Ryan ähnlich ist. –

22

Ich nehme an, dass Sie dies von dem .NET-Client tun möchten. Wenn ja, verwenden Sie den Standard DocumentsByEntityName Index:

var indexQuery = new IndexQuery { Query = "Tag:" + collectionName }; 
session.Advanced.DocumentStore.DatabaseCommands.DeleteByIndex(
    "Raven/DocumentsByEntityName", 
    indexQuery, 
    new BulkOperationOptions { AllowStale = true }); 

var hilo = session.Advanced.DocumentStore.DatabaseCommands.Get("Raven/H‌​ilo/", collectionName); 
if (hilo != null) { 
    session.Advanced.DocumentStore.DatabaseCommands.Delete(hilo.‌​Key, hilo.Etag); 
} 

Wo collectionName der tatsächliche Name Ihrer Sammlung ist.

Die erste Operation löscht die Elemente. Die zweite löscht die HiLo file.

Überprüfen Sie auch die offizielle Dokumentation - How to delete or update documents using index.

+1

Dies ist IMHO ein besserer Weg als die akzeptierte Antwort, da es nicht die Erstellung eines Indexes erfordert und löscht alle Dokumente, die nicht Wenn Sie einen vorhandenen Index löschen – wal

+0

Ich möchte auch das verwandte HiLo-Dokument löschen, um die IDs zurückzusetzen. @alexn kann ich deinen Code bearbeiten, um dies hinzuzufügen? 'var hilo = session.Advanced.DocumentStore.DatabaseCommands.Get (" Raven/Hilo/themes "); session.Advanced.DocumentStore.DatabaseCommands.Delete (hilo.Key, hilo.Etag); ' – SandRock

+0

@SandRock absolut :) – alexn

6

Ich hatte dieses Problem auch und das ist die Lösung, die für mich arbeitete. Ich arbeite nur in einem Testprojekt, also könnte das für eine größere dB langsam sein, aber Ryan's Antwort hat nicht für mich funktioniert.

public static void ClearDocuments<T>(this IDocumentSession session) 
    { 
     var objects = session.Query<T>().ToList(); 
     while (objects.Any()) 
     { 
      foreach (var obj in objects) 
      { 
       session.Delete(obj); 
      } 

      session.SaveChanges(); 
      objects = session.Query<T>().ToList(); 
     } 
    } 
+0

Ich führe auch Tests gegen einen Embedded-Shop und nur Ihre Lösung funktionierte für mich. In einem Beitrag von Google Groups (https://groups.google.com/forum/#!topic/ravendb/QqZPrRUwEke) wird empfohlen, zunächst den DocumentsByEntityName-Index in diesem Szenario zu erstellen: "new RavenDocumentsByEntityName(). Execute (store) " Nachdem ich dies getan habe, fand ich immer noch, dass die Dokumente, die gelöscht werden sollten, noch vorhanden waren (ich verhindere auch, dass veraltete Abfragen zurückgegeben werden, so dass dies auch nicht die Antwort war). – rogersillito