Django haystack LocationField 在 elasticsearch 中创建为字符串而不是 geo_point
Django haystack LocationField created as string instead of geo_point in elasticsearch
我将 django 1.8.9、django-rest-framework、django-haystack 与 Elasticsearch 一起使用,并试图让 LocationField 正常工作,索引已创建,但类型始终为 string
geo_point
,所以显然没有地理搜索工作。
settings.py:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.gis',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'django_extensions',
'elasticsearch',
'rest_framework',
'haystack',
)
requirements.txt:
Django==1.8.9
django-appconf==1.0.1
django-compressor==1.6
django-extensions==1.6.1
django-filter==0.11.0
django-haystack==2.4.1
djangorestframework==3.3.1
djangorestframework-jwt==1.7.2
ecdsa==0.13
elasticsearch==2.2.0
Fabric==1.10.2
future==0.15.2
geopy==1.11.0
gunicorn==19.4.1
Markdown==2.6.5
paramiko==1.16.0
psycopg2==2.6.1
pycrypto==2.6.1
PyJWT==1.4.0
python-dateutil==2.4.2
python-memcached==1.57
setproctitle==1.1.9
six==1.10.0
urllib3==1.14
search_indexes.py:
from haystack import indexes
from blah.api.models import MyModel
class MyIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
description = indexes.CharField(model_attr='description')
location = indexes.LocationField(model_attr='get_location')
created = indexes.DateTimeField(model_attr='created')
def get_model(self):
return MyModel
MyModel 上的 get_location 属性:
from haystack.utils.geo import Point
def get_location(self):
return Point(self.lng, self.lat)
创建的 elasticsearch 索引(对格式感到抱歉!):
{
"myindex":{
"mappings":{
"modelresult":{
"properties":{
"created":{
"type":"date",
"format":"strict_date_optional_time||epoch_millis"
},
"description":{
"type":"string"
},
"django_ct":{
"type":"string"
},
"django_id":{
"type":"string"
},
"id":{
"type":"string"
},
"location":{
"type":"string"
},
"text":{
"type":"string"
}
}
}
}
}
}
有人有什么想法吗?感觉它是 django、django-haystack 和 elasticsearch 之间版本的组合,玩起来不太好,但我似乎无法让任何组合工作。
也许它不起作用,因为 get_location
不是 MyModel
上的字段。
也许您可以通过添加 @property
装饰器来避免将位置创建为字段,如下所示:
from haystack.utils.geo import Point
@property
def get_location(self):
return Point(self.lng, self.lat)
编辑:这看起来不会解决问题。你拥有它就像它在文档中一样。
好的,我知道问题出在哪里了:
在 Elasticsearch 2.0 中,有元数据的变化,其中之一是 boost
已经被移除:https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking_20_mapping_changes.html#migration-meta-fields
通过 elasticsearch/transport.py
回溯,对 http://127.0.0.1:9200/myindex/_mapping/modelresult 的 PUT 请求包括 "_boost": {"name": "boost", "null_value": 1.0} 在body。
因此跟踪调用并将它们重新命名为 CURL:
创建索引
curl -X PUT -d '{"settings": {"analysis": {"filter": {"haystack_edgengram": {"max_gram": 15, "type": "edgeNGram", "min_gram": 2}, "haystack_ngram": {"max_gram": 15, "type": "nGram", "min_gram": 3}}, "tokenizer": {"haystack_ngram_tokenizer": {"max_gram": 15, "type": "nGram", "min_gram": 3}, "haystack_edgengram_tokenizer": {"max_gram": 15, "type": "edgeNGram", "side": "front", "min_gram": 2}}, "analyzer": {"edgengram_analyzer": {"filter": ["haystack_edgengram", "lowercase"], "type": "custom", "tokenizer": "standard"}, "ngram_analyzer": {"filter": ["haystack_ngram", "lowercase"], "type": "custom", "tokenizer": "standard"}}}}}' http://127.0.0.1:9200/myindex
请求失败
curl -X PUT -d '{"modelresult": {"_boost": {"name": "boost", "null_value": 1.0}, "properties": {"django_id": {"include_in_all": false, "index": "not_analyzed", "type": "string"}, "description": {"type": "string", "analyzer": "snowball"}, "created": {"type": "date"}, "text": {"type": "string", "analyzer": "snowball"}, "django_ct": {"include_in_all": false, "index": "not_analyzed", "type": "string"}, "location": {"type": "geo_point"}}}}' http://127.0.0.1:9200/myindex/_mapping/modelresult
更改为这个有效
curl -X PUT -d '{"modelresult": {"properties": {"django_id": {"include_in_all": false, "index": "not_analyzed", "type": "string"}, "description": {"type": "string", "analyzer": "snowball"}, "created": {"type": "date"}, "text": {"type": "string", "analyzer": "snowball"}, "django_ct": {"include_in_all": false, "index": "not_analyzed", "type": "string"}, "location": {"type": "geo_point"}}}}' http://127.0.0.1:9200/myindex/_mapping/modelresult
因此,python 修正
在 haystack/backends/elasticsearch_backend.py 中,注释掉第 137-140 行 current_mapping 的提升部分
我将 django 1.8.9、django-rest-framework、django-haystack 与 Elasticsearch 一起使用,并试图让 LocationField 正常工作,索引已创建,但类型始终为 string
geo_point
,所以显然没有地理搜索工作。
settings.py:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.gis',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'django_extensions',
'elasticsearch',
'rest_framework',
'haystack',
)
requirements.txt:
Django==1.8.9
django-appconf==1.0.1
django-compressor==1.6
django-extensions==1.6.1
django-filter==0.11.0
django-haystack==2.4.1
djangorestframework==3.3.1
djangorestframework-jwt==1.7.2
ecdsa==0.13
elasticsearch==2.2.0
Fabric==1.10.2
future==0.15.2
geopy==1.11.0
gunicorn==19.4.1
Markdown==2.6.5
paramiko==1.16.0
psycopg2==2.6.1
pycrypto==2.6.1
PyJWT==1.4.0
python-dateutil==2.4.2
python-memcached==1.57
setproctitle==1.1.9
six==1.10.0
urllib3==1.14
search_indexes.py:
from haystack import indexes
from blah.api.models import MyModel
class MyIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
description = indexes.CharField(model_attr='description')
location = indexes.LocationField(model_attr='get_location')
created = indexes.DateTimeField(model_attr='created')
def get_model(self):
return MyModel
MyModel 上的 get_location 属性:
from haystack.utils.geo import Point
def get_location(self):
return Point(self.lng, self.lat)
创建的 elasticsearch 索引(对格式感到抱歉!):
{
"myindex":{
"mappings":{
"modelresult":{
"properties":{
"created":{
"type":"date",
"format":"strict_date_optional_time||epoch_millis"
},
"description":{
"type":"string"
},
"django_ct":{
"type":"string"
},
"django_id":{
"type":"string"
},
"id":{
"type":"string"
},
"location":{
"type":"string"
},
"text":{
"type":"string"
}
}
}
}
}
}
有人有什么想法吗?感觉它是 django、django-haystack 和 elasticsearch 之间版本的组合,玩起来不太好,但我似乎无法让任何组合工作。
也许它不起作用,因为 get_location
不是 MyModel
上的字段。
也许您可以通过添加 @property
装饰器来避免将位置创建为字段,如下所示:
from haystack.utils.geo import Point
@property
def get_location(self):
return Point(self.lng, self.lat)
编辑:这看起来不会解决问题。你拥有它就像它在文档中一样。
好的,我知道问题出在哪里了:
在 Elasticsearch 2.0 中,有元数据的变化,其中之一是 boost
已经被移除:https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking_20_mapping_changes.html#migration-meta-fields
通过 elasticsearch/transport.py
回溯,对 http://127.0.0.1:9200/myindex/_mapping/modelresult 的 PUT 请求包括 "_boost": {"name": "boost", "null_value": 1.0} 在body。
因此跟踪调用并将它们重新命名为 CURL:
创建索引
curl -X PUT -d '{"settings": {"analysis": {"filter": {"haystack_edgengram": {"max_gram": 15, "type": "edgeNGram", "min_gram": 2}, "haystack_ngram": {"max_gram": 15, "type": "nGram", "min_gram": 3}}, "tokenizer": {"haystack_ngram_tokenizer": {"max_gram": 15, "type": "nGram", "min_gram": 3}, "haystack_edgengram_tokenizer": {"max_gram": 15, "type": "edgeNGram", "side": "front", "min_gram": 2}}, "analyzer": {"edgengram_analyzer": {"filter": ["haystack_edgengram", "lowercase"], "type": "custom", "tokenizer": "standard"}, "ngram_analyzer": {"filter": ["haystack_ngram", "lowercase"], "type": "custom", "tokenizer": "standard"}}}}}' http://127.0.0.1:9200/myindex
请求失败
curl -X PUT -d '{"modelresult": {"_boost": {"name": "boost", "null_value": 1.0}, "properties": {"django_id": {"include_in_all": false, "index": "not_analyzed", "type": "string"}, "description": {"type": "string", "analyzer": "snowball"}, "created": {"type": "date"}, "text": {"type": "string", "analyzer": "snowball"}, "django_ct": {"include_in_all": false, "index": "not_analyzed", "type": "string"}, "location": {"type": "geo_point"}}}}' http://127.0.0.1:9200/myindex/_mapping/modelresult
更改为这个有效
curl -X PUT -d '{"modelresult": {"properties": {"django_id": {"include_in_all": false, "index": "not_analyzed", "type": "string"}, "description": {"type": "string", "analyzer": "snowball"}, "created": {"type": "date"}, "text": {"type": "string", "analyzer": "snowball"}, "django_ct": {"include_in_all": false, "index": "not_analyzed", "type": "string"}, "location": {"type": "geo_point"}}}}' http://127.0.0.1:9200/myindex/_mapping/modelresult
因此,python 修正 在 haystack/backends/elasticsearch_backend.py 中,注释掉第 137-140 行 current_mapping 的提升部分