【问题标题】:Django Haystack Distinct Value for FieldDjango Haystack 字段的不同值
【发布时间】:2013-11-17 18:49:46
【问题描述】:

我正在使用 Django Haystack + Elasticsearch + Django REST Framework 构建一个小型搜索引擎,我试图找出重现 Django QuerySetdistinct 方法的行为。

我的索引看起来像这样:

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 的 SearchQuerySet 没有 distinct 方法,所以我有点迷路了。我尝试对字段进行分面,然后使用返回的 item_id 列表查询 Django,但这会损失 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,但是在搜索时,我只想为每个项目检索最多一个结果。因此,我需要 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 进行排序。

【问题讨论】:

  • 不确定方法是否正确。你想完成什么,数据是什么样的
  • @JamesR 我在编辑中添加了一些信息,您介意看一下吗?

标签: python django elasticsearch django-haystack searchqueryset


【解决方案1】:

我认为我能给你的最好建议是停止使用 Haystack。

Haystack 的默认后端(elasticsearch_backend.py)主要是考虑到 Solr 编写的。我在 haystack 中发现了很多烦恼,但最大的问题是它将所有查询打包到名为 query_string 的东西中。使用查询字符串,他们可以使用 lucene 语法,但这也意味着丢失了整个 elasticsearch DSL。 lucene 语法有一些优点,特别是如果这是你习惯的,但从弹性搜索的角度来看它是非常有限的。

此外,我认为您正在将 RDBMS 概念应用于搜索引擎。这并不是说你不应该得到你需要的结果,但方法往往不同。

如果您不使用 haystack,则查询和检索此数据的方式可能会有所不同,因为 haystack 创建索引的方式更适合 solr 而不是 elasticsearch。

例如,在创建一个新索引时,haystack 将为将进入索引的所有模型分配一个名为“modelresult”的“类型”。

因此,假设您有一些名为 Items 的实体和一些名为 vendoritems 的其他实体。

将它们都放在同一个索引中但将 vendoritems 作为一种类型的 vendoritems 和具有一种类型的项可能是合适的。

查询时,您将根据其余端点进行查询,例如localhost:9200/index/type (query)。 haystack 实现的方式是通过 django 内容类型模块。因此,有一个名为“django_ct”的字段,当您只寻找独特的项目时,它会查询并附加到您可能进行的任何查询。

为了说明以上内容:

此端点搜索所有索引

`localhost:9200/`

此端点搜索索引中的所有类型:

`localhost:9200/yourindex/`

此端点在索引中搜索类型:

`localhost:9200/yourindex/yourtype/`

并且此端点在索引中搜索两种指定类型:

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

不过,回到 haystack,您可以通过在查询中添加 django_ct 来获得唯一值,但这可能不是您想要的。

您真正想做的是一个方面,并且可能您想使用术语方面。这可能是 haystack 中的一个问题,因为它 A.) 分析所有文本和 B.) 将 store=True 应用于所有字段(实际上不是您想在 elasticsearch 中做的事情,而是您经常想在 solr 中做的事情)。

您可以在 elasticsearch (http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-terms-facet.html#_ordering) 中订购 facet 结果

我的意思并不是说这会成为大海捞针。我认为它在概念上做了很多正确的事情。如果您只需要索引单个模型(例如博客)并让它快速返回结果,那就特别好。

也就是说,我强烈推荐使用elasticutils。 haystack 中的一些概念类似,但它使用搜索 dsl,而不是 query_string(但如果需要,您仍然可以使用 query_string)。

但请注意,我认为默认情况下您不能使用 elasticutils 订购构面,但您可以将您想要的构面的 python 字典传递给facet_raw 方法(我认为您不能这样做大海捞针)。

您的最后一个选择是创建您自己的 haystack 后端,从现有的后端继承,然后在 .facet() 方法中添加一些功能,以便按照上述 dsl 进行排序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多