2012-12-05 51 views
1

鑑於這樣的模式:如何按RavenDB中的嵌套兒童的財產的平均聚合來訂購文檔?

public class Location 
{ 
    public int Id { get; set; } 

    public string Name { get; set; } 

    public Coordinates Geo { get; set; } 

    public IList<Review> Reviews { get; set; } 
} 

public class Review 
{ 
    public string Comment { get; set; } 

    public int Rating { get; set; } 
} 

我如何編寫一個查詢,將返回匹配由他們的評分降序排序的位置嗎?

我,讓我身邊一個GeoPoint一定半徑內的查詢位置的索引:

public class Locations_ByCoordinates : AbstractIndexCreationTask<Location> 
{ 
    public Locations_ByCoordinates() 
    { 
     Map = locations => from l in locations 
          select new {_ = SpatialIndex.Generate(l.Geo.Lat, l.Geo.Lon)}; 
    } 
} 

這似乎是工作,我能夠到的結果,像這樣排序:

RavenQueryStatistics stats; 
var query = session.Advanced.LuceneQuery<Location>(Names.Indexes.LocationsByCoordinates) 
         .Statistics(out stats) 
         .WithinRadiusOf(radius, coordinates.Lat, coordinates.Lon); 

switch (sort) 
{ 
    case Sort.Distance: 
     query = query.SortByDistance(); 
     break; 
    case Sort.Rating: 
     query = query.AddOrder(l => l.Reviews.Average(r => r.Rating), true); // TODO: This throws an exception, perhaps a modified index with an aggregate is required? Maybe Map/Reduce? 
     break; 
    case Sort.Alphabetical: 
     query = query.OrderBy(l => l.Name); 
     break; 
    case Sort.Number_of_ratings: 
     query = query.AddOrder(l => l.Reviews.Count, true); 
     break; 
    case Sort.Relevance: // This is the default ordering in RavenDB. 
     break; 
    default: 
     throw new ArgumentOutOfRangeException("sort"); 
} 

除了根據未知字段拋出異常的平均評分排序,每個選項都可以正常工作。我覺得這必須是Map/Reduce索引而不是Map索引。但我不知道如何寫它。

我正在從MongoDB遷移此代碼,但我曾經在客戶端按評分對文檔進行排序,我想我現在會在服務器端執行此操作。

回答

2

由於所有評論都位於此位置,並且您希望每個位置的評論的平均評分不需要降低。只需在您的地圖中創建一個新字段。

Map = locations => from l in locations 
        select new { 
         _ = SpatialIndex.Generate(l.Geo.Lat, l.Geo.Lon), 
         AvgRating = l.Reviews.Average(r => r.Rating) 
        }; 
+0

這就是我不明白:),我一直以爲返回地圖的東西。如何使用AvgRating字段對結果進行排序?我是否需要將AvgRating屬性添加到Location類或什麼? –

+0

地圖只是控制獲得索引的東西,即可以搜索和排序的字段。默認情況下,RavenDB將始終返回與查詢匹配的完整文檔。 –

+0

我在理論上知道很多,但不知道如何在實踐中應用。 :)我改變了在我的'開關'塊的評級排序: 'query = query.AddOrder(「AvgRating」,true);' 它現在不會拋出錯誤,但它也排除沒有任何評論的地點。我仍然希望看到它們的評級爲0. 更改爲: AvgRating = l.Reviews.Count> 0? l.Reviews.Average(r => r.Rating):0' 現在效果很好。但我仍然想要做魔法,不完全理解正在發生的事情,那很糟糕。 :( –