Raven以特定方式分页查询

时间:2015-06-26 14:10:10

标签: asp.net-mvc pagination ravendb

我正在使用RavenDB 3开发ASP.NET MVC应用程序。我没有很多关于乌鸦的经验。

通常,在执行查询以显示数据时,页面上会返回前128个项目。通过使用分页查询,在"无限滚动" -manner中添加更多记录。

但是,我现在要求将项目加载到'组中。

假设以下课程:

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件商品。这意味着最后一个小组'取得的不完整。它将缺少2个项目。

我想要一个能够意识到这一点的机制,这样它至少可以获取128并且会获取额外的'如果最后一组没有完全包括在内。

之后,当我获取下一页时,我希望它从下一组开始。

如果没有“制作”,我有什么方法可以完成这项工作。通过多次通话我自己一个页面?

编辑:我不能假设这些组的大小完全相同,但我可以假设大小将是' simular'

此外,我无法更改设计以将所有项目存储在单个“组”对象中。

1 个答案:

答案 0 :(得分:0)

好的,基本上你需要做的是计算前几页中的结果数和当前页面中的结果数。下面是一个快速示例应用程序,可以让您了解如何执行此操作。需要注意的是,如果当前组范围的结果数超过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; }
        }
    }
}