Raven 以特定方式进行分页查询
Raven paging queries in a specific way
我正在使用 RavenDB 3 开发 ASP.NET MVC 应用程序。我对 raven 没有太多经验。
一般情况下,执行查询显示数据时,页面返回前128条。使用分页查询以 "infinite scroll" 方式添加更多记录。
但是,现在我要求在 'groups' 中加载项目。
假设以下 class:
public class Item {
public string Id { get; set; }
public int Group { get; set; }
public string text { get; set; }
}
假设数据库包含 40 个组=“1”的项目、40 个组=“2”的项目和 50 个组=“3”的项目。
共有 130 项。这意味着最后获取的 'group' 将不完整。它将缺少 2 个项目。
我想要一种能够识别这一点的机制,这样它至少可以获取 128 并且如果最后一组未完全包含则可以获取 'extra'。
然后,当我获取下一页时,我希望它从下一组开始。
有什么方法可以让我自己通过多次调用在 'fabricating' 一个页面的情况下完成这项工作吗?
编辑:我不能假设这些组的大小完全相等,但我可以假设大小将是 'simular'
此外,我无法更改设计以将所有项目存储在一个 'group' 对象中。
好的,基本上您需要做的是计算前几页中的结果数和当前页中的结果数。下面是一个快速示例应用程序,可让您了解如何执行此操作。需要注意的是,如果当前组范围的结果数量超过 MaxNumberOfRequestsPerSession
,则会抛出错误,因此您可能需要为此进行一些处理。
运行 这个例子的注意事项:
如果您使用的是最新版本的 RavenDB,请确保您的平台在 visual studio 中设置为 x64。否则,此示例将抛出有关 Voron 在 32 位模式下不稳定的错误。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Raven.Client;
using Raven.Client.Embedded;
using Raven.Client.Listeners;
namespace ConsoleApplication
{
internal class Program
{
private static void Main(string[] args)
{
using (var gdm = new GroupDataManager())
{
Console.WriteLine("Started Seeding");
gdm.Seed().Wait();
Console.WriteLine("Finished Seeding");
Console.WriteLine("===============================================================");
Console.WriteLine("Get First Page");
Console.WriteLine("===============================================================");
var firstPage = gdm.GetPagedGroupResults(1, 3).Result;
foreach (var item in firstPage)
{
Console.WriteLine(item.Text);
}
Console.WriteLine("===============================================================");
Console.WriteLine("Get Second Page");
Console.WriteLine("===============================================================");
var secondPage = gdm.GetPagedGroupResults(2, 3).Result;
foreach (var item in secondPage)
{
Console.WriteLine(item.Text);
}
}
Console.ReadLine();
}
}
public class GroupDataManager : IDisposable
{
private readonly IDocumentStore _documentStore = new EmbeddedRavenDatabase().Store;
public void Dispose()
{
_documentStore.Dispose();
}
public async Task Seed()
{
var rnd = new Random();
using (var session = _documentStore.OpenAsyncSession())
{
for (var groupNumber = 1; groupNumber < 15; groupNumber++)
{
for (var i = 0; i < rnd.Next(5, 25); i++)
{
var item = new Item
{
Group = groupNumber,
Text = string.Format("Group: {0} Item:{1}", groupNumber, i)
};
await session.StoreAsync(item);
}
}
await session.SaveChangesAsync();
}
}
public async Task<IList<Item>> GetPagedGroupResults(int page, int numberOfGroupsPerPage)
{
var startingGroup = ((page - 1) * numberOfGroupsPerPage) + 1;
using (var session = _documentStore.OpenAsyncSession())
{
// Calculate the number of items that were contained in the previous groups
var numberToSkip = await session.Query<Item>().CountAsync(item => item.Group < startingGroup);
var endGroup = startingGroup + numberOfGroupsPerPage;
// Calculate the number of items that are in the current range of groups
var numberToTake = await session.Query<Item>().CountAsync(item => item.Group >= startingGroup && item.Group < endGroup);
var results = await session.Query<Item>().Skip(numberToSkip).Take(numberToTake).ToListAsync();
return results;
}
}
}
public class Item
{
public string Id { get; set; }
public int Group { get; set; }
public string Text { get; set; }
}
/// <summary>
/// For Testing Only. Prevents stale queries
/// </summary>
public class NoStaleQueriesAllowed : IDocumentQueryListener
{
public void BeforeQueryExecuted(IDocumentQueryCustomization queryCustomization)
{
queryCustomization.WaitForNonStaleResults();
}
}
public class EmbeddedRavenDatabase
{
private static bool _configured = false;
private static readonly Lazy<IDocumentStore> _lazyDocStore = new Lazy<IDocumentStore>(() =>
{
var docStore = new EmbeddableDocumentStore
{
RunInMemory = true
};
docStore.RegisterListener(new NoStaleQueriesAllowed());
docStore.Initialize();
return docStore;
});
public IDocumentStore Store
{
get { return _lazyDocStore.Value; }
}
}
}
我正在使用 RavenDB 3 开发 ASP.NET MVC 应用程序。我对 raven 没有太多经验。
一般情况下,执行查询显示数据时,页面返回前128条。使用分页查询以 "infinite scroll" 方式添加更多记录。
但是,现在我要求在 'groups' 中加载项目。
假设以下 class:
public class Item {
public string Id { get; set; }
public int Group { get; set; }
public string text { get; set; }
}
假设数据库包含 40 个组=“1”的项目、40 个组=“2”的项目和 50 个组=“3”的项目。
共有 130 项。这意味着最后获取的 'group' 将不完整。它将缺少 2 个项目。
我想要一种能够识别这一点的机制,这样它至少可以获取 128 并且如果最后一组未完全包含则可以获取 'extra'。
然后,当我获取下一页时,我希望它从下一组开始。
有什么方法可以让我自己通过多次调用在 'fabricating' 一个页面的情况下完成这项工作吗?
编辑:我不能假设这些组的大小完全相等,但我可以假设大小将是 'simular'
此外,我无法更改设计以将所有项目存储在一个 'group' 对象中。
好的,基本上您需要做的是计算前几页中的结果数和当前页中的结果数。下面是一个快速示例应用程序,可让您了解如何执行此操作。需要注意的是,如果当前组范围的结果数量超过 MaxNumberOfRequestsPerSession
,则会抛出错误,因此您可能需要为此进行一些处理。
运行 这个例子的注意事项: 如果您使用的是最新版本的 RavenDB,请确保您的平台在 visual studio 中设置为 x64。否则,此示例将抛出有关 Voron 在 32 位模式下不稳定的错误。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Raven.Client;
using Raven.Client.Embedded;
using Raven.Client.Listeners;
namespace ConsoleApplication
{
internal class Program
{
private static void Main(string[] args)
{
using (var gdm = new GroupDataManager())
{
Console.WriteLine("Started Seeding");
gdm.Seed().Wait();
Console.WriteLine("Finished Seeding");
Console.WriteLine("===============================================================");
Console.WriteLine("Get First Page");
Console.WriteLine("===============================================================");
var firstPage = gdm.GetPagedGroupResults(1, 3).Result;
foreach (var item in firstPage)
{
Console.WriteLine(item.Text);
}
Console.WriteLine("===============================================================");
Console.WriteLine("Get Second Page");
Console.WriteLine("===============================================================");
var secondPage = gdm.GetPagedGroupResults(2, 3).Result;
foreach (var item in secondPage)
{
Console.WriteLine(item.Text);
}
}
Console.ReadLine();
}
}
public class GroupDataManager : IDisposable
{
private readonly IDocumentStore _documentStore = new EmbeddedRavenDatabase().Store;
public void Dispose()
{
_documentStore.Dispose();
}
public async Task Seed()
{
var rnd = new Random();
using (var session = _documentStore.OpenAsyncSession())
{
for (var groupNumber = 1; groupNumber < 15; groupNumber++)
{
for (var i = 0; i < rnd.Next(5, 25); i++)
{
var item = new Item
{
Group = groupNumber,
Text = string.Format("Group: {0} Item:{1}", groupNumber, i)
};
await session.StoreAsync(item);
}
}
await session.SaveChangesAsync();
}
}
public async Task<IList<Item>> GetPagedGroupResults(int page, int numberOfGroupsPerPage)
{
var startingGroup = ((page - 1) * numberOfGroupsPerPage) + 1;
using (var session = _documentStore.OpenAsyncSession())
{
// Calculate the number of items that were contained in the previous groups
var numberToSkip = await session.Query<Item>().CountAsync(item => item.Group < startingGroup);
var endGroup = startingGroup + numberOfGroupsPerPage;
// Calculate the number of items that are in the current range of groups
var numberToTake = await session.Query<Item>().CountAsync(item => item.Group >= startingGroup && item.Group < endGroup);
var results = await session.Query<Item>().Skip(numberToSkip).Take(numberToTake).ToListAsync();
return results;
}
}
}
public class Item
{
public string Id { get; set; }
public int Group { get; set; }
public string Text { get; set; }
}
/// <summary>
/// For Testing Only. Prevents stale queries
/// </summary>
public class NoStaleQueriesAllowed : IDocumentQueryListener
{
public void BeforeQueryExecuted(IDocumentQueryCustomization queryCustomization)
{
queryCustomization.WaitForNonStaleResults();
}
}
public class EmbeddedRavenDatabase
{
private static bool _configured = false;
private static readonly Lazy<IDocumentStore> _lazyDocStore = new Lazy<IDocumentStore>(() =>
{
var docStore = new EmbeddableDocumentStore
{
RunInMemory = true
};
docStore.RegisterListener(new NoStaleQueriesAllowed());
docStore.Initialize();
return docStore;
});
public IDocumentStore Store
{
get { return _lazyDocStore.Value; }
}
}
}