1

QuerySetDjango Haystack + Elasticsearch + Django REST Framework を使用して小さな検索エンジンを構築しており、Djangoのdistinctメソッドの動作を再現しようとしています。

私のインデックスは次のようになります。

class ItemIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)
    item_id = indexes.IntegerField(faceted=True)

    def prepare_item_id(self, obj):
        return obj.item_id

私ができるようにしたいのは、次のとおりです。

sqs = SearchQuerySet().filter(content=my_search_query).distinct('item_id')

ただ、Haystack'sにはメソッドSearchQuerySetがないので、なんだか迷ってしまいます。distinctフィールドをファセットし、返された のリストを使用して Django にクエリを実行しようとしましitem_idたが、これにより Elasticsearch のパフォーマンスが低下し、Elasticsearch の並べ替え機能も使用できなくなります。

何かご意見は?

編集:

サンプルデータ:

サンプルデータ:

Item Model
==========

id  title
1   'Item 1'
2   'Item 2'
3   'Item 3'


VendorItem Model << the table in question
================

id  item_id  vendor_id  lat   lon
1   1        1          38    -122
2   2        1          38.2  -121.8
3   3        2          37.9  -121.9
4   1        2          ...   ...
5   2        2          ...   ...
6   2        3          ...   ...

ご覧のとおり、同じアイテムに対して複数の VendorItem がありますが、検索するときは、アイテムごとに最大で 1 つの結果のみを取得したいと考えています。したがって、item_id列を一意/個別にする必要があります。

列でファセットを作成してからitem_id、次のクエリを実行してみました。

facets = SearchQuerySet().filter(content=query).facet('item_id')
counts = sqs.facet_counts()

# ids will look like: [345, 892, 123, 34,...]
ids = [i[0] for i in counts['fields']['item_id']]

items = VendorItem.objects.filter(vendor__lat__gte=latMin,
    vendor__lon__gte=lonMin, vendor__lat__lte=latMax,
    vendor__lon__lte=lonMax, item_id__in=ids).distinct(
        'item').select_related('vendor', 'item')

ここでの主な問題は、結果が 100 項目に制限されており、haystack でソートできないことです。

4

1 に答える 1

4

私があなたにできる最善のアドバイスは、Haystack の使用をやめることだと思います。

Haystack のデフォルトのバックエンド (elasticsearch_backend.py) は、ほとんどが Solr を念頭に置いて作成されています。haystack には多くの問題がありますが、最大の問題は、すべてのクエリが query_string と呼ばれるものにパックされていることです。クエリ文字列を使用すると、lucene 構文を使用できますが、elasticsearch DSL 全体が失われることにもなります。lucene 構文には、特にこれに慣れている場合はいくつかの利点がありますが、elasticsearch の観点からは非常に制限されています。

さらに、RDBMS の概念を検索エンジンに適用していると思います。必要な結果が得られないというわけではありませんが、アプローチはしばしば異なります。

haystack は Elasticsearch よりも solr に適した方法でインデックスを作成するため、haystack を使用しない場合、このデータをクエリして取得する方法が異なる場合があります。

たとえば、新しいインデックスを作成する場合、haystack は「modelresult」という「タイプ」をインデックスに含まれるすべてのモデルに割り当てます。

そこで、Items と呼ばれるいくつかのエンティティと、vendoritems と呼ばれる他のいくつかのエンティティがあるとします。

両方を同じインデックスに入れるのが適切かもしれませんが、vendoritems は vendoritem のタイプとして、item は items のタイプを持ちます。

クエリを実行するときは、残りのエンドポイントに基づいてクエリを実行するため、localhost:9200/index/type (query). haystack がこれを実現する方法は、django コンテンツ タイプ モジュールを使用することです。したがって、「django_ct」と呼ばれるフィールドがあり、haystack がクエリを実行し、一意のアイテムのみを探しているときに作成するクエリにアタッチします。

上記を説明するには:

このエンドポイントはすべてのインデックスを検索します

`localhost:9200/`

このエンドポイントは、インデックス内のすべてのタイプを検索します。

`localhost:9200/yourindex/`

このエンドポイントは、インデックス内のタイプを検索します。

`localhost:9200/yourindex/yourtype/`

このエンドポイントは、インデックス内の指定された 2 つのタイプを検索します。

`localhost:9200/yourindex/yourtype,yourothertype/`

ただし、haystack に戻ると、クエリに django_ct を追加することで一意の値を取得できる可能性がありますが、それはおそらくあなたが望むものではありません。

本当にやりたいのはファセットであり、おそらく用語ファセットを使用したいと思うでしょう。これは、A.) すべてのテキストを分析し、B.) store=True をすべてのフィールドに適用するため、haystack で問題になる可能性があります (実際には、elasticsearch で実行したいことではなく、solr で実行したいことがよくあります)。

Elasticsearch でファセット結果を並べ替えることができます ( http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-terms-facet.html#_ordering )

私はこれが干し草の山のスラムであるという意味ではありません. 概念的には多くのことを正しく行っていると思います。単一のモデル (ブログなど) にインデックスを付けるだけでよく、すぐに結果が返される場合は特に便利です。

とはいえ、 elasticutilsを使用することを強くお勧めします。haystack の概念のいくつかは似ていますが、query_string ではなく検索 dsl を使用します (ただし、必要に応じて query_string を使用することもできます)。

ただし、デフォルトでelasticutilsを使用してファセットを注文できるとは思いませんが、facet_rawメソッドを作成したいファセットのPython辞書を渡すことができます(haystackではできないと思います)。

最後のオプションは、独自の haystack バックエンドを作成し、既存のバックエンドから継承し、.facet() メソッドにいくつかの機能を追加して、上記の DSL に従って注文できるようにすることです。

于 2013-11-18T16:35:14.693 に答える