# -*- coding: utf-8 -*-
"""
app.search
~~~~~~~~~~
This module implements the search interface.
:copyright: (c) 2018 European Spallation Source ERIC
:license: BSD 2-Clause, see LICENSE for more details.
"""
from flask import current_app
[docs]def delete_index(index, **kwargs):
"""Delete the given index"""
if not current_app.elasticsearch:
return
current_app.elasticsearch.indices.delete(index=index, **kwargs)
[docs]def create_index(index, mapping, **kwargs):
"""Create an index with the given mapping"""
if not current_app.elasticsearch:
return
body = {"mappings": {"dynamic": "strict", "properties": mapping}}
current_app.elasticsearch.indices.create(index=index, body=body, **kwargs)
[docs]def add_to_index(index, body):
"""Add a document to an index"""
if not current_app.elasticsearch:
return
# We remove the id key because it's used as the id of the document.
# Using the model id as document id allows to easily retrieve
# the model linked to a document
id = body.pop("id")
current_app.elasticsearch.index(
index=index,
id=id,
body=body,
refresh=current_app.config["ELASTICSEARCH_REFRESH"],
)
[docs]def remove_from_index(index, id):
"""Remove a document from the index"""
if not current_app.elasticsearch:
return
current_app.elasticsearch.delete(
index=index, id=id, refresh=current_app.config["ELASTICSEARCH_REFRESH"]
)
[docs]def query_index(index, query, page=1, per_page=20, sort=None):
"""Run a search query on the index
Return a BaseQuery (with the ids found) and the total number of hits as a tuple
"""
if not current_app.elasticsearch:
return [], 0
kwargs = {
"index": index,
"q": query,
"from_": (page - 1) * per_page,
"size": per_page,
}
if sort is not None:
kwargs["sort"] = sort
current_app.logger.debug(f"Search: {kwargs}")
search = current_app.elasticsearch.search(**kwargs)
ids = [int(hit["_id"]) for hit in search["hits"]["hits"]]
return ids, search["hits"]["total"]["value"]
[docs]def update_document(index, id, partial_doc):
"""Update partially a document
:param index: elasticsearch index
:param id: document id
:param dict partial_doc: fields to update
"""
if not current_app.elasticsearch:
return
current_app.elasticsearch.update(
index=index,
id=id,
body={"doc": partial_doc},
refresh=current_app.config["ELASTICSEARCH_REFRESH"],
)