为什么我的索引中的Sum()不起作用?

时间:2014-06-15 13:56:13

标签: c# ravendb

我有以下测试:

public class ListingEventTest
{
    public ListingEventTest()
    {
        Artists = new List<ArtistTest>();
    }
    public List<ArtistTest> Artists { get; set; }
    public string Id { get; set; }
    public string Name { get; set; }
    public double Popularity { get; set; }
}

public class ArtistTest
{
    public string Id { get; set; }
    public Stat Stats { get; set; }
}

public class Stat
{
    public double Popularity { get; set; }
}


public class ArtistsWithStats_ByName : AbstractIndexCreationTask<ListingEventTest>
{
    public ArtistsWithStats_ByName()
    {
        Map = listingEvents => from listingEvent in listingEvents
                               let artists = LoadDocument<ArtistTest>(listingEvent.Artists.Select(x => x.Id))
                               select new
                               {
                                   Popularity = artists.Average(x => x.Stats.Popularity),
                                   listingEvent.Name
                               };
    }
}



[TestFixture]
public class IndexCanDoSums
{
    [Test]
    public async void WhenListingEventArtistsHaveStatsIndexReturnsPopularity()
    {
        var store = new EmbeddableDocumentStore
        {
            UseEmbeddedHttpServer = true,
            Configuration =
            {
                RunInUnreliableYetFastModeThatIsNotSuitableForProduction = true,
                RunInMemory = true,

            }
        }.Initialize();

        IndexCreation.CreateIndexes(typeof(ArtistsWithStats_ByName).Assembly, store);

        using (var session = store.OpenAsyncSession())
        {
            for (int i = 0; i < 10; i++)
            {
                var le = new ListingEventTest
                {
                    Name = "test-" + i
                };

                await session.StoreAsync(le);

                for (int j = 0; j < 2; j++)
                {
                    var artist = new ArtistTest
                    {
                        Stats = new Stat
                        {
                            Popularity = 0.89d
                        }
                    };

                    await session.StoreAsync(artist);

                    le.Artists.Add(artist);
                }

                await session.SaveChangesAsync();
            }
        }

        Thread.Sleep(2000);

        using (var session = store.OpenAsyncSession())
        {
             var query = session
            .Advanced.AsyncLuceneQuery<ListingEventTest>("ArtistsWithStats/ByName");

            var result = await query.ToListAsync();

            result.First().Popularity.Should().NotBe(0);
        }
    }
}

当我查询此索引Popularity始终为0时。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

这里发生了一些有趣的事情。

首先,您将在ArtistEventTest文档下存储ArtistTest,而不是作为单独的文档存储,因此在索引中无需调用LoadDocument,您可以这样做:

from listingEvent in listingEvents
from artist in listingEvent.Artists
select ...

其次,Map-only索引很像一个SQL索引,你只需要调用你想要查询的列。在这里,您正在对一组隐藏属性进行计算,并且您有一个顶级属性,您希望存储该信息,但最终如何工作是您的计算属性值进入Lucene索引(所以你如果你愿意,可以按人气查询,但返回的数据是直接来自未改变的文件。地图定义了Lucene中指向文档ID的内容,然后文档存储将文档作为结果返回。

这可以通过在索引的构造函数中调用Store(x => x.Popularity)来修改,这将存储稍后要调用的值,但老实说,我不确定你的计算值或文档的值(即零) )会赢。

鉴于此,拥有一个文档属性变得非常混乱,其唯一目的是在索引期间尝试填充它,这就是为什么拥有一个表示映射状态的类通常是更好的选择,然后实现{{ 1}} AbstractIndexCreationTask<TDocument, TReduceResult>类只包含映射的结果,即TReduceResultName列。

然后,当您从中查询时,可以使用Popularity从存储的索引结果中获取结果,而不是从文档存储中获取结果。