0

Basically I have a table like this:

movieId name
1 White chicks
2 Inception
3 The Avengers: Endgame
4 Avatar: The Last Air Bender

My job is to retrieve all relevant movies based on a substring of the movie name. For example, if a user enters a substring such as "av" (e.g., they enter "http://localhost:5000/search/movies?name=av"), they will find movies like The Avengers and Avatar.

Because the assignment requires the use of a Model-View-Controller(MVC) design with a pool of open connections, I have created 3 separate python files (a model, a controller and a database). For full information, this is my database file (shown below):

from mysql.connector import pooling

class DatabasePool:
    connection_pool = pooling.MySQLConnectionPool(
                               pool_name="ws_pool",
                               pool_size=5,
                               host='localhost'
                               database='assignment',
                               user='root',
                               password='abc123')

    @classmethod
    def getConnection(cls):
        dbConn = cls.connection_pool.get_connection()
        return dbConn

This is my model file (shown below):

from model.DatabasePool import DatabasePool

class Movie:
    @classmethod
    def getRelevantMovies(cls,name):
        try:
            dbConn = DatabasePool.getConnection()
            cursor = dbConn.cursor(dictionary=True)
            sql = "select * from movie where name like % + %s + %"
            cursor.execute(sql,(name,))
            results = cursor.fetchall()
            return results
        finally:
            dbConn.close()

and this is my controller file (shown below):

from flask import Flask,jsonify,request
from model.Movie import Movie

app = Flask(__name__)
@app.route('/search/movies', methods=['GET'])

def getMoviesBySubstring(name):
    try:
        movieList = Movie.getRelevantMovies(name)

        if len(movieList)>0:
            foundData = {"Movies":movieList}
            return jsonify(foundData),200

        else:
            return jsonify({}),400

    except Exception as err:
        print(err)
        return jsonify({}),500

if __name__=="__main__":
    app.run(debug=True)

I am struggling to figure out how exactly can I modify the sql code (found in the model file) to take in whatever substring input entered by the user (e.g., http://localhost:5000/search/movies?name=av), select the relevant movies in the database (Avatar and The Avengers) and pass it back to the controller. I am only allowed to use the like operator. Most online guides (e.g., Check if a string contains a substring in SQL Server 2005, using a stored procedure) on the LIKE operator have given examples that require pre-specified queries (e.g., using %a% to find values that contain an "a"), which is not appropriate for my case.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Ebbinghaus
  • 95
  • 6

2 Answers2

1

I made it! You owe me a drink... really! :-)

Beforehand, I named main.py because I don't do Flask (but, yes, I tested it!).

In:

  • model/DatabasePool.py, you had a missing comma @7
  • model/Movie.py, the query had to be changed
  • main.py, Flask controllers do not expect as call parameters those from URLs as ?parm=val

model/DatabasePool.py

from mysql.connector import pooling

class DatabasePool:
    connection_pool = pooling.MySQLConnectionPool(
                               pool_name="ws_pool",
                               pool_size=5,
                               host='localhost',
                               database='assignment',
                               user='root', 
                               password='abc123')

    @classmethod
    def getConnection(cls):
        dbConn = cls.connection_pool.get_connection()
        return dbConn

model/Movie.py


class Movie:
    @classmethod
    def getRelevantMovies(cls,name):
        try:
            dbConn = DatabasePool.getConnection()
            cursor = dbConn.cursor(dictionary=True)
            sql = "select * from movie where name like %s"
            cursor.execute(sql, (f"%{name}%", ))
            results = cursor.fetchall()
            return results
        finally:
            dbConn.close()

main.py

from flask import Flask,jsonify,request
from model.Movie import Movie

app = Flask(__name__)

# https://stackoverflow.com/a/35189294/206413
# https://stackoverflow.com/a/51385027/206413
@app.route('/search/movies', methods=['GET'])
def getMoviesBySubstring():
    name = request.args['name']

    try:
        movieList = Movie.getRelevantMovies(name)

        if len(movieList)>0:
            foundData = {"Movies":movieList}
            return jsonify(foundData),200

        else:
            return jsonify({}),400

    except Exception as err:
        print(err)
        return jsonify({}),500

if __name__=="__main__":
    app.run(debug=True)

Oh. One more thing! Man, Python is awesome, but it's not built for web apps. React, Vue, .Net, Ruby/Rails are perfect alternatives.


Depricated


You are almost there.

I'm pretty sure these lines below yield an exception, right?

sql = "select * from movie where name like % + %s + %"
cursor.execute(sql,(name,))

Change them to:

sql = "select * from movie where name like %s"
cursor.execute(sql, (f"%{name}%", ))

I don't have a working environment here to check it. So... my apologies if it's syntactic wrong.

Marcus Vinicius Pompeu
  • 1,219
  • 1
  • 11
  • 24
  • Thank you for your help. Doesn't seem to work for me, I've tried solutions from both Vignesh and your's. Both return TypeError: getMoviesBySubstring() missing 1 required positional argument: 'name'. Nonetheless, really appreciate this – Ebbinghaus Nov 28 '21 at 17:54
  • @Ebbinghaus, `... missing 1 required argument...` has nothing to do with the `like` clause. Are you sure the code in your question is up-to-date? – Marcus Vinicius Pompeu Nov 28 '21 at 18:03
  • I gave my codes a second check (even re-wrote the entire thing) but still encounter the same error. I suspect the issue is with the control file (because the error kept referring to getMoviesBySubstring()) but it doesnt make sense to instantiate the movie class either. Please let me know if you need any further information! – Ebbinghaus Nov 28 '21 at 20:34
  • @Ebbinghaus, please, try this edited solution. Lemme know the results, ok? – Marcus Vinicius Pompeu Nov 28 '21 at 22:27
  • Marcus Vinicius Pompeu (still awaiting the day when the stack grants me @ powers) I just want to say thank you so much for your help! You have freed me from another week of suffering and I now see the importance of request.args. I definitely owe you several drinks :) Also, for learning's sake, may I know where can I learn more about this "f"%{name}%""? Thank you once again! – Ebbinghaus Nov 29 '21 at 09:29
  • @Ebbinghaus, the name is `f-string syntax`. Enjoy! https://www.google.com/search?q=python+f-string – Marcus Vinicius Pompeu Dec 01 '21 at 01:17
0

Use the below SQL statement:

sql = "select * from movie where name like %%{0}%%".format(name)
cursor.execute(sql)
Vignesh
  • 115
  • 9