【发布时间】:2025-11-23 07:55:02
【问题描述】:
我正在使用带有 Elasticsearch 的 Django Haystack 作为实时航班地图服务的后端。
我已正确设置所有搜索索引,但是,我无法返回非完整字词的搜索结果(例如航空呼号,其中一些采用 N346IF 样式,其他包含完整字词例如Speedbird 500)。 N346IF 样式的查询不会产生任何结果,而对于后一个示例,我可以轻松返回结果。
我的查询如下:
queryResults = SearchQuerySet().filter(content=q) # where q is the query in string format
(请注意,过去我使用了AutoQuery 查询集,但文档列出了它只跟踪单词,所以我现在传递一个原始字符串)。
我的搜索索引字段设置为EdgeNgramField 和搜索模板。
我有一个具有以下索引设置的自定义后端(以及snowball 分析器和pattern 分析器):
ELASTICSEARCH_INDEX_SETTINGS = {
'settings': {
"analysis": {
"analyzer": {
"ngram_analyzer": {
"type": "custom",
"tokenizer": "lowercase",
"filter": ["haystack_ngram"]
},
"edgengram_analyzer": {
"type": "custom",
"tokenizer": "lowercase",
"filter": ["haystack_edgengram"]
}
},
"tokenizer": {
"haystack_ngram_tokenizer": {
"type": "nGram",
"min_gram": 4,
"max_gram": 15,
},
"haystack_edgengram_tokenizer": {
"type": "edgeNGram",
"min_gram": 4,
"max_gram": 15,
"side": "front"
}
},
"filter": {
"haystack_ngram": {
"type": "nGram",
"min_gram": 4,
"max_gram": 15
},
"haystack_edgengram": {
"type": "edgeNGram",
"min_gram": 4,
"max_gram": 15
}
}
}
}
}
ELASTICSEARCH_DEFAULT_ANALYZER = "pattern"
我的后端配置为:
class ConfigurableElasticBackend(ElasticsearchSearchBackend):
def __init__(self, connection_alias, **connection_options):
super(ConfigurableElasticBackend, self).__init__(
connection_alias, **connection_options)
user_settings = getattr(settings, 'ELASTICSEARCH_INDEX_SETTINGS')
if user_settings:
setattr(self, 'DEFAULT_SETTINGS', user_settings)
class ConfigurableElasticBackend(ElasticsearchSearchBackend):
DEFAULT_ANALYZER = "pattern"
def __init__(self, connection_alias, **connection_options):
super(ConfigurableElasticBackend, self).__init__(
connection_alias, **connection_options)
user_settings = getattr(settings, 'ELASTICSEARCH_INDEX_SETTINGS')
user_analyzer = getattr(settings, 'ELASTICSEARCH_DEFAULT_ANALYZER')
if user_settings:
setattr(self, 'DEFAULT_SETTINGS', user_settings)
if user_analyzer:
setattr(self, 'DEFAULT_ANALYZER', user_analyzer)
def build_schema(self, fields):
content_field_name, mapping = super(ConfigurableElasticBackend,
self).build_schema(fields)
for field_name, field_class in fields.items():
field_mapping = mapping[field_class.index_fieldname]
if field_mapping['type'] == 'string' and field_class.indexed:
if not hasattr(field_class, 'facet_for') and not \
field_class.field_type in('ngram', 'edge_ngram'):
field_mapping['analyzer'] = self.DEFAULT_ANALYZER
mapping.update({field_class.index_fieldname: field_mapping})
return (content_field_name, mapping)
class ConfigurableElasticSearchEngine(ElasticsearchSearchEngine):
backend = ConfigurableElasticBackend
为了成功地为既是和/或N346IF-style 字符串的搜索模式生成结果,正确的设置是什么?
感谢任何输入,如果这与另一个问题相似(找不到任何相关内容),我们深表歉意。
编辑: solarissmoke 请求,此模型的架构:
class FlightIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.EdgeNgramField(document=True, use_template=True)
flight = indexes.CharField(model_attr='flightID')
callsign = indexes.CharField(model_attr='callsign')
displayName = indexes.CharField(model_attr='displayName')
session = indexes.CharField(model_attr='session')
def prepare_session(self, obj):
return obj.session.serverId
def get_model(self):
return Flight
文本被索引为:
flight___{{ object.callsign }}___{{ object.displayName }}
【问题讨论】:
-
我认为我们需要查看您正在索引的字段的架构。请发布索引定义。
-
@solarissmoke - 刚刚编辑它。如果您认为还有其他需要,请告诉我。
-
我有理由确定我知道问题出在哪里,但为了帮助我确认您能否提供您可以成功搜索的样本
Flight数据(callsign、displayName),以及一些你不能,以及相关的搜索查询? -
没问题!有效的查询:
callsign是United 55,displayName是Tsuyoshi Hiroi- 使用查询United或United 55,将返回结果。一个不起作用:callsign是N133TC,displayName是Shahrul Nizam,并且通过查询呼号(其中查询内容为N133TC),此查询不起作用。但是,如果使用显示名称,则此查询有效,Shahrul产生结果)。 -
嗯,这不是我所期望的。您能否确认在您的
text文档中___是下划线而不是空格?
标签: django elasticsearch django-haystack