1
1
from django .utils .encoding import force_str
2
2
from elasticsearch_dsl import Q
3
3
from haystack .backends import BaseEngine , BaseSearchBackend , BaseSearchQuery , log_query
4
+ from haystack .forms import ModelSearchForm
4
5
from haystack .models import SearchResult
5
6
from haystack .utils import log as logging
6
7
@@ -18,6 +19,7 @@ def __init__(self, connection_alias, **connection_options):
18
19
connection_alias ,
19
20
** connection_options )
20
21
self .manager = ArticleDocumentManager ()
22
+ self .include_spelling = True
21
23
22
24
def _get_models (self , iterable ):
23
25
models = iterable if iterable and iterable [0 ] else Article .objects .all ()
@@ -51,15 +53,40 @@ def remove(self, obj_or_string):
51
53
def clear (self , models = None , commit = True ):
52
54
self .remove (None )
53
55
56
+ @staticmethod
57
+ def get_suggestion (query : str ) -> str :
58
+ """获取推荐词, 如果没有找到添加原搜索词"""
59
+
60
+ search = ArticleDocument .search () \
61
+ .query ("match" , body = query ) \
62
+ .suggest ('suggest_search' , query , term = {'field' : 'body' }) \
63
+ .execute ()
64
+
65
+ keywords = []
66
+ for suggest in search .suggest .suggest_search :
67
+ if suggest ["options" ]:
68
+ keywords .append (suggest ["options" ][0 ]["text" ])
69
+ else :
70
+ keywords .append (suggest ["text" ])
71
+
72
+ return ' ' .join (keywords )
73
+
54
74
@log_query
55
75
def search (self , query_string , ** kwargs ):
56
76
logger .info ('search query_string:' + query_string )
57
77
58
78
start_offset = kwargs .get ('start_offset' )
59
79
end_offset = kwargs .get ('end_offset' )
60
80
61
- q = Q ('bool' , should = [Q ('match' , body = query_string ), Q (
62
- 'match' , title = query_string )], minimum_should_match = "70%" )
81
+ # 推荐词搜索
82
+ if getattr (self , "is_suggest" , None ):
83
+ suggestion = self .get_suggestion (query_string )
84
+ else :
85
+ suggestion = query_string
86
+
87
+ q = Q ('bool' ,
88
+ should = [Q ('match' , body = suggestion ), Q ('match' , title = suggestion )],
89
+ minimum_should_match = "70%" )
63
90
64
91
search = ArticleDocument .search () \
65
92
.query ('bool' , filter = [q ]) \
@@ -85,7 +112,7 @@ def search(self, query_string, **kwargs):
85
112
** additional_fields )
86
113
raw_results .append (result )
87
114
facets = {}
88
- spelling_suggestion = None
115
+ spelling_suggestion = None if query_string == suggestion else suggestion
89
116
90
117
return {
91
118
'results' : raw_results ,
@@ -134,6 +161,22 @@ def get_count(self):
134
161
results = self .get_results ()
135
162
return len (results ) if results else 0
136
163
164
+ def get_spelling_suggestion (self , preferred_query = None ):
165
+ return self ._spelling_suggestion
166
+
167
+ def build_params (self , spelling_query = None ):
168
+ kwargs = super (ElasticSearchQuery , self ).build_params (spelling_query = spelling_query )
169
+ return kwargs
170
+
171
+
172
+ class ElasticSearchModelSearchForm (ModelSearchForm ):
173
+
174
+ def search (self ):
175
+ # 是否建议搜索
176
+ self .searchqueryset .query .backend .is_suggest = self .data .get ("is_suggest" ) != "no"
177
+ sqs = super ().search ()
178
+ return sqs
179
+
137
180
138
181
class ElasticSearchEngine (BaseEngine ):
139
182
backend = ElasticSearchBackend
0 commit comments