从RavenDB检索整个数据集合

从RavenDB检索整个数据集合,ravendb,Ravendb,我需要从RavenDB获取整个数据收集用户,并将检索到的结果集与另一组数据进行比较。在这个特定的收藏中有近4000条记录 由于Raven在默认情况下是安全的,因此每次会话的请求数超过或返回最多128条记录时,我都会收到一个异常 我不想将属性Session.Advanced.MaxNumberOfRequestsPerSession设置为更高的值 我应该使用什么查询来获取所有记录的计数?处理这种情况的理想方法是什么?您使用分页,一次读取1024项 int start = 0; while(true

我需要从RavenDB获取整个数据收集
用户
,并将检索到的结果集与另一组数据进行比较。在这个特定的收藏中有近4000条记录

由于Raven在默认情况下是安全的,因此每次会话的请求数超过
或返回最多128条记录时,我都会收到一个异常

我不想将属性
Session.Advanced.MaxNumberOfRequestsPerSession
设置为更高的值


我应该使用什么查询来获取所有记录的计数?处理这种情况的理想方法是什么?

您使用分页,一次读取1024项

int start = 0;
while(true)
{
   var current = session.Query<User>().Take(1024).Skip(start).ToList();
   if(current.Count == 0)
          break;

   start+= current.Count;
   allUsers.AddRange(current);

}
int start=0;
while(true)
{
var current=session.Query().Take(1024).Skip(start).ToList();
如果(current.Count==0)
打破
开始+=当前的计数;
allUsers.AddRange(当前);
}

在Ayende答案的基础上,这里有一个完整的方法,它确实克服了每个会话30个查询的问题,并且确实返回了所提供类的所有文档:

    public static List<T> getAll<T>(DocumentStore docDB) {
        return getAllFrom(0, new List<T>(), docDB);
    }

    public static List<T> getAllFrom<T>(int startFrom, List<T> list, DocumentStore docDB ) {
        var allUsers = list;

        using (var session = docDB.OpenSession())
        {
            int queryCount = 0;
            int start = startFrom;
            while (true)
            {
                var current = session.Query<T>().Take(1024).Skip(start).ToList();
                queryCount += 1;
                if (current.Count == 0)
                    break;

                start += current.Count;
                allUsers.AddRange(current);

                if (queryCount >= 30)
                {
                    return getAllFrom(start, allUsers, docDB);
                }
            }
        }
        return allUsers;
    }
公共静态列表getAll(DocumentStore docDB){
返回getAllFrom(0,new List(),docDB);
}
公共静态列表getAllFrom(int startFrom、列表列表、DocumentStore docDB){
var allUsers=列表;
使用(var session=docDB.OpenSession())
{
int queryCount=0;
int start=startFrom;
while(true)
{
var current=session.Query().Take(1024).Skip(start).ToList();
查询计数+=1;
如果(current.Count==0)
打破
开始+=当前的计数;
allUsers.AddRange(当前);
如果(查询计数>=30)
{
返回getAllFrom(start、allUsers、docDB);
}
}
}
回归诱惑;
}

我希望这样做不会太粗鲁

老实说,我更喜欢以下功能:

    public IEnumerable<T> GetAll<T>()
    {
        List<T> list = new List<T>();

        RavenQueryStatistics statistics = new RavenQueryStatistics();

        list.AddRange(_session.Query<T>().Statistics(out statistics));
        if (statistics.TotalResults > 128)
        {
            int toTake = statistics.TotalResults - 128;
            int taken = 128;
            while (toTake > 0)
            {
                list.AddRange(_session.Query<T>().Skip(taken).Take(toTake > 1024 ? 1024 : toTake));
                toTake -= 1024;
                taken += 1024;
            }
        }

        return list;
    }
public IEnumerable GetAll()
{
列表=新列表();
RavenQueryStatistics=新的RavenQueryStatistics();
list.AddRange(_session.Query().Statistics(out Statistics));
如果(statistics.TotalResults>128)
{
int-toTake=statistics.TotalResults-128;
int=128;
while(toTake>0)
{
AddRange(_session.Query().Skip(Take.Take)(toTake>1024?1024:toTake));
toTake-=1024;
取+=1024;
}
}
退货清单;
}
[]的

有轻微的扭曲。下面是一种将所有文档ID作为字符串列表获取的通用方法。请注意使用
Advanced.LuceneQuery(idPropertyName)
SelectFields(idPropertyName)
GetProperty(idPropertyName)
使事物变得通用。默认设置假定
“Id”
是给定
上的有效属性(99.999%的情况下应该是这样)。如果您有一些其他属性作为
Id
,您也可以将其传入

公共静态列表getAllID(DocumentStore docDB,字符串idPropertyName=“Id”){ 返回getAllidFrom(0,new List(),docDB,idPropertyName); } 公共静态列表getAllidFrom(int startFrom、列表列表、DocumentStore docDB、字符串idPropertyName){ var allUsers=列表; 使用(var session=docDB.OpenSession()) { int queryCount=0; int start=startFrom; while(true) { var current=session.Advanced.LuceneQuery().Take(1024).Skip(start).SelectFields(idPropertyName).ToList(); 查询计数+=1; 如果(current.Count==0) 打破 开始+=当前的计数; AddRange(current.Select(t=>(t.GetType().GetProperty(idPropertyName).GetValue(t,null)).ToString()); 如果(查询计数>=28) { 返回GetAllidFrom(start、allUsers、docDB、idPropertyName); } } } 回归诱惑; }
使用
BulkInsert
会话在RavenDb中发出
PatchRequest
时,我在何处/如何使用此选项的一个示例。在某些情况下,我可能有数十万个文档,无法在内存中加载所有文档,只是为了重新迭代它们以进行修补操作。。。因此,只需将其字符串ID加载到
Patch
命令中

void PatchRavenDocs()
{
    var store = new DocumentStore
    {
        Url = "http://localhost:8080",
        DefaultDatabase = "SoMeDaTaBaSeNaMe"
    };

    store.Initialize();

    // >>>here is where I get all the doc IDs for a given type<<<
    var allIds = getAllIds<SoMeDoCuMeNtTyPe>(store);    

    // create a new patch to ADD a new int property to my documents
    var patches = new[]{ new PatchRequest { Type = PatchCommandType.Set, Name = "SoMeNeWPrOpeRtY" ,Value = 0 }};

    using (var s = store.BulkInsert()){
        int cntr = 0;
        Console.WriteLine("ID Count " + allIds.Count);
        foreach(string id in allIds)
        {
            // apply the patch to my document
            s.DatabaseCommands.Patch(id, patches);

            // spit out a record every 2048 rows as a basic sanity check
            if ((cntr++ % 2048) == 0)
                Console.WriteLine(cntr + " " + id);
        }
    }
}
void PatchRavenDocs()
{
var存储=新文档存储
{
Url=”http://localhost:8080",
DefaultDatabase=“SoMeDaTaBaSeNaMe”
};
store.Initialize();

//>>>这里是我获取给定类型的所有文档ID的地方这个问题是在RavenDB中提供此功能之前发布的,但是如果其他人现在发现了这个问题

鼓励您这样做的方法是通过。RavenDB客户端对流进行批处理,以便自动“分页”服务器的请求/响应。如果您选择使用流API,则客户端会假定您“知道自己在做什么”,并且不会检查用于常规查询的128/1024/30限制

var query = session.Query<User>();
 
using (var enumerator = session.Advanced.Stream(query)) {
    while (enumerator.MoveNext()) {
        allUsers.Add(enumerator.Current.Document);
    }
}

var count = allUsers.Count;
var query=session.query();
 
使用(var枚举器=session.Advanced.Stream(查询)){
while(枚举数.MoveNext()){
添加(枚举器.Current.Document);
    }
}
var count=alluser.count;
提示:虽然这是解决问题的一种受鼓励的方法……但作为一般规则,最好从一开始就避免这种情况。如果有一百万条记录怎么办?那
alluser
列表将变得巨大。也许可以先进行索引或转换,以过滤出您实际需要向用户/进程显示的数据这是为了报告?也许RavenDB应该自动导出到
public List<string> GetAllIds<T>()
{
var allIds = new List<string>();
IDocumentSession session = null;

try
{
    session = documentStore.OpenSession();
    int queryCount = 0;
    int start = 0;
    while (true)
    {
        var current = session.Advanced.DocumentQuery<T>()
            .Take(1024)
            .Skip(start)
            .SelectFields<string>("__document_id")
            .AddOrder("__document_id")
            .ToList();

        if (current.Count == 0)
            break;
        allIds.AddRange(current);

        queryCount += 1;
        start += current.Count;

        if (queryCount == 30)
        {
            queryCount = 0;
            session.Dispose();
            session = documentStore.OpenSession();
        }
    }
}
finally
{
    if (session != null)
    {
        session.Dispose();
    }
}

return allIds;
}