27

我知道这个问题的变体已经被问过(甚至是我),但我仍然不明白关于这个的一两件事......

据我了解,这样做可以检索比 128 默认设置更多的文档:

session.Advanced.MaxNumberOfRequestsPerSession = int.MaxValue;

而且我了解到 WHERE 子句应该是 ExpressionTree 而不是 Func,因此它被视为 Queryable 而不是 Enumerable。所以我认为这应该有效:

public static List<T> GetObjectList<T>(Expression<Func<T, bool>> whereClause)
{
    using (IDocumentSession session = GetRavenSession())
    {
        return session.Query<T>().Where(whereClause).ToList();                
    }
}

但是,这只返回 128 个文档。为什么?

注意,这里是调用上述方法的代码:

RavenDataAccessComponent.GetObjectList<Ccm>(x => x.TimeStamp > lastReadTime);

如果我添加 Take(n),那么我可以得到尽可能多的文档。例如,这将返回 200 个文档:

return session.Query<T>().Where(whereClause).Take(200).ToList();

基于所有这些,似乎检索数千个文档的适当方法是设置 MaxNumberOfRequestsPerSession 并在查询中使用 Take()。是对的吗?如果没有,应该怎么做?

对于我的应用程序,我需要检索数千个文档(其中的数据非常少)。我们将这些文档保存在内存中并用作图表的数据源。

** 编辑 **

我尝试在我的 Take() 中使用 int.MaxValue:

return session.Query<T>().Where(whereClause).Take(int.MaxValue).ToList();

然后返回 1024。啊。我如何获得超过 1024?

** 编辑 2 - 显示数据的示例文档 **

{
  "Header_ID": 3525880,
  "Sub_ID": "120403261139",
  "TimeStamp": "2012-04-05T15:14:13.9870000",
  "Equipment_ID": "PBG11A-CCM",
  "AverageAbsorber1": "284.451",
  "AverageAbsorber2": "108.442",
  "AverageAbsorber3": "886.523",
  "AverageAbsorber4": "176.773"
}
4

5 回答 5

37

值得注意的是,从 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;
    }
}

支持标准 RavenDB 查询、Lucence 查询,还支持异步。

文档可以在这里找到。可以在此处找到 Ayende 的介绍性博客文章。

于 2013-11-27T09:10:30.123 回答
25

默认情况下,该Take(n)功能最多只能为您提供 1024。但是,您可以在以下位置更改此默认值Raven.Server.exe.config

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

有关详细信息,请参阅:http ://ravendb.net/docs/intro/safe-by-default

于 2012-04-06T21:02:43.690 回答
16

默认情况下,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;

RavenDB 分页

于 2012-07-16T20:58:14.273 回答
5

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

如果您从商店中获得超过 10 个任何东西(甚至少于默认 128 个)供人类消费,那么就出现了问题,或者您的问题需要不同的想法,然后从数据存储中加载卡车装载的文档。

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

如果您需要执行数据聚合,请创建生成聚合数据的 map/reduce 索引,例如:

指数:

    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)();
于 2012-04-07T00:55:09.800 回答
1

您还可以在该方法中使用预定义的索引Stream。您可以在索引字段上使用 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
    }
}

示例索引:

public class MyUserIndex: AbstractIndexCreationTask<User>
{
    public MyUserIndex()
    {
        this.Map = users =>
            from u in users
            select new
            {
                u.IsDeleted,
                u.Username,
            };
    }
}

文档:什么是索引? 会话:查询:如何流式传输查询结果?


重要提示:该Stream方法不会跟踪对象。如果改变从这个方法获得的对象,SaveChanges()将不会察觉到任何改变。


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

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

于 2016-03-09T18:40:03.380 回答