sql >> Databáze >  >> NoSQL >> HBase

Vytvoření jednoduché webové aplikace CRUD a úložiště obrázků pomocí Cloudera Operational Database a Flask

Cloudera Operational Database (COD) je spravované řešení dbPaaS dostupné jako zkušenost v Cloudera Data Platform (CDP). Nabízí multimodální klientský přístup s hodnotou klíče NoSQL pomocí Apache HBase API a relačního SQL s JDBC (prostřednictvím Apache Phoenix). Ten zpřístupňuje COD vývojářům, kteří jsou zvyklí vytvářet aplikace využívající MySQL, Postgres atd. Mezi hlavní výhody COD patří:

  • Automatické škálování – je založeno na pracovní zátěži clusteru a brzy bude mít možnost škálovat nahoru/dolů cluster
  • Automatické ladění – lepší výkon v rámci stávající infrastruktury.
  • Automatické léčení – automatické řešení provozních problémů (již brzy).

V tomto blogu ukážu, jak lze COD snadno použít jako backendový systém pro ukládání dat a obrázků pro jednoduchou webovou aplikaci. K vytvoření této aplikace budeme používat Phoenix, jednu ze základních komponent COD, spolu s Flask. Pro ukládání obrázků budeme používat funkci HBase (základní úložiště Apache Phoenix) nazvanou MOB (střední objekty). MOB nám umožňuje rychle číst/zapisovat hodnoty od 100k-10MB.

*Pro usnadnění vývoje můžete místo COD použít také dotazovací server Phoenix. Dotazovací server je malé sestavení phoenix, které je určeno pouze pro účely vývoje a v každém sestavení jsou data smazána.

Veškerý kód je v mém repozitáři github.

Pokyny:

1. Přihlaste se do Cloudera Management Console a vyberte prostředí Operational Database

2. Vyberte své prostředí a pojmenujte svou DB

3. Jakmile je databáze spuštěna, vezměte URL z tenkého klienta JDBC

4. Nastavte heslo pro pracovní zátěž CDP

5. Klonujte projekt git repo a požadavky na instalaci:$ pip install -r requirements.txt

6. Přejděte do složky aplikace a spusťte „setup.py“ – tím se vytvoří tabulka se 3 záznamy uživatelů a jejich obrázky $ python setup.py

7. Spusťte webový server flask pro webovou aplikaci, aby se spustila:$ FLASK_APP=app.py python -m flask run –port=8888 –host=127.0.0.1  –reload –with-threads –debugger

8. Přejděte v prohlížeči na adresu http://localhost:8888/users. Měli byste vidět spuštěnou aplikaci! Jak jednoduché.

Procházení kódu

1. Třída Schema,  V podstatě obsahuje podrobnosti o připojení a metody vytváření a vypouštění tabulky. Jak můžete vidět, sloupec „fotka“ je typu VARBINARY, který se překládá jako objekt MOB v HBase:

import phoenixdb
import phoenixdb.cursor
class Schema:
    def __init__(self):
        opts = {}
        opts['authentication'] = 'BASIC'
        opts['avatica_user'] = '<cod workload username>'
        opts['avatica_password'] = '<cod workload pw>'
        database_url = "<cod thin jdbc url>"
        self.TABLENAME = "users"
        self.conn = phoenixdb.connect(database_url, autocommit=True,**opts)
        self.curs = self.conn.cursor()

    def create_users_table(self):
        query = """
        CREATE TABLE IF NOT EXISTS """+self.TABLENAME+""" (
        username VARCHAR NOT NULL,
        firstname VARCHAR,
        lastname  VARCHAR,
        telephone VARCHAR,
        message VARCHAR,
        email VARCHAR,
        photo VARBINARY,
        photo_name VARCHAR,
        photo_type VARCHAR,
        photo_chars VARCHAR
        CONSTRAINT my_pk PRIMARY KEY (username))
        """
        self.curs.execute(query)

    def drop_users_table(self):
        query = "DROP TABLE "+self.TABLENAME
        self.curs.execute(query)

2 Třída uživatelů je zodpovědná za všechny operace aplikací s Phoenix. Můžeme aktualizovat/vkládat (upsert v jazyce phoenix) , mazat, vypisovat a zpracovávat transakce s obrázky:

