這是this問題概述的項目的延續。查詢產品目錄RavenDB專門針對任意集合產品的規格彙總
我有以下模式:
class Product {
public string Id { get; set; }
public string[] Specs { get; set; }
public int CategoryId { get; set; }
}
的「規格」數組存儲產品規格名稱值由一個特殊的字符加入對。例如,如果產品是藍色的,則規格字符串將是「顏色〜藍色」。以這種方式表示規格允許查詢具有由查詢指定的多個規格值的產品。我希望支持兩種主要查詢:
- 獲取給定類別中的所有產品。
- 獲取給定類別中具有一組指定規格的所有產品。
這適用於RavenDB。但是,除了滿足給定查詢的產品外,我還希望返回一個結果集,其中包含查詢指定的產品組的所有規格名稱 - 值對。規格名稱 - 值對應按規格的名稱和值進行分組,幷包含具有給定規格名稱 - 值對的產品的計數。對於查詢#1我創建了下面的地圖減少指數:
class CategorySpecGroups {
public int CategoryId { get; set; }
public string Spec { get; set; }
public int Count { get; set; }
}
public class SpecGroups_ByCategoryId : AbstractIndexCreationTask<Product, CategorySpecGroups>
{
public SpecGroups_ByCategoryId()
{
this.Map = products => from product in products
where product.Specs != null
from spec in product.Specs
select new
{
CategoryId = product.CategoryId,
Spec = spec,
Count = 1
};
this.Reduce = results => from result in results
group result by new { result.CategoryId, result.Spec } into g
select new
{
CategoryId = g.Key.CategoryId,
Spec = g.Key.Spec,
Count = g.Sum(x => x.Count)
};
}
}
然後我就可以查詢該索引,並得到所有規格名稱 - 值對給定類別。我遇到的問題是獲得相同的結果集,但對於通過類別和一組規格名稱 - 值對進行篩選的查詢。使用SQL時,通過按類別和規格過濾的一組產品進行分組可獲得此結果集。一般來說,這種類型的查詢很昂貴,但是當按照類別和規格進行過濾時,產品集通常很小,但不足以放入單個頁面 - 它們可能包含多達1000種產品。作爲參考,MongoDB支持可用於實現相同結果集的group方法。這將執行ad hoc分組服務器端,性能是可以接受的。
如何使用RavenDB獲得這種類型的結果集?
一個可能的解決方案是獲取查詢的所有產品並在內存中執行分組,另一個選項是創建一個如上所述的mapreduce索引,但挑戰是推導出可以進行的所有可能的spec選擇對於給定的類別,此外,此類索引的大小可能會爆炸。
舉個例子,看看this fastener category page。用戶可以通過選擇屬性來過濾他們的選擇。選擇屬性後,會縮小產品的選擇範圍,並在新的一組產品中顯示屬性。這種交互通常稱爲faceted search。
編輯
在此期間,他們支持面搜索開箱我將嘗試使用Solr的解決方案。
編輯2
似乎RavenDB還支持faceted search(這當然是有道理的,索引由Lucene的存儲一樣的Solr)。我將會探索這個併發布更新。
編輯3
的RavenDB面搜索功能按預期工作。我爲每個類別ID存儲一個構面設置文檔,用於計算給定類別內的查詢的構面。我現在面臨的問題是表現。對於具有4500個不同類別的500k產品的集合導致4500個構面文檔設置文檔,查詢分類id在查詢構面時大約需要16秒,而在不查詢構面時大約需要0.05秒。測試的特定類別包含約6k產品,23個不同的刻面和2k個不同刻面名稱範圍組合。查看FacetedQueryRunner中的代碼後,出現一個facets查詢將導致每個方面名稱 - 值組合的Lucene查詢獲取計數,以及每個方面名稱的查詢以獲取這些術語。實現的一個問題是,它將檢索給定方面名稱的所有不同的術語,而不考慮查詢,這在大多數情況下會顯着減少方面的術語數量,並因此減少Lucene查詢的數量。提高性能的方法之一是爲每個分面設置文檔存儲一個MapReduce計算結果集(如上所示),然後可以查詢這些文檔,以便在按分面進一步過濾時獲取所有不同的術語。但整體表現可能仍然太慢。
我不認爲我理解。你想要做什麼查詢? 預期結果是什麼? –
以例如由類別id定義的產品集 - 給定類別中的所有產品。該集合中的每個產品都有一組規格名稱 - 值對,可以按名稱和值對它們進行分組,計數具有給定名稱值對的產品數量。這是我希望得到的結果,但不僅適用於給定類別的產品,還適用於通過一組規格名稱 - 值對過濾的類別中的類別。這是爲了允許在網站產品目錄上「鑽取」產品選擇。 – eulerfx