我有以下测试:
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时。
有什么想法吗?
答案 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>
类只包含映射的结果,即TReduceResult
和Name
列。
然后,当您从中查询时,可以使用Popularity
从存储的索引结果中获取结果,而不是从文档存储中获取结果。