0

与此问题相关:RavenDB Get By List of IDs? 我所拥有的不起作用:

public class Entity
{
    public int CategoryId; //Unique identifier for the category the price applies to.
    public int Price; //Changes with time
    public DateTime Timestamp; //DateTime.UtcNow
}
public class LastEntityIndex : AbstractIndexCreationTask<Entity, Entity>
{
    public LastEntityIndex()
    {
        Map = prices => prices.Select(a => new { a.CategoryId, a.Price, a.Timestamp });

        Reduce = prices => from price in prices
                           group price by price.CategoryId
                                 into g
                                 let a = g.OrderByDescending(a => a.Timestamp).FirstOrDefault()
                                 select new
                                 {
                                     a.CategoryId,
                                     a.Price,
                                     a.Timestamp
                                 };
    }
}
public class LastEntity
{
    public int CategoryId;
    public DateTime Timestamp;
    public Entity LastEntity;
}
public class LastReportIndex : AbstractIndexCreationTask<Entity, LastEntity>
{
    public LastReportIndex()
    {
        Map = reports => reports.Select(a => new { a.CategoryId, a.Timestamp, LastEntity = a });

        Reduce = reports => from report in reports
                            group report by report.CategoryId
                                into g
                                let a = g.OrderByDescending(a => a.Timestamp).FirstOrDefault()
                                select new
                                {
                                    a.CategoryId,
                                    a.Timestamp,
                                    a.LastEntity
                                };
    }
}

我想创建一个索引来获取每个类别的最新记录。但以上都不起作用。非常感谢任何帮助。为这个新项目离开 sql 并评估 Raven。到目前为止,它似乎非常强大并且可以满足我们的需要,但是从 sql dbs 转变范式很难。

非常感谢你。

PS 使用它来检索记录:

public List<Entity> GetLastEntityForCategoryIds(List<int> categoryIds)
    {
        using (var session = _documentStore.OpenSession())
        {
            return session.Query<LastEntity, LastReportIndex>()
                                    .Where(x => x.CategoryId.In(categoryIds))
                                    .Select(a => a.LastEntity)
                                    .ToList();
        }
    }

显然,“LastEntityIndex”不是我长期使用的东西(它只是为了尝试看看它是否有效),因为真正的实体有更多的字段,只有 3 个,并且将它们全部复制并维护它会非常困难.

4

2 回答 2

1

您是正确的,您必须选择整个文档,而不是文档的一部分。默认情况下,查询返回整个文档。

如果您只想返回文档的一部分,则必须使用projectionstransformers,或者像您所做的那样获取整个内容,然后取出您想要的部分。

但是,您正在做很多我认为不必要的事情。例如,您在 reduce 中订购并获取单个项目。这不是索引的一个很好的用途。您可能应该只有一个简单的地图并按您的查询进行排序。

请参阅此 GIST并阅读我的评论。那里还评论了其他一些内容。

也为你喝彩!

于 2013-11-05T05:46:27.403 回答
0

是的,我知道发生了什么。如果我对 Mapped/Reduced 查询执行 .Select,则返回默认值。如果我这样做 .ToList().Select 或 Single() 等,我会得到正确的结果。

这是我设置的一个单元测试来演示我在说什么。

using Raven.Client.Indexes;
using Raven.Tests.Helpers;
using System;
using System.Linq;
using Xunit; //XUnit
//using Microsoft.VisualStudio.TestTools.UnitTesting; //MSTest

namespace RavenDBTest.Tests
{
    //[TestClass] //MSTest
    public class RavenIndexTest : RavenTestBase
    {
        //[TestMethod] //MSTest
        [Fact] //XUnit
        public void CanIndexAndQuery()
        {
            var timestamp = DateTime.Now;
            var report1 = new Entity { CategoryId = 123, Price = 51, Timestamp = timestamp.AddSeconds(-20) };
            var report2 = new Entity { CategoryId = 123, Price = 62, Timestamp = timestamp.AddSeconds(-10) };
            var report3 = new Entity { CategoryId = 123, Price = 73, Timestamp = timestamp };

            using (var store = NewDocumentStore())
            {
                new LatestEntity_Index().Execute(store);

                using (var session = store.OpenSession())
                {
                    session.Store(report1);
                    session.Store(report2);
                    session.Store(report3);

                    session.SaveChanges();
                }

                //WILL PASS
                using (var session = store.OpenSession())
                {
                    var result = session.Query<LastEntity, LatestEntity_Index>()
                        .Customize(customization => customization.WaitForNonStaleResultsAsOfNow())
                        .FirstOrDefault()
                        .LastReport;

                    AssertLatestResult(timestamp, result);
                }

                //WILL FAIL
                using (var session = store.OpenSession())
                {
                    var result = session.Query<LastEntity, LatestEntity_Index>()
                        .Customize(customization => customization.WaitForNonStaleResultsAsOfNow())
                        .Select(a => a.LastReport)
                        .FirstOrDefault();

                    AssertLatestResult(timestamp, result);
                }
            }
        }

        private static void AssertLatestResult(DateTime timestamp, Entity result)
        {
            //MSTest:
            //Assert.AreEqual(123, result.CategoryId, "Category Does Not Match");
            //Assert.AreEqual(73, result.Price, "Latest Price Does Not Match");
            //Assert.AreEqual(timestamp, result.Timestamp, "Latest Timestamp Does Not Match");

            //XUnit:
            Assert.Equal(123, result.CategoryId);
            Assert.Equal(73, result.Price);
            Assert.Equal(timestamp, result.Timestamp);
        }
    }

    public class Entity
    {
        public int CategoryId {get;set;} //Unique identifier for the category the price applies to.
        public int Price {get;set;} //Changes with time
        public DateTime Timestamp {get;set;} //DateTime.UtcNow
    }

    public class LastEntity
    {
        public int CategoryId { get; set; }
        public DateTime Timestamp { get; set; }
        public Entity LastReport { get; set; }
    }

    public class LatestEntity_Index : AbstractIndexCreationTask<Entity, LastEntity>
    {
        public LatestEntity_Index()
        {
            Map = reports => from report in reports
                             select new LastEntity
                             {
                                 CategoryId = report.CategoryId,
                                 Timestamp = report.Timestamp,
                                 LastReport = report,
                             };

            Reduce = reports => from report in reports
                                group report by report.CategoryId
                                    into g
                                    let last = g.OrderBy(a=>a.Timestamp).Last()
                                    select new LastEntity
                                    {
                                        CategoryId = g.Key,
                                        Timestamp = last.Timestamp,
                                        LastReport = last.LastReport,
                                    };
        }
    }
}

我希望这可以帮助别人。

@Matt Johnson,这些索引的效率/糟糕程度如何?性能明智?和空间明智?顺便为你的帮助干杯。:)

于 2013-11-05T02:24:35.440 回答