15

Solr のドキュメントにpriceというフィールドがあり、そのフィールドがファセットされているとします。ファセットを値の範囲として取得したい (例: 0-100、100-500、500-1000 など)。どうやってするの?

事前に範囲を指定することはできますが、ドキュメントの値に基づいて範囲 (たとえば 5 つの値) を自動的に計算できるかどうかも知りたいですか?

4

4 に答える 4

14

最初の質問に答えるために、汎用ファセット クエリ サポートを使用してファセット範囲を取得できます。を次に示します。

http://localhost:8983/solr/select?q=video&rows=0&facet=true&facet.query=price:[*+TO+500]&facet.query=price:[500+TO+*]

2 番目の質問 (自動的にファセット範囲を提案する) については、まだ実装されていません。Solr に最適なファセット範囲を「推測」させるよりも、この種のクエリをアプリケーションに実装するのが最適であると主張する人もいます。

このトピックに関するいくつかの議論を以下に示します。

于 2008-10-04T15:04:56.923 に答える
7

私は、製品の価格帯について適切な動的ファセットを計算する方法を考え出しました。このソリューションには、ドキュメントの前処理とクエリ結果の後処理が含まれますが、Solr へのクエリは 1 つしか必要なく、1.4 のような古いバージョンの Solr でも動作するはずです。

送信前に価格を切り上げる

まず、ドキュメントを送信する前に、価格を最も近い「ナイス ラウンド ファセット境界」に切り上げ、「rounded_price」フィールドに格納します。ユーザーは、ファセットが「247-483」ではなく「250-500」のように見えることを好みます。また、丸めは、数百万ではなく数百の価格ファセットを返すことも意味します。少し努力すれば、次のコードを一般化して、任意の価格スケールで適切に丸めることができます。

    public static decimal RoundPrice(decimal price)
    {
        if (price < 25)
            return Math.Ceiling(price);
        else if (price < 100)
            return Math.Ceiling(price / 5) * 5;
        else if (price < 250)
            return Math.Ceiling(price / 10) * 10;
        else if (price < 1000)
            return Math.Ceiling(price / 25) * 25;
        else if (price < 2500)
            return Math.Ceiling(price / 100) * 100;
        else if (price < 10000)
            return Math.Ceiling(price / 250) * 250;
        else if (price < 25000)
            return Math.Ceiling(price / 1000) * 1000;
        else if (price < 100000)
            return Math.Ceiling(price / 2500) * 2500;
        else
            return Math.Ceiling(price / 5000) * 5000;
    }

許容価格は、1、2、3、...、24、25、30、35、...、95、100、110、...、240、250、275、300、325、...、975、1000 などです。

丸められた価格のすべての側面を取得

次に、クエリを送信するときに、価格で並べ替えられた丸められた価格のすべてのファセットを要求しますfacet.field=rounded_price。丸めのおかげで、最大で数百のファセットが返されます。

隣接するファセットを結合してより大きなファセットにする

第 3 に、結果が得られた後、ユーザーは数百のファセットではなく、3 から 7 のファセットのみを表示したいと考えています。したがって、隣接するファセットをいくつかの大きなファセット (「セグメント」と呼ばれる) に結合して、各セグメントでほぼ同数のドキュメントを取得しようとします。次のかなり複雑なコードはこれを行い、範囲クエリの実行に適した (開始、終了、カウント) のタプルを返します。価格が最も近い境界に切り上げられていれば、返されるカウントは正しいものになります。

    public static List<Tuple<string, string, int>> CombinePriceFacets(int nSegments, ICollection<KeyValuePair<string, int>> prices)
    {
        var ranges = new List<Tuple<string, string, int>>();
        int productCount = prices.Sum(p => p.Value);
        int productsRemaining = productCount;
        if (nSegments < 2)
            return ranges;
        int segmentSize = productCount / nSegments;
        string start = "*";
        string end = "0";
        int count = 0;
        int totalCount = 0;
        int segmentIdx = 1;
        foreach (KeyValuePair<string, int> price in prices)
        {
            end = price.Key;
            count += price.Value;
            totalCount += price.Value;
            productsRemaining -= price.Value;
            if (totalCount >= segmentSize * segmentIdx)
            {
                ranges.Add(new Tuple<string, string, int>(start, end, count));
                start = end;
                count = 0;
                segmentIdx += 1;
            }
            if (segmentIdx == nSegments)
            {
                ranges.Add(new Tuple<string, string, int>(start, "*", count + productsRemaining));
                break;
            }
        }
        return ranges;
    }

選択したファセットで結果をフィルタリングする

4 番目に、("250","500",38) が結果のセグメントの 1 つであるとします。ユーザーがフィルターとして「250 ドルから 500 ドル」を選択した場合は、単純にフィルター クエリを実行します。fq=price:[250 TO 500]

于 2012-07-04T13:14:58.640 に答える
4

より良い Solr 固有の回答があるかもしれませんが、私は単純な Lucene を使用しています。そこで、オリジナルをラップして populate aFilterを作成します。次に、関心のある分野の を取得します。フィルターのビットセットでヒットを列挙し、ヒットごとに、フィールド キャッシュからフィールドの値を取得し、SortedSet に追加します。すべてのヒットを取得したら、セットのサイズを必要な範囲の数に分割します (ユーザー インターフェイスの関係者によると、5 から 7 が適切な数です)。単一値の制約ではなく、ファセットは次のようになります。これらの各サブセットの下限と上限を持つ範囲クエリになります。FilteredQueryQueryFieldCache

少数の値には特殊なケースのロジックを使用することをお勧めします。明らかに、4 つの個別の値しかない場合、それらから 5 つの範囲を絞り込むことは意味がありません。特定のしきい値 (たとえば、範囲の理想的な数の 3 倍) を下回ると、範囲ではなくファセットを通常どおりに表示します。

于 2008-08-29T05:53:19.837 に答える
4

solrファセット範囲を使用できます

http://wiki.apache.org/solr/SimpleFacetParameters#Facet_by_Range

于 2012-05-15T10:42:39.767 に答える