これはthisで概説されたプロジェクトの続きです。製品カタログの照会製品の任意のコレクションに対するスペック集約のためのRavenDBストア
私は、次のモデルがあります:
class Product {
public string Id { get; set; }
public string[] Specs { get; set; }
public int CategoryId { get; set; }
}
「仕様」の配列に格納の特殊文字によって接合された製品仕様名と値のペアを。例えば、製品が青色に着色されている場合、仕様文字列は「Color〜Blue」になります。このように仕様を表すことで、クエリで指定された複数の仕様値を持つ製品をクエリできます。私がサポートしたい2つの主要な質問があります:
- 特定のカテゴリのすべての製品を取得します。
- 指定されたカテゴリのすべての製品が、指定された仕様のセットを取得します。
これはRavenDBでうまくいきます。しかし、特定のクエリを満たす製品に加えて、クエリで指定された製品のセットのすべての仕様の名前と値のペアを含む結果セットを返したいと思います。スペック名と値のペアは、スペックの名前と値でグループ化し、指定されたスペック名と値のペアを持つ製品の数を含む必要があります。私は、このインデックスを照会し、特定のカテゴリ内のすべてのスペックの名前と値のペアを取得することができます
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)
};
}
}
:クエリ#1のために私は、次のマップは、インデックスを減らす作成しました。私が実行している問題は、同じ結果セットを取得することですが、カテゴリと仕様の名前と値のペアの両方をフィルタリングするクエリに対してです。 SQLを使用する場合、この結果セットは、カテゴリと仕様でフィルタリングされた一連の製品でグループを実行することによって得られます。一般に、このタイプのクエリは高価ですが、カテゴリと仕様の両方でフィルタリングすると、製品セットは通常小さくなりますが、単一のページに収まるほど小さくはありません。参考までに、MongoDBは同じ結果セットを得るために使用できるgroupメソッドをサポートしています。これにより、アドホックグループ化サーバー側が実行され、パフォーマンスは許容されます。
RavenDBを使用してこのタイプの結果セットを取得するにはどうすればよいですか?
可能な解決策の1つは、クエリですべての製品を取得してメモリ内でグループ分けを実行することです。これを使用すると、可能なすべてのスペック選択を推測することができます特定のカテゴリの場合、さらにこのタイプのインデックスはサイズが爆発する可能性があります。
たとえば、this fastener category pageをご覧ください。ユーザーは、属性を選択することによって選択をフィルタリングできます。属性を選択すると、製品の選択が絞り込まれ、新しい製品セット内の属性が表示されます。この種の相互作用は、通常faceted searchと呼ばれます。
EDIT
その間に彼らは箱から出しファセット検索をサポートするように、私はSolrを使用してソリューションをしようとします。
EDIT 2
RavenDBも(もちろん理にかなっている、インデックスがちょうどSolrのようLuceneとによって保存されている)faceted searchをサポートしていることが表示されます。私はこれを探求し、更新を掲載する予定です。予想通り
EDIT 3
RavenDBファセット検索機能は動作します。私は、各カテゴリIDのファセット設定文書を保存します。これは、特定のカテゴリ内のクエリのファセットを計算するために使用されます。今私が持っている問題はパフォーマンスです。 4500個の異なるカテゴリを持つ500k製品のコレクションでは、4500個のファセット設定ドキュメントが生成され、カテゴリIDによるクエリでは、ファセットを照会する場合は約16秒、ファセットを照会しない場合は約0.05秒かかります。テストされた特定のカテゴリには、約6kの製品、23の異なるファセット、2kの異なるファセットの名前範囲の組み合わせが含まれています。 FacetedQueryRunnerのコードを調べると、ファセットクエリーが表示され、各ファセット名と値の組み合わせごとにカウントを取得し、各ファセット名のクエリーとして結果を取得します。この実装の1つの問題は、ほとんどの場合、ファセットの用語数を大幅に減らし、したがってLuceneクエリの数を減らす、クエリに関係なく、指定されたファセット名のすべての別個の用語を検索することです。ここでのパフォーマンスを向上させる方法の1つは、各ファセット設定ドキュメント用のMapReduce計算結果セット(上記のように)を保存することです。ファセットによってさらにフィルタリングするときにすべての別個の用語を取得することができます。しかし、全体的なパフォーマンスはまだ遅すぎるかもしれません。
私は理解しているとは思わない。作成するクエリは何ですか? 期待される結果は何ですか? –
たとえば、カテゴリidで定義された一連の製品 - 特定のカテゴリのすべての製品を取り上げます。セット内の各製品には、指定された名前値のペアを持つ製品の数を数えて名前と値でグループ化することができる仕様の名前と値のペアのセットがあります。これは私が得たい結果ですが、特定のカテゴリの製品だけでなく、一連のスペック名と値のペアでフィルタリングされたカテゴリのカテゴリも対象となります。これは、ウェブサイトの製品カタログ上の製品選択を「穴あけ」することを可能にすることである。 – eulerfx