使用RavenDB检索128多个文档的正确方法

使用RavenDB检索128多个文档的正确方法,ravendb,Ravendb,我知道以前有人问过这个问题(甚至是我),但我还是不明白其中的一两件事 我的理解是,通过执行以下操作,可以检索到比128默认设置更多的文档: session.Advanced.MaxNumberOfRequestsPerSession = int.MaxValue; 我已经了解到WHERE子句应该是ExpressionTree而不是Func,因此它被视为可查询的,而不是可枚举的。所以我觉得这应该行得通: public static List<T> GetObjectList<T

我知道以前有人问过这个问题(甚至是我),但我还是不明白其中的一两件事

我的理解是,通过执行以下操作,可以检索到比128默认设置更多的文档:

session.Advanced.MaxNumberOfRequestsPerSession = int.MaxValue;
我已经了解到WHERE子句应该是ExpressionTree而不是Func,因此它被视为可查询的,而不是可枚举的。所以我觉得这应该行得通:

public static List<T> GetObjectList<T>(Expression<Func<T, bool>> whereClause)
{
    using (IDocumentSession session = GetRavenSession())
    {
        return session.Query<T>().Where(whereClause).ToList();                
    }
}
默认情况下,
Take(n)
函数最多只能提供1024个字符。但是,您可以在
Raven.Server.exe.config
中更改此默认值:

<add key="Raven/MaxPageSize" value="5000"/>

每个会话的请求数是一个单独的概念,然后是每个调用检索的文档数。会话的寿命很短,预计通过会话发出的呼叫很少

如果您从存储中获取的任何内容超过10个(甚至少于默认值128个)供人类使用,则可能是出了问题,或者您的问题需要不同的思考,然后从数据存储中装载文档

RavenDB索引非常复杂。关于索引和方面的好文章

如果需要执行数据聚合,请创建映射/减少索引,以生成聚合数据,例如:

索引:

    from post in docs.Posts
    select new { post.Author, Count = 1 }

    from result in results
    group result by result.Author into g
    select new
    {
       Author = g.Key,
       Count = g.Sum(x=>x.Count)
    }
查询:

session.Query<AuthorPostStats>("Posts/ByUser/Count")(x=>x.Author)();
session.Query(“Posts/ByUser/Count”)(x=>x.Author)();
默认情况下,Take(n)函数最多只能提供1024个。但是,您可以将其与Skip(n)成对使用,以获得全部

        var points = new List<T>();
        var nextGroupOfPoints = new List<T>();
        const int ElementTakeCount = 1024;
        int i = 0;
        int skipResults = 0;

        do
        {
            nextGroupOfPoints = session.Query<T>().Statistics(out stats).Where(whereClause).Skip(i * ElementTakeCount + skipResults).Take(ElementTakeCount).ToList();
            i++;
            skipResults += stats.SkippedResults;

            points = points.Concat(nextGroupOfPoints).ToList();
        }
        while (nextGroupOfPoints.Count == ElementTakeCount);

        return points;
