Uso de matraz para implementar la función de búsqueda web basada en elasticsearch

Visión de conjunto

Llevo un mes haciendo estas prácticas a distancia y me siento bastante bien, el sueldo de 200 diarios no es bajo para un universitario. La semana pasada, los líderes asignaron nuevas tareas para esta semana. El requisito general es hacer una página de búsqueda del lado web, y la lógica general se muestra en la siguiente figura:

En primer lugar, puede ver que el lado web puede usar matraz o streamlit, pero estoy más familiarizado con el matraz, así que lo escribí con el matraz. La idea general es dejar que el usuario elija primero el tipo de archivo cargado, ya sea cargar la ID de Pubmed y buscar en función de esta ID, o cargar la palabra clave y buscar el título y el resumen en función de las frases clave. Luego está la rutina, un botón de envío y un botón de carga de archivos. Después de cargar el archivo, la lógica de back-end es acceder a elasticserach para recuperarlo de acuerdo con las opciones y la información del archivo cargado, y luego generar un archivo csv.El archivo csv contiene tres columnas de pmid, título y resumen, y luego usar el línea de comando para poner el archivo en el sistema de almacenamiento S3, el líder tenía miedo de que no lo entendiera, por lo que también escribió la línea de comando almacenada en S3. Luego, una vez que todo haya terminado, devuelva un mensaje de éxito al front-end.

Implementación frontal

Para la parte delantera, utilizo la plantilla jinjia2 de bootstrap y matraz. No utilicé flass-bootstrap, principalmente porque no estoy muy familiarizado con él. Solía ​​usar django, pero django es demasiado inflado para este sistema simple, así que sigo usando la idea original de bootstrap y la plantilla de django para el desarrollo. . La página de inicio se muestra aproximadamente de la siguiente manera:

 Aquí está mi código de plantilla:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Uploads</title>
    <link rel="stylesheet" href="{
   
   { url_for('static', filename='css/bootstrap.min.css') }}">
    <script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
    <script src="{
   
   { url_for('static', filename='js/bootstrap.bundle.js') }}"></script>
    <script src="{
   
   { url_for('static', filename='js/bootstrap.bundle.min.js') }}"></script>
</head>
<body>

<form method="post" enctype="multipart/form-data" action="{
   
   { url_for('upload') }}">
    <div class="jumbotron">
    <h1 class="display-4">Upload Files</h1>
    <hr class="my-4">
    <p>Choose file type.</p>
    <div class="form-group">
    <select name="option" class="form-control">
      <option >Pubmed ids</option>
      <option >Key phrases</option>
    </select>
    <hr class="my-4">
    <p>Choose your local file to upload.</p>
    <input type="file" name="file_name">
    <hr class="my-4">
    <input class="btn btn-primary btn-lg" type="submit"></input>
    </div>
    <ul>
    {% for message in get_flashed_messages() %}
        <div class="alert alert-warning alert-dismissible fade show" role="alert">
            {
   
   { message }}
  <button type="button" class="close" data-dismiss="alert" aria-label="Close">
    <span aria-hidden="true">&times;</span>
  </button>
</div>
    {% endfor %}
    </ul>
    </div>

</form>



</div>
</body>
</html>

Se puede ver que hay este párrafo, que no se muestra en la imagen de arriba.Esto se usa con la función de parpadeo del matraz. Es equivalente a enviar mensajes de back-end al front-end de una manera más amigable y conveniente. Específicamente, se usa para devolver el "mensaje de éxito" mencionado anteriormente y otros mensajes de error.

    <ul>
    {% for message in get_flashed_messages() %}
        <div class="alert alert-warning alert-dismissible fade show" role="alert">
            {
   
   { message }}
  <button type="button" class="close" data-dismiss="alert" aria-label="Close">
    <span aria-hidden="true">&times;</span>
  </button>
</div>
    {% endfor %}
    </ul>

Puede ver la siguiente pantalla, cómo se muestra el mensaje flash en la parte frontal:

Aquí hay una muestra del mensaje de éxito:

 Aquí está el mensaje de error:

 implementación de back-end

A continuación, hablemos de la implementación del backend. De todos modos, solo una página es muy ligera, por lo que no es necesario escribir un segundo archivo. Escríbalo directamente en el archivo manage.py. Pero la desventaja es que si hay tareas de desarrollo en el futuro, es necesario trasladarlas. Ahora, por conveniencia, todo está escrito en manage.py.

Primero necesitamos una función de enrutamiento y otra configuración general, utilicé el soporte de extensión de Flass_script, para que pueda iniciarse desde la línea de comando como Django, por ejemplo, python manage.py runserver -p 8000 -r -d, puede ver es así Es muy similar a cómo se inicia Django.

import os

from elasticsearch import Elasticsearch
from flask import Flask, request, flash, redirect
from flask import render_template
from flask_script import Manager
import pandas as pd
import numpy as np


app = Flask(__name__)
# 启用类似Django的命令行支持
manage = Manager(app)
# app配置列表
app.config["SECRET_KEY"] = "yuetian"