import phoenixdb
from schema import Schema
import json
class UsersModel:
    TABLENAME = "users"

    def __init__(self):
        db = Schema()
        self.conn=db.conn
        self.curs=db.curs

    def upsert(self, params):

        sql = "upsert into " + self.TABLENAME + \
            " (username ,message,telephone,firstname,lastname,email) \
             values (?,?,?,?,?,?)"
        data = (params.get('username'),params.get('message'),\
            params.get('telephone'),params.get('firstname'),\
            params.get('lastname'),params.get('email'))
        results = self.curs.execute(sql,data)
        return results

    def upsert_photo(self, params):
        if params.get('photo') is None:
            photo = bytes('','utf-8')
        else:
            photo = params.get('photo')

        sql = "upsert into " + self.TABLENAME + \
            " (username, photo,photo_name) values (?,?,?)"

        data = (params.get('username'),photo, params.get('photo_name'))
        results = self.curs.execute(sql,data)
        return results

    def delete(self, username):
        query = f"DELETE from {self.TABLENAME} " \
                f"WHERE username = {username}"

        self.curs.execute(query)

    def list_items(self, where_clause="",format="json"):
        query = f"SELECT username ,email,message,telephone,firstname,\
            lastname,photo_name " \
            f"from {self.TABLENAME} WHERE  " + where_clause

        self.curs.execute(query)
        if format=="json":
            r = [dict((self.curs.description[i][0].lower(), value) \
                   for i, value in enumerate(row)) for row in \
                   self.curs.fetchall()]
            self.conn.close()
            data={'data': r }
            return json.dumps(data)

        result_set=self.curs.fetchall()
        result = [{column: row[i]
            for i, column in enumerate(result_set[0].keys())}
                for row in result_set]
        return result
    def get_image(self, username):
        query = f"SELECT photo,photo_name " \
                f"from {self.TABLENAME} WHERE  username='"+username+"'"

        self.curs.execute(query)
        row = self.curs.fetchone()
        return row

3. App.py je hlavní směrovač pro aplikaci. Obsahuje veškerou manipulaci s uživatelskými vstupy a jejich směrování na metody připojení. Oddělil jsem manipulaci s obrázky pro snadné použití, a tak mohu získat konkrétní obrázek pro uživatele:

from flask import Flask, request, send_file ,jsonify,render_template
import phoenixdb
import io
from users import UsersModel
from schema import Schema
import json

app = Flask(__name__)

@app.after_request
def add_headers(response):
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Headers'] =  \
        "Content-Type, Access-Control-Allow-Headers, Authorization, \
        X-Requested-With"
    response.headers['Access-Control-Allow-Methods']=  "POST, GET, PUT, \
    DELETE, OPTIONS"
    response.headers['Allow']=  "POST, GET, PUT, OPTIONS"
    return response

@app.route("/")
def hello():
    return "Hello World!"

@app.route("/users")
def return_form():
    return render_template("users.html")

@app.route("/handle_data",methods=['POST'])
def handle_data():
    if request.method == 'POST':
        username = request.form['username']
        firstname = request.form['firstname']
        lastname = request.form['lastname']
        email = request.form['email']
        telephone = request.form['telephone']
        message = request.form['message']
        photo = request.files['photo']
        photo_bytes = photo.read()
        model=Schema()
        usersmodel=UsersModel()
        data = {'username':f"{username}",'firstname':f"{firstname}",\
            'lastname':f"{lastname}",'telephone':f"{telephone}",\
            'message':f"{message}"}
        photo_data = {'username':f"{username}",\
            'photo':photo_bytes,\
            'photo_name':f"{photo.filename}"}
        usersmodel.upsert(data)
        usersmodel.upsert_photo(photo_data)
        return render_template('users.html')
    else:
        return render_template('users.html')

@app.route("/get_users",methods=['GET'])
def get_users():
    if request.method == 'GET':
        usersmodel=UsersModel()
        users = usersmodel.list_items("1=1")
        return users

@app.route("/get_image",methods=['GET'])
def get_image():
    if request.method == 'GET':
        username = request.args.get('username')
        usersmodel=UsersModel()
        imagedb = usersmodel.get_image(username)
        return send_file(io.BytesIO(imagedb[0]),mimetype='image/png', \
            attachment_filename=imagedb[1])

if __name__ == "__main__":
    Schema()
    app.run(debug=True, port=8888)

V dalších krocích můžete použít toto úložiště github k testování své aplikace.

Doufám, že to pro vás bude užitečné, Veselé kódování!!


  1. Redis Sentinely s TLS

  2. Aktualizujte položku v poli, které je v poli

  3. Pořadí odpovědí na MongoDB $v dotazu?

  4. Výkon MongoDB na agregační dotazy