var points=新列表();
var nextGroupOfPoints=新列表();
常量int ElementTakeCount=1024;
int i=0;
int-skippresults=0;
做
{
nextGroupOfPoints=session.Query().Statistics(out stats).Where(Where子句).Skip(i*ElementTakeCount+skippresults).Take(ElementTakeCount).ToList();
i++;
SkipPresults+=统计数据SkippedResults;
points=points.Concat(nextGroupOfPoints.ToList();
}
while(nextGroupOfPoints.Count==ElementTakeCount);
返回点;

值得注意的是,自2.5版以来,RavenDB有一个“无限结果API”来允许流媒体。文档中的示例显示了如何使用此选项:

var query = session.Query<User>("Users/ByActive").Where(x => x.Active);
using (var enumerator = session.Advanced.Stream(query))
{
    while (enumerator.MoveNext())
    {
        User activeUser = enumerator.Current.Document;
    }
}
var query=session.query(“Users/ByActive”)。其中(x=>x.Active);
使用(var枚举器=session.Advanced.Stream(查询))
{
while(枚举数.MoveNext())
{
User activeUser=enumerator.Current.Document;
}
}
它支持标准的RavenDB查询、Lucence查询以及异步支持


可以找到文档。可以找到Ayende的介绍性博客文章。

您还可以通过
方法使用预定义的索引。可以对索引字段使用Where子句

var query = session.Query<User, MyUserIndex>();
var query = session.Query<User, MyUserIndex>().Where(x => !x.IsDeleted);

using (var enumerator = session.Advanced.Stream<User>(query))
{
    while (enumerator.MoveNext())
    {
        var user = enumerator.Current.Document;
        // do something
    }
}
var query=session.query();
var query=session.query()。其中(x=>!x.IsDeleted);
使用(var枚举器=session.Advanced.Stream(查询))
{
while(枚举数.MoveNext())
{
var user=enumerator.Current.Document;
//做点什么
}
}
示例索引:

public class MyUserIndex: AbstractIndexCreationTask<User>
{
    public MyUserIndex()
    {
        this.Map = users =>
            from u in users
            select new
            {
                u.IsDeleted,
                u.Username,
            };
    }
}
公共类MyUserIndex:AbstractIndexCreationTask
{
公共MyUserIndex()
{
this.Map=users=>
来自用户中的u
选择新的
{
u、 被删除,
u、 用户名,
};
}
}
文件:


重要提示:
Stream
方法不会跟踪对象。如果更改从该方法获得的对象,
SaveChanges()
将不会意识到任何更改


其他注意事项:如果未指定要使用的索引,则可能会出现以下异常

InvalidOperationException:StreamQuery不支持查询动态索引。它设计用于大型数据集,不太可能像Query()那样在索引15秒后返回所有数据集


谢谢,迈克。我认为这最终会成为公认的答案,但我想先看看是否有其他人对此有不同的看法。那么,你将如何解决这个问题?企业希望看到一张图表,显示过去24小时的数据点价值。每个文档都是一个数据点,在过去24小时内有10000个文档。如何在不包含所有数据的情况下绘制图表?我认为您可以通过创建索引来实现这一点,或者我刚刚注意到“每个文档都是一个数据点”-您可以展示一个此文档的示例吗?实际上更准确的说法是,每个文档包含一个或多个图表的一个或多个数据点。我编辑了上面的问题,以显示带有数据点的示例文档。另外,谢谢你的帮助。我不熟悉面。我得去看看。最后,我认为聚合数据不起作用,因为该图表单独绘制了每个数据点。我还没有看到过包含10000个数据点的图表,如果由人类查看(但奇怪的事情存在)会有任何意义。一个想法是降低粒度。您可以创建一组文档,这些文档表示24小时内的聚合数据,例如快照每小时。如果业务部门想要深入挖掘,那么打开所有水龙头,带上卡车:)您是否想过将所有10000点作为一个集合放在一个文档中?这种方法是更好的方法。请注意服务器请求数量的限制。根据Raven的“默认安全”设置,它最多只能往返服务器30次,因此如果循环需要执行的次数超过30次,它将失败,因为循环的每次迭代都是另一个服务器请求。请注意,使用流式API进行查询时,索引必须已经存在。如果通过普通会话API运行查询,但不存在匹配索引,则将创建动态索引。但是在流式API中,动态索引没有创建,服务器抱怨没有找到索引。Mike-这是一个有趣的行为,听起来像个bug。
        var points = new List<T>();
        var nextGroupOfPoints = new List<T>();
        const int ElementTakeCount = 1024;
        int i = 0;
        int skipResults = 0;

        do
        {
            nextGroupOfPoints = session.Query<T>().Statistics(out stats).Where(whereClause).Skip(i * ElementTakeCount + skipResults).Take(ElementTakeCount).ToList();
            i++;
            skipResults += stats.SkippedResults;

            points = points.Concat(nextGroupOfPoints).ToList();
        }
        while (nextGroupOfPoints.Count == ElementTakeCount);

        return points;
var query = session.Query<User>("Users/ByActive").Where(x => x.Active);
using (var enumerator = session.Advanced.Stream(query))
{
    while (enumerator.MoveNext())
    {
        User activeUser = enumerator.Current.Document;
    }
}
var query = session.Query<User, MyUserIndex>();
var query = session.Query<User, MyUserIndex>().Where(x => !x.IsDeleted);

using (var enumerator = session.Advanced.Stream<User>(query))
{
    while (enumerator.MoveNext())
    {
        var user = enumerator.Current.Document;
        // do something
    }
}
public class MyUserIndex: AbstractIndexCreationTask<User>
{
    public MyUserIndex()
    {
        this.Map = users =>
            from u in users
            select new
            {
                u.IsDeleted,
                u.Username,
            };
    }
}