Я получаю эту ошибку, когда пытаюсь использовать ElasticSearch для запроса одного индекса, но не другого:
elasticsearch.exceptions.RequestError: RequestError(400, 'search_phase_execution_exception', 'failed to
create query: {\n "multi_match" : {\n "query" : "bob",\n "fields" : [\n
"additional_comments^1.0",\n "age^1.0",\n "first_name^1.0",\n "gender^1.0",\n
"needs^1.0",\n "program_number^1.0",\n "read^1.0",\n "sheet_size^1.0",\n
"shoe_size_category^1.0",\n "shoe_sock_size^1.0",\n "shoe_type^1.0",\n
"time_chosen^1.0",\n "wants^1.0",\n "wear^1.0"\n ],\n "type" : "best_fields",\n
"operator" : "OR",\n "slop" : 0,\n "fuzziness" : "50",\n "prefix_length" : 0,\n
"max_expansions" : 50,\n "zero_terms_query" : "NONE",\n "auto_generate_synonyms_phrase_query" :
true,\n "fuzzy_transpositions" : true,\n "boost" : 1.0\n }\n}')
У меня следующий запрос ES:
def query_object(index, fields, query, page, per_page, fuzziness=0):
print(index)
print(query)
print(fields)
search = current_app.elasticsearch.search(
index=index,
body={'query': {'multi_match': {'query': query, 'fields': fields, 'fuzziness': fuzziness}},
'from': (page - 1) * per_page, 'size': per_page}
)
ids = [int(hit['_id']) for hit in search['hits']['hits']]
return ids, search['hits']['total']['value']
Вот Метод класса для поиска, который является родительским для обоих доступных для поиска классов:
class SearchableMixin(object):
@classmethod
def search_object(cls, fields, expression, page, per_page, fuzziness=0):
ids, total = query_object(
cls.__tablename__, fields, expression, page, per_page, fuzziness=fuzziness)
if total == 0:
return cls.query.filter_by(id=0), 0
when = []
for i in range(len(ids)):
when.append((ids[i], i))
return cls.query.filter(cls.id.in_(ids)).order_by(
db.case(when, value=cls.id)), total
Вот класс пользователя:
class User(db.Model, UserMixin, SearchableMixin):
__searchable__ = ['email', 'phone', 'street_address',
'city', 'state', 'zip_code', 'last_reminded']
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(100), unique=True)
phone = db.Column(db.String(20), nullable=True, default=None)
password = db.Column(db.String(200))
street_address = db.Column(db.String(100))
city = db.Column(db.String(100))
state = db.Column(db.String(52))
zip_code = db.Column(db.String(10))
last_reminded = db.Column(db.String(40), default=datetime.utcnow().strftime(
"%A, %B %e{}, %Y".format(suffix(datetime.today().day))))
admin = db.Column(db.Boolean, default=False)
wish_lists = db.relationship('WishList', backref='sponsor', lazy='dynamic')
drives = db.relationship(
'HolidayCheerDrive', secondary=years, lazy='dynamic')
А вот класс WishList:
class WishList(db.Model, SearchableMixin):
__searchable__ = ['program_number', 'first_name', 'age', 'gender', 'wants', 'needs', 'wear',
'read', 'shoe_sock_size', 'shoe_size_category', 'shoe_type', 'sheet_size', 'additional_comments', 'time_chosen',
]
id = db.Column(db.Integer, primary_key=True)
program_number = db.Column(db.String(4))
first_name = db.Column(db.String(20))
age = db.Column(db.String(10))
gender = db.Column(db.String(20))
wants = db.Column(db.String(300))
needs = db.Column(db.String(300))
wear = db.Column(db.String(300))
read = db.Column(db.String(300))
pant_dress_size = db.Column(db.String(20), default='unspecified')
shirt_blouse_size = db.Column(db.String(20), default='unspecified')
jacket_sweater_size = db.Column(db.String(20), default='unspecified')
shoe_sock_size = db.Column(db.String(20), default='unspecified')
shoe_size_category = db.Column(db.String(20), default='unspecified')
shoe_type = db.Column(db.String(50), nullable=True, default=None)
sheet_size = db.Column(db.String(20))
additional_comments = db.Column(db.Text(), nullable=True, default=None)
time_chosen = db.Column(db.String(40), nullable=True, default=None)
sponsor_id = db.Column(db.Integer, db.ForeignKey(
'user.id'), nullable=True, default=None)
drive_id = db.Column(db.Integer, db.ForeignKey(
'holiday_cheer_drive.id'), nullable=False, default=None)
Я попытался удалить поисковый термин time_chosen
, потому что он еще не определен, но это не помогло. Я также пытался искать только в одном поле, и это тоже не сработало. Когда я ищу пользователя, он не возвращает никаких ошибок. Насколько я могу судить, маршруты python не содержат ошибок, вот они:
@bp.route('/manage_users', methods=['GET', 'POST'])
#@admin_only
def manage_users():
form = SearchUsersForm()
page = request.args.get('page', 1, type=int)
if not form.validate():
all_users = User.query.all()
total = len(all_users)
start = ((page-1) * current_app.config['RESULTS_PER_PAGE'])
end = (start + current_app.config['RESULTS_PER_PAGE'])
if end >= total:
display_users = all_users[start:]
else:
display_users = all_users[start:end]
else:
if form.fields.data == 'default':
fields = [field for field in User.__searchable__]
elif form.fields.data == 'address':
fields = ['street_address', 'city', 'state', 'zip_code']
else:
fields = [form.fields.data]
fuzzy = True
if fuzzy:
fuzziness = 50
else:
fuzziness = 0
display_users, total = User.search_object(fields, form.q.data, page,
current_app.config['RESULTS_PER_PAGE'], fuzziness=fuzziness)
q = form.q.data if form.q.data else None
next_url = url_for('admin.manage_users', q=q, page=page + 1) \
if total > page * current_app.config['RESULTS_PER_PAGE'] else None
prev_url = url_for('admin.manage_users', q=q, page=page - 1) \
if page > 1 else None
context = {
'next_url': next_url,
'prev_url': prev_url,
'display_users': display_users,
'form': form,
}
return render_template('/admin/manage_users.html', **context)
@bp.route('/manage_wish_lists', methods=['GET', 'POST'])
#@admin_only
def manage_wish_lists():
form = SearchWishListsForm()
page = request.args.get('page', 1, type=int)
if not form.validate():
all_wish_lists = WishList.query.all()
total = len(all_wish_lists)
start = ((page-1) * current_app.config['RESULTS_PER_PAGE'])
end = (start + current_app.config['RESULTS_PER_PAGE'])
if end >= total:
display_lists = all_wish_lists[start:]
else:
display_lists = all_wish_lists[start:end]
else:
if form.fields.data == 'default':
fields = [field for field in WishList.__searchable__]
elif form.fields.data == 'wish_list_items':
fields = ['wants', 'need', 'wear', 'read']
elif form.fields.data == "shoes":
fields = ['shoe_sock_size', 'shoe_size_category', 'shoe_type']
else:
fields = [form.fields.data]
fuzzy = True
if fuzzy:
fuzziness = 50
else:
fuzziness = 0
display_lists, total = WishList.search_object(fields, form.q.data, page,
current_app.config['RESULTS_PER_PAGE'], fuzziness=fuzziness)
q = form.q.data if form.q.data else None
next_url = url_for('admin.manage_wish_lists', q=q, page=page + 1) \
if total > page * current_app.config['RESULTS_PER_PAGE'] else None
prev_url = url_for('admin.manage_wish_lists', q=q, page=page - 1) \
if page > 1 else None
context = {
'next_url': next_url,
'prev_url': prev_url,
'display_lists': display_lists,
'form': form,
}
return render_template('/admin/manage_wish_lists.html', **context)
Я не понимаю. Я запрашиваю очень похожий объект с тем же запросом, и все, включая индекс и запросы, печатаются правильно в терминал.
в функции поиска, которую я добавляю:
print(index)
print(query)
print(fields)
import json
body={'query': {'multi_match': {'query': query, 'fields': fields, 'fuzziness': fuzziness}},
'from': (page - 1) * per_page, 'size': per_page}
print(json.dumps(body))
search = current_app.elasticsearch.search(
index=index,
body={'query': {'multi_match': {'query': query, 'fields': fields, 'fuzziness': fuzziness}},
'from': (page - 1) * per_page, 'size': per_page}
)
print(json.dumps(search))
Отредактированный вывод для этих print
операторов
Для объекта User:
#INDEX NAME
user
#QUERY TERMS
bob
#SEARCH FIELDS
['email', 'phone', 'street_address', 'city', 'state', 'zip_code', 'last_reminded']
#BODY OF SEARCH
{"query": {"multi_match": {"query": "bob", "fields": ["email", "phone", "street_address", "city", "state", "zip_code", "last_reminded"], "fuzziness": 50}}, "from": 0, "size": 10}
#SEARCH JSON
{"took": 18, "timed_out": false, "_shards": {"total": 1, "successful": 1, "skipped": 0, "failed": 0}, "hits": {"total": {"value": 0, "relation": "eq"}, "max_score": null, "hits": []}}
Для объекта WishList:
#INDEX NAME
wish_list
#QUERY TERMS
bob
#SEARCH FIELDS
['program_number', 'first_name', 'age', 'gender', 'wants', 'needs', 'wear', 'read', 'shoe_sock_size', 'shoe_size_category', 'shoe_type', 'sheet_size', 'additional_comments', 'time_chosen']
#BODY OF SEARCH
{"query": {"multi_match": {"query": "bob", "fields": ["program_number", "first_name", "age", "gender", "wants", "needs", "wear", "read", "shoe_sock_size", "shoe_size_category", "shoe_type", "sheet_size", "additional_comments", "time_chosen"], "fuzziness": 50}}, "from": 0, "size": 10}
#Cannot build query so search object never instantiates
Разница лишь в том, что объект User не выдает мне ошибку и возвращает результат поиска, который я вижу на своей странице HTML. Объект WishList, когда запросы выдают ошибку, которую я вставил выше.
Пожалуйста, дайте мне знать ... что-то не так с моими маршрутами? Можно ли индексировать слишком много полей? additional_comments
- текстовый столбец вместо строкового столбца; Возможно ли, что это может сыграть свою роль?
Я в растерянности. Помощь очень ценится. Заранее спасибо!
Изменения: Я добавляю вывод на мой серверный терминал ElasticSearch, если это будет полезно. Это JSON может быть лучше воспринимается лучше, если говорить визуально?