【问题标题】:Raven DB: How can I delete all documents of a given typeRavendb:如何删除给定类型的所有文档
【发布时间】:2012-04-13 18:07:36
【问题描述】:

更具体地说,在 Raven DB 中,我想创建一个带有类似签名的通用方法;

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

然后让 Raven DB 清除给定类型的所有文档。

我从 Ayende 的其他帖子中了解到类似的问题,您需要一个索引才能批量执行此操作。

我认为这将涉及创建一个映射每种文档类型的索引 - 这似乎需要大量工作。

有没有人知道一种有效的方法来创建像上面这样直接在数据库中执行集合删除的方法?

【问题讨论】:

    标签: ravendb


    【解决方案1】:

    我假设您想从 .NET 客户端执行此操作。如果是,请使用标准的DocumentsByEntityName 索引:

    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);
    }
    

    collectionName 是您收藏的实际名称。

    第一个操作删除项目。第二个删除HiLo file

    还可以查看官方文档 - How to delete or update documents using index

    【讨论】:

    • 这比接受的答案更好,因为它不需要创建索引,并且如果您使用现有索引进行删除,它会删除任何可能不包含的文档。
    • 我也想删除相关的HiLo文档来重置ID。 @alexn 我可以编辑你的代码来添加这个吗? var hilo = session.Advanced.DocumentStore.DatabaseCommands.Get("Raven/Hilo/themes"); session.Advanced.DocumentStore.DatabaseCommands.Delete(hilo.Key, hilo.Etag);
    • @SandRock 绝对 :)
    • 以上代码有一些语法错误。这是无错误代码 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); }
    【解决方案2】:

    经过大量实验,我发现答案很简单,虽然远非显而易见;

    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());
    }
    

    当然,您几乎肯定不会一次性定义索引并删除,为了简洁起见,我将其作为单一方法。

    我自己的实现按照文档的建议定义了应用程序启动时的索引。

    如果您想使用这种方法来实际索引 T 的属性,那么您需要约束 T。例如,如果我有一个 IEntity,我的所有文档类都从该 IEntity 继承,并且该类指定了一个属性 Id。然后一个 'where T : IEntity' 将允许您在索引中使用该属性。

    在其他地方已经说过了,但同样值得注意的是,一旦你定义了一个静态索引,Raven 可能会使用它,这可能会导致你的查询似乎没有返回你插入的数据:

    RavenDB Saving to disk query

    【讨论】:

    • 作为 RavenDB 的贡献者,我不推荐这种方式,因为您创建了一个不必要的索引。相反,我推荐@alexn 的答案:stackoverflow.com/a/13049179/536
    【解决方案3】:

    我也遇到了这个问题,这是对我有用的解决方案。我只在一个测试项目中工作,所以对于更大的数据库来说这可能会很慢,但是 Ryan 的回答对我不起作用。

        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();
            }
        }
    

    【讨论】:

    • 我还在针对嵌入式商店运行测试,只有您的解决方案对我有用。 Google Groups (groups.google.com/forum/#!topic/ravendb/QqZPrRUwEkE) 上的帖子建议您首先需要在这种情况下创建 DocumentsByEntityName 索引:“new RavenDocumentsByEntityName().Execute(store);”完成此操作后,我仍然发现应该删除的文档仍然存在(我还防止返回过时的查询,所以这也不是答案)。
    【解决方案4】:

    【讨论】:

    • 嗨 Ayende,您的回答非常有用,但不是我想要的。经过大量实验和了解 Raven,我找到了我正在寻找的解决方案。我很快就会在这里为其他人发布答案。
    • 我发现这是最简单的非编程解决方案。
    • 我从未找到该博客中提到的重置命令。最终得到一个类似于 Ryan 的索引。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-08
    相关资源
    最近更新 更多