django-haystack elasticsearch 多索引错误结果
django-haystack elasticsearch multiple indexes wrong results
我使用 django-haystack + elasticsearch 在我的站点中设置了一个搜索索引。有不同的索引,通常它们可以正常工作,但当我搜索一个人时 ProjectIndex 除外。让我解释一下:
这些是型号:
class Person(models.Model):
first_name = models.CharField()
last_name = models.CharField()
class Project(models.Model):
project_name = models.CharField()
employees = models.ManyToManyField(Person)
这些是索引:
class ProjectIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.EdgeNgramField(document=True, use_template=True)
project_name = indexes.CharField(model_attr='project_name', boost=1.4)
employees = indexes.CharField(boost=1.5)
def get_model(self):
return Project
def prepare_employees(self, obj):
return ' '.join([employee.__unicode__() for employee in obj.employees.all()])
def prepare(self, obj):
data = super(ProjectIndex, self).prepare(obj)
data['boost'] = 1.3
return data
class PersonIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.EdgeNgramField(document=True, use_template=True)
first_name = indexes.CharField(model_attr='first_name', boost=1.1)
last_name = indexes.CharField(model_attr='last_name', boost=1.2)
def get_model(self):
return Person
当我 运行 rebuild_index 时,所有项目似乎都已正确编入索引。当我搜索一个人时对elasticsearch服务器的一个简单的http查询 returns 有用的项目结果(真的很有意义)。
>>> from urllib import urlopen
>>> response = urlopen('http://127.0.0.1:9200/_search?q=' + q)
>>> json_data = response.read()
>>> from json import loads
>>> d = loads(json_data)
>>> f = filter(lambda d: d['_source']['django_ct'] == "project.project", d['hits']['hits'])
>>> len(f)
8
另一方面,SearchQuerySet 仅返回 3 个此人未参与的项目,此人的姓名也与项目名称相似。
>>> sqs = SearchQuerySet().filter(content__auto=q)
>>> sqs.count()
8
>>> sqs.models(Project)
[<SearchResult: project.project (pk=u'409')>, <SearchResult: project.project (pk=u'521')>, <SearchResult: project.project (pk=u'82')>]
我是不是做错了什么?感谢您的反馈:-)
我已经通过修改我的 filter() 查询获得了质量更好的结果。我在 django-haystack 文档中了解到 filter_or() 方法,可以根据需要多次连接。这样就很容易根据需要匹配尽可能多的字段 and/or 索引。例如:
sqs = SearchQuerySet().filter_or(content__contains=q).filter_or(employees__name__contains=q).filter_or(projects_name__contains=q)
# etc.
正如刚才所说,这大大提高了搜索结果的质量。
我使用 django-haystack + elasticsearch 在我的站点中设置了一个搜索索引。有不同的索引,通常它们可以正常工作,但当我搜索一个人时 ProjectIndex 除外。让我解释一下:
这些是型号:
class Person(models.Model):
first_name = models.CharField()
last_name = models.CharField()
class Project(models.Model):
project_name = models.CharField()
employees = models.ManyToManyField(Person)
这些是索引:
class ProjectIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.EdgeNgramField(document=True, use_template=True)
project_name = indexes.CharField(model_attr='project_name', boost=1.4)
employees = indexes.CharField(boost=1.5)
def get_model(self):
return Project
def prepare_employees(self, obj):
return ' '.join([employee.__unicode__() for employee in obj.employees.all()])
def prepare(self, obj):
data = super(ProjectIndex, self).prepare(obj)
data['boost'] = 1.3
return data
class PersonIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.EdgeNgramField(document=True, use_template=True)
first_name = indexes.CharField(model_attr='first_name', boost=1.1)
last_name = indexes.CharField(model_attr='last_name', boost=1.2)
def get_model(self):
return Person
当我 运行 rebuild_index 时,所有项目似乎都已正确编入索引。当我搜索一个人时对elasticsearch服务器的一个简单的http查询 returns 有用的项目结果(真的很有意义)。
>>> from urllib import urlopen
>>> response = urlopen('http://127.0.0.1:9200/_search?q=' + q)
>>> json_data = response.read()
>>> from json import loads
>>> d = loads(json_data)
>>> f = filter(lambda d: d['_source']['django_ct'] == "project.project", d['hits']['hits'])
>>> len(f)
8
另一方面,SearchQuerySet 仅返回 3 个此人未参与的项目,此人的姓名也与项目名称相似。
>>> sqs = SearchQuerySet().filter(content__auto=q)
>>> sqs.count()
8
>>> sqs.models(Project)
[<SearchResult: project.project (pk=u'409')>, <SearchResult: project.project (pk=u'521')>, <SearchResult: project.project (pk=u'82')>]
我是不是做错了什么?感谢您的反馈:-)
我已经通过修改我的 filter() 查询获得了质量更好的结果。我在 django-haystack 文档中了解到 filter_or() 方法,可以根据需要多次连接。这样就很容易根据需要匹配尽可能多的字段 and/or 索引。例如:
sqs = SearchQuerySet().filter_or(content__contains=q).filter_or(employees__name__contains=q).filter_or(projects_name__contains=q)
# etc.
正如刚才所说,这大大提高了搜索结果的质量。