# 首页路由
@app.route('/')
def index():
    return render_template('index.html')

Luego, debe escribir una función para enviar un formulario y cargar un archivo. Puede ver que la función de envío flash está escrita aquí. La lógica específica es que se ejecuta la función deal_with_XXX(), y si devuelve True, parpadeará Success! ! ! noticias. En su lugar, envíe: ¡Algo sale mal! ! ! Verifique el archivo que cargó. mensaje de error. No hablaré de otros detalles de carga. Se utiliza la interfaz nativa de Python Flass.

# 文件上传功能
@app.route('/upload/', methods=["POST"])
def upload():
    if request.method == "POST":
        file = request.files.get("file_name")
        file.save(f"fileSaved/{file.filename}")
        option = request.form["option"]
        if option == "Pubmed ids":
            res = deal_with_pmid(file.filename)
            if res is True:
                flash('success!!!')
                return redirect("/")
            else:
                flash('Something goes Wrong!!!Check the file that you uploaded.')
                return redirect("/")
        elif option == "Key phrases":
            res = deal_with_kp(file.filename)
            if res is True:
                flash('success!!!')
                return redirect("/")
            else:
                flash('Something goes Wrong!!!Check the file that you uploaded.')
                return redirect("/")
    elif request.method == "GET":
        return render_template('index.html')

Luego están las dos funciones deal_with_XXX(). Como sugiere el nombre, deal_with_pmid() se usa para procesar datos cuyo tipo de archivo de carga es pubmed ID, y uno es el tipo de datos cuyo tipo de procesamiento es la palabra clave. Los dos formatos de datos son más o menos los siguientes. En total, una búsqueda por línea.

1                                                                     enfermedad del corazón

2                                                                    variación genética 

3                                                                     Vía biológica

4

(formato de datos de tipo pubmedID) ( formato de datos de tipo de frases clave )          

 El código específico es el siguiente:

# 处理Pubmed ID类型文件
def deal_with_pmid(file_name):
    try:
        pmid_list = []
        title_list = []
        abstract_list =[]
        es = Elasticsearch(hosts=['http://52.14.194.191:9200'])
        list_pmid = open(f"fileSaved/{file_name}", "rb").readlines()
        for pmid in list_pmid:
            json_data = {
                "query": {
                    "match": {
                        "pmid": str(pmid)
                    }
                }
            }

            res = es.search(index="pubmed-paper-index-2", body=json_data)
            pmid_list.append(res["hits"]["hits"][0]["_source"]["pmid"])
            title_list.append(res["hits"]["hits"][0]["_source"]["title"])
            abstract_list.append(res["hits"]["hits"][0]["_source"]["abstract"])
        data = pd.DataFrame(np.array([pmid_list, title_list, abstract_list]).T, columns=["pmid", "title", "abstract"])
        data.to_csv(f"query/{data['pmid'].iloc[0]}~{data['pmid'].iloc[-1]}.csv")
        os.system(f"aws s3 cp query/{data['pmid'].iloc[0]}~{data['pmid'].iloc[-1]}.csv s3://meta-adhoc/nlp/es/ --recursive")
        return True
    except Exception:
        return False

# 处理Key Phrases类型文件
def deal_with_kp(file_name):
    try:
        pmid_list = []
        title_list = []
        abstract_list = []
        es = Elasticsearch(hosts=['http://52.14.194.191:9200'])
        kp_list = open(f"fileSaved/{file_name}", "rb").readlines()
        for kp in kp_list:
            key_list = str(kp).split(" ")
            json_data = {
                "query": {
                    "bool": {
                        "should":[
                            {
                                "match":{}
                            },
                            {
                                "match": {}
                            }

                        ]
                    }
                }
            }
            for key in key_list:
                json_data["query"]["bool"]["should"][0]["match"].update({"title": key})
                json_data["query"]["bool"]["should"][1]["match"].update({"abstract": key})

            res = es.search(index="pubmed-paper-index-2", body=json_data)
            for tmp in res["hits"]["hits"]:
                pmid_list.append(tmp["_source"]["pmid"])
                title_list.append(tmp["_source"]["title"])
                abstract_list.append(tmp["_source"]["abstract"])
        data = pd.DataFrame(np.array([pmid_list, title_list, abstract_list]).T, columns=["pmid", "title", "abstract"])
        data.to_csv(f"query/{data['pmid'].iloc[0]}.csv")
        os.system(f"aws s3 cp query/{data['pmid'].iloc[0]}.csv s3://meta-adhoc/nlp/es/ --recursive")
        return True
    except Exception:
        return False

Específicamente, cuando se trata de campos json, se debe tener en cuenta que el resultado de la búsqueda de tipo pmid debe ser un pmid correspondiente a un resultado, porque este se identifica de forma única y una búsqueda de palabras clave corresponde a múltiples resultados de búsqueda, así que use un bucle for para tratar con.


FIN

Supongo que te gusta

Origin blog.csdn.net/qq_41938259/article/details/124338119
Recomendado
Clasificación