Подтвердить что ты не робот

Правильный способ получения более 128 документов с помощью RavenDB

Я знаю, что варианты этого вопроса задавались раньше (даже мной), но я до сих пор ничего не понимаю об этом...

Насколько я понял, можно было получить больше документов, чем значение по умолчанию 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() в запросе. Это правильно? Если нет, то как следует сделать это?

Для моего приложения мне нужно получить тысячи документов (в них очень мало данных). Мы сохраняем эти документы в памяти и используются в качестве источника данных для диаграмм.

** РЕДАКТИРОВАТЬ **

Я попробовал использовать int.MaxValue в своем методе Take():

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

И это возвращает 1024. Argh. Как получить более 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"
}
4b9b3361

Ответ 1

Функция Take(n) предоставит вам до 1024 по умолчанию. Однако вы можете изменить это значение по умолчанию в Raven.Server.exe.config:

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

Для получения дополнительной информации см. http://ravendb.net/docs/intro/safe-by-default

Ответ 2

Стоит отметить, что с версии 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, а также поддержка async.

Документацию можно найти здесь. Вводную статью в блоге Айенде можно найти здесь.

Ответ 3

Функция 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 Paging

Ответ 4

Число запросов на сеанс - это отдельная концепция, а затем количество документов, полученных за каждый вызов. Сеансы недолговечны, и ожидается, что их вызовет несколько звонков.

Если вы получаете более 10 предметов из магазина (даже меньше, чем по умолчанию 128) для потребления человеком, то что-то не так, или ваша проблема требует другого мышления, а затем загрузки грузовика документов, поступающих из хранилища данных.

Индексирование RavenDB довольно сложно. Хорошая статья об индексировании здесь и facets здесь.

Если вам необходимо выполнить агрегацию данных, создайте индекс 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)
    }

Query:

session.Query<AuthorPostStats>("Posts/ByUser/Count")(x=>x.Author)();

Ответ 5

Вы также можете использовать предопределенный индекс с помощью метода 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().