pythonelasticsearchflaskwhoosh

I need help implementing a keyword search in Flask with Flask-msearch


I am using version 3.9 of python and attempting to create a keyword search where a user can enter a string of keywords and that string can be queried against the database containing strings. There are no errors in compilation and everything runs but the result of the query is not what I expect. Instead of returning all of the rows that contain similar words to the keyword from the description column it returns the query in string form.

This is my init.py file:

import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_msearch import Search
...
app = Flask(__name__)
searched = Search(app)
searched.init_app(app)
searched.create_index(update=True)
MSEARCH_INDEX_NAME =  os.path.join(app.root_path,'msearch')
MSEARCH_ENABLE = True
from .search import search as search_blueprint
app.register_blueprint(search_blueprint)

return app

This is my models.py file

class Service (db.Model):
    __searchable__  = ['description']
    provider_id     = db.Column(db.Integer, db.ForeignKey('provider.provider_id'), nullable=False)
    service_id      = db.Column(db.Integer, nullable=False, primary_key=True)
    rating_avg      = db.Column(db.Float(precision=2), nullable=False)
    service_name    = db.Column(db.String(20), nullable=False)
    cost            = db.Column(db.Float(precision=2), nullable=False)
    description     = db.Column(db.String(255), nullable=False)
    category        = db.Column(db.String(20), nullable=False)
    
    def __repr__(self):
        return 'String representation of Service'

This is my search.py file:


search = Blueprint('search', __name__)

@search.route('/search')
def searching():
    return render_template('search.html')

@search.route('/search', methods=['POST'])
def searching_post():
    searchInput = request.form.get('searchInput')
    results = Service.query.msearch(searchInput, fields= ['description'])
    return render_template('result.html', results=results)

This is my search.html template file:

{% extends "base.html" %}

{% block content %}
<div class="column is-8 is-offset-2">
    <h1 class ="title">
    Enter keywords and minimum rating
    </h1>
    <div class="box">
        <form method="POST" action="/search">
        <div class="field">
                    <div class="form-group">
                    <input class="input is-large" type="text" name="searchInput" placeholder=" " autofocus="">
                    </div>
                </div>
        <button class="button is-block is-info is-large is-fullwidth">Search</button>
         </form>
    </div>
</div>
{% endblock %}

This is the result I get when I search anything in the searchbar:

Results: SELECT service.provider_id AS service_provider_id, service.service_id AS service_service_id, service.rating_avg AS service_rating_avg, service.service_name AS service_service_name, service.cost AS service_cost, service.description AS service_description, service.category AS service_category FROM service WHERE (service.description LIKE '%' || ? || '%')!

Solution

  • msearch returns a Query object and when you print your results variable you see its string representation - the underlying SQL query.

    To get the actual results you need to 'execute' the query, e.g.

    results = Service.query.msearch(searchInput, fields= ['description']).all()
    

    The following method calls would also cause the execution of the underlying query:

    results = Service.query.msearch(searchInput, fields= ['description']).first()
    results = Service.query.msearch(searchInput, fields= ['description']).one()
    results = Service.query.msearch(searchInput, fields= ['description']).one_or_none()