繁体   English   中英

Django Haystack对场的不同价值

[英]Django Haystack Distinct Value for Field

我正在使用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列上尝试过faceting,然后执行以下查询:

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进行排序。

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

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

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

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

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

所以,假设您有一些名为Items的实体和一些名为vendoritems的实体。

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

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

为了说明上述内容:

此端点搜索所有索引

`localhost:9200/`

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

`localhost:9200/yourindex/`

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

`localhost:9200/yourindex/yourtype/`

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

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

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

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

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

我并不是说这是干草堆的大满贯。 我认为它在概念上做了很多事情。 如果所有你需要做的就是索引单个模型(比如说博客)并且让它快速返回结果,那就特别好了。

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

但是请注意,我不认为你可以默认使用elasticutils来命令facet,但你可以传入一个你想要facet_raw方法的facet的python字典(我认为你不能在haystack中做)。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM