[PYTHON] Wissensdatenbank + Web-API, die von NoSQL x PaaS betrieben wird

Was ist das

Dies ist eine Zusammenfassung des Know-hows beim Erstellen einer Wissensdatenbank + Web-API mit NoSQL und PaaS.

Bei der Implementierung einer Architektur namens "String Tag-orientierte ungerichtete Graph Knowledge Base" Ein Beispiel, das mit Heroku + Redis + FastAPI erstellt wurde, Hier ist ein Beispiel, das mit AWS (DynamoDB + Lambda + API Gateway) erstellt wurde.

Alle Codeteile verwenden Python3.8.0.

Was ist eine Wissensbasis?

Es gibt verschiedene Definitionen der Wissensbasis, aber in diesem Artikel Bezieht sich auf "eine Datenbank, in der Wissen in einem computerlesbaren Format gespeichert wird". Es wird auch als "Wissensdatenbank", "Wissensdatenbank", "KB" bezeichnet.

Referenzlink (zum Öffnen klicken)

String Base-orientierte, ungerichtete Wissensdatenbank

Dies ist die Wissensbasis, die diesmal als Beispiel erstellt werden soll. Ich denke, es ist schwierig, nur den Namen zu verstehen, deshalb habe ich ein Bilddiagramm erstellt. (Da die Visualisierung nicht implementiert ist, erstellen Sie sie mit dem Mind Map Tool coggle.)

スクリーンショット 2019-12-03 20.00.32.png

Die Rolle dieser Wissensbasis

Durch Wiederholen der einfachen Operation "Speichern von zwei Zeichenketten" Es soll ein wörterbuchartiges Wissenssystem (kollektives Wissen) bilden.

Und Sie benötigen eine Web-API, um sie mit explosiver Geschwindigkeit zu erweitern.

Über "Zeichenfolgen-Tag-orientiert"

Diese Wissensdatenbank behandelt nur Zeichenfolgendaten (und deren Satz) Behandle alle Zeichenfolgen als Tags.

Im obigen Beispiel Web Service Name``` Account ID`` URL`` Artikeltitel `` Konzept Programmiersprache Jede Zeichenfolge wird beispielsweise als ein Tag behandelt.

Aufgrund der Spezifikationen enthält die Zeichenfolge keine Leerzeichen oder Zeilenvorschubzeichen.

Über "ungerichteten Diagrammtyp"

In dieser Wissensdatenbank versuchen wir, verwandte Tags zu verbinden.

Zum Beispiel das Tag "Framework" Rails Laravel Django Flask Sie können die Daten erhalten, mit denen das Tag verknüpft ist.

スクリーンショット 2019-12-03 20.43.44.png

Beispielsweise sind sowohl die Tags "Qiita" als auch "Python" verknüpft. https://qiita.com/1ntegrale9/items/94ec4437f763aa623965 Sie können die Daten wie das Tag abrufen (Qiitas Artikel-URL zu Python).

スクリーンショット 2019-12-03 20.44.33.png

In der obigen Abbildung repräsentieren die Eckpunkte (Zeichenfolgen) Tags und die Seiten Beziehungen. Und da es ungeeignet ist, kann auf beide Bezug genommen werden. Darüber hinaus erfolgt keine Gewichtung, da die Einschlussbeziehung nicht berücksichtigt wird.

Referenzartikel: Grundlagen der Graphentheorie - Qiita

Zusatzinformationen

Diese Architektur ist nicht im Umlauf Inspiriert von GraphQL wurde es ursprünglich entwickelt.

Es ist also nur eine leichte Umfrage mit Schlüsselwörtern pro GraphDB Vielleicht existiert es schon.

Konstruktionsbeispiel: Redis + FastAPI + Heroku

Wenn Sie es einfach und kostenlos bedienen möchten, verwenden Sie dies.

Die anfänglichen Einstellungen von Heroku und die grundlegenden Operationen von Redis werden hier erklärt. Einführung in NoSQL DB beginnend mit Heroku x Redis x Python - Qiita

Redis

KVS ist speicherintern und schnell zu lesen und zu schreiben. Es unterstützt auch die Persistenz. Ich möchte einem Tag mehrere Tags zuordnen, daher verwende ich nur den kollektiven Typ.

Bibliotheksinstallation

Verwenden Sie redis-py, da es von Python verwaltet wird.

python3 -m pip install redis hiredis

employeeis-py ist ein schneller Parser-Wrapper für die C-Implementierung. Die Redis-Py-Seite erkennt Hiredis und schaltet den Parser um. Legen Sie ihn also ein.

Stellen Sie eine Verbindung zu Redis her

Initialisieren Sie die Verbindung mit dem folgenden Code. Verwenden Sie die Umgebungsvariable "REDIS_URL", die Heroku Redis automatisch festlegt.

import redis, os
conn = redis.from_url(os.environ['REDIS_URL'], decode_responses=True)

Standardmäßig liegt also ein Problem mit der japanischen Anzeige vor decode_responses = True ist erforderlich.

Holen Sie sich alle Tags

Holen Sie es sich mit keys ().

def get_all_tags():
    return sorted(conn.keys())

Es ist praktisch, die Tags in einer Liste anzuzeigen. Seien Sie also vorbereitet. Bitte beachten Sie jedoch, dass die Last mit zunehmender Skalierung zunimmt.

Holen Sie sich das zu verknüpfende Tag

Holen Sie es sich mit smembers (key).

def get_related_tags(tag):
    r.smembers(tag) if r.exists(tag) else []

Wenn vorsichtshalber ein nicht vorhandenes Tag angegeben wird, wird ein leeres Array zurückgegeben. Verwenden Sie exist (Schlüssel), um die Existenz zu überprüfen.

Speichern Sie zwei Tags in Verbindung miteinander

Verwenden Sie "sadd (Schlüssel, Wert)", um aggregierte Daten zu speichern. Ich möchte sie in beide Richtungen verknüpfen, also tausche ich die Schlüsselwerte aus und führe sie zweimal aus.

def set_relation_tags(tag1, tag2):
    return conn.pipeline().sadd(t1, t2).sadd(t2, t1).execute()

Redis unterstützt Transaktionen für Redis-Py Durch Verketten von "Pipeline ()" mit "Execute ()" Eine Stapelausführung innerhalb einer Transaktion ist möglich.

Außerdem scheint die atomare Ausführung durch die Pipeline-Methode schneller zu sein als die individuelle Ausführung. Effiziente Verwendung von Redis in Python (um die Leistung von Redis-py zu verbessern) - [Dd] enzow (krank)? Mit DB und Python / 08/212059)

FastAPI

FastAPI ist eines der Python-Webframeworks Sie können eine einfache Web-API mit weniger Code implementieren Die Funktion besteht darin, dass das API-Dokument automatisch ohne Einstellungen generiert wird.

Flask Responder Starlette DRF usw. sind über Spezifikationen, Im Gegenteil, Bottle fehlte die Funktion, und die Fast-API war genau richtig.

Bibliotheksinstallation

python3 -m pip install fastapi uvicorn email-validator

Uvicorn ist ein schneller ASGI-Server. Wird zum Starten von FastAPI verwendet. Es ist kein Tippfehler in Gunicorn.

Wenn Sie email-validator nicht angeben, werden Sie beim Start wütend. Warum?

Anwendungsinitialisierung

Es ist sehr einfach.

main.py


from fastapi import FastAPI
app = FastAPI()

Wenn Sie die Argumente "Titel" und "Beschreibung" setzen, Der Titel und die Beschreibung werden wie im obigen Bild im automatisch generierten API-Dokument wiedergegeben.

main.py


app = FastAPI(
    title='collective-intelligence',
    description='String Base-orientierte, ungerichtete Wissensdatenbank',
)

Sie können die API-Dokument-URL auch ändern, indem Sie "docs_url" angeben. Der Standardwert ist "/ docs", aber es ist eine gute Idee, ihn als root beizubehalten.

main.py


app = FastAPI(docs_url='/')

Holen Sie sich alle Tags

Schreiben Sie einfach die HTTP-Methode (GET), die URL und den Rückgabewert. Sie können eine JSON-Antwort erhalten, indem Sie eine Liste oder ein Wörterbuch zurückgeben.

main.py


@app.get('/api')
def read_all_tags():
    return get_all_tags()

Diese Definition wird automatisch in API Doc widergespiegelt. Sie können die Anfrage auch über "Try it out" oben rechts ausführen.

Holen Sie sich das Tag, das dem angegebenen Tag zugeordnet ist

Das Tag soll eine beliebige Zeichenfolge mit Symbolen sein. Da die Abfragezeichenfolge nicht damit umgehen kann, belassen Sie sie als POST.

main.py


@app.post('/api/pull')
def read_related_tags(tag: str):
    return get_related_tags(tag)

Das im Argument angegebene tag: str wird vom Anfragetext akzeptiert. Ich habe eine Typanmerkung angehängt, mit der die Anforderung validiert wird. Wenn es nicht übereinstimmt, lautet die Antwort "422 Validation Error".

Speichern Sie zwei Tags in Verbindung miteinander

FastAPI heißt pydantic Enthält eine Bibliothek zur Verwendung von Typanmerkungen. Verwenden Sie diese Option, um Ihren eigenen Typ zu definieren und zur Validierung zu verwenden.

main.py


from pydantic import BaseModel

class Tags(BaseModel):
    tag1: str
    tag2: str

@app.post('/api/push')
def create_tags_relationship(tags: Tags):
    set_tags_relationship(tags.tag1, tags.tag2)
    return {tag: get_related_tags(tag) for _, tag in tags}

Der definierte Typ wird in API Doc als Schema wiedergegeben.

Starten Sie FastAPI

Beginnen Sie mit dem zuvor eingeführten Uvicorn. Wenn Sie mit app in main.py initialisiert haben, geben Sie main: app an. Mit der Option "--reload" wird es neu geladen und angezeigt, wenn die Datei geändert wird.

$ uvicorn main:app --reload
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [57749]
INFO:     Started server process [57752]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

Wenn Sie auf "http: //127.0.0.1: 8000" oder "http: //127.0.0.1: 8000 / docs" zugreifen, Sie können sehen, dass das API-Dokument angezeigt wird.

Heroku

PaaS, mit dem Sie Webanwendungen einfach bereitstellen können. Es unterstützt viele Sprachen und Frameworks. PostgreSQL und Redis hosten bis zu einem bestimmten Limit kostenlos.

Zunächst sind die folgenden Schritte erforderlich.

Vorbereitung der notwendigen Dateien

Sie benötigen folgende Dateien: Haben Sie dies in Ihrem GitHub-Repository.

$ tree
.
├── main.py          #Anwendung
├── Procfile         #Befehlsdefinitionsdatei für die Prozessausführung
├── requirements.txt #Abhängige Bibliotheksdefinitionsdatei
└── runtime.txt      #Python-Versionsdefinitionsdatei

Procfile


web: uvicorn main:app --host 0.0.0.0 --port $PORT

requirements.txt


fastapi
email-validator
uvicorn
redis
hiredis

runtime.txt


python-3.8.0

[Aktuelles Verzeichnis](1ntegrale9 / kollektive Intelligenz bei Heroku ) Siehe auch.

Anwendung bereitstellen

Führen Sie die Bereitstellung auf der Registerkarte Bereitstellen des Dashboards durch. Verknüpfen Sie das Repository in Zusammenarbeit mit GitHub und führen Sie "Manual Deploy" aus. Wenn Sie auch "Automatische Bereitstellungen" festlegen, wird diese automatisch bereitgestellt, wenn Sie auf Master drücken.

スクリーンショット 2019-12-19 14.45.06.png

Sobald der Build erfolgreich abgeschlossen wurde Lassen Sie den registrierten Prozess unter Configure Dynos eingeschaltet.

スクリーンショット 2019-12-19 14.48.21.png

Sie können die bereitgestellte Anwendung unter "App öffnen" in der oberen rechten Ecke des Dashboards anzeigen.

Konstruktionsbeispiel: AWS (DynamoDB + Lambda + API Gateway)

Bitte warten Sie auf die Veröffentlichung, während sie geschrieben wird

Wenn Sie sich der Skalierbarkeit bewusst sind, verwenden Sie diese. Es ist auch möglich, die Datenstruktur flexibel zu ändern.

Erste API-Entwicklung mit Lambda und DynamoDB-Qiita API Gateway + Lambda + DynamoDB - Qiita

Amazon DynamoDB

Wie bei RDB sind eine Tabelle und ein Primärschlüssel grundlegend. Der Primärschlüssel ist ein Schlüssel, der die Daten eindeutig identifiziert und entweder ein "Partitionsschlüssel" oder ist Es bedeutet "zusammengesetzter Schlüssel aus Partitionsschlüssel und Sortierschlüssel". Sie können die eindeutigen Einschränkungen für Partitionsschlüssel lockern, indem Sie Sortierschlüssel hinzufügen.

So starten Sie --Amazon DynamoDB | AWS Entwickeln der ersten serverlosen Anwendung - Erstellen einer Tabelle in DynamoDB- | Developers.IO Verständnis der Fähigkeit von DynamoDB, Ihr Bestes im kostenlosen Rahmen zu geben - Zwei Schwerter des IT- und Muskeltrainings

Tischgestaltung

Partitionsschlüssel: Tag Sortierschlüssel: Zeitstempel

Eine Tabelle erstellen

AWS Lambda

Entwickeln der ersten serverlosen Anwendung - Abrufen des Werts von DynamoDB mit Lambda- | Developers.IO Automatische Bereitstellung in AWS Lambda mithilfe von GitHub-Aktionen (detailliert + Demo-Verfahren ver) --Qiita

Speichern Sie zwei Tags in Verbindung miteinander

Die Funktion lambda_handler wird ausgeführt, wenn Lambda aufgerufen wird

import boto3, time
from decimal import Decimal

def lambda_handler(event, context):
    timestamp = Decimal(time.time())
    table = boto3.resource('dynamodb').Table('collective-intelligence')
    with table.batch_writer() as batch: #Batch bei mehreren Puts_Verwenden Sie Writer
        batch.put_item(Item={
            'tag': event['tag1'],
            'related_tag': event['tag2'],
            'timestamp': timestamp
        })
        batch.put_item(Item={
            'tag': event['tag2'],
            'related_tag': event['tag1'],
            'timestamp': timestamp
        })
    return {'statusCode': 201}

Holen Sie sich das Tag, das dem angegebenen Tag zugeordnet ist

import boto3
from boto3.dynamodb.conditions import Key

def lambda_handler(event, context):
    table = boto3.resource('dynamodb').Table('collective-intelligence')
    response = table.query(KeyConditionExpression=Key('tag').eq(event['tag'])) #Suche nach Tag-Spezifikation
    tags = set(item['related_tag'] for item in response['Items']) #Im festgelegten Typ speichern und Duplikate entfernen
    return {'statusCode': 200, 'body': list(tags)} #In Listentyp für JSON-Antwort umwandeln

Amazon API Gateway

Erstellt und verwaltet Web-APIs

Entwicklung des ersten serverlosen Lambda-Aufrufs von API Gateway- | Developers.IO Erstellen einer API-Gateway-Umgebung zum Lernen beim Erstellen von Grund auf neu | Developers.IO Amazon API Gateway-Lernprogramm - Amazon API Gateway

Ressourcen und Methoden erstellen

Erstellen Sie POST mit / push und / pull

Festlegen der Anforderungsvalidierung

Das Spielen vor dem Ausführen von Lambda kann die Kosten senken

--Modelldefinition (JSON-Schema) --Einstellungen-> Stellen Sie "Körper überprüfen" in der Anforderungsvalidierung ein

  • Modell im Anforderungshauptteil festlegen

JSON Schema Tool Erstellen von Anforderungs- und Antwortzuordnungsmodellen und Zuordnungsvorlagen - Amazon API Gateway (https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/models-mappings.html) Ich habe die neue Funktion Request Validation of API Gateway - MTI Engineer Blog ausprobiert

Eine Methode erstellen

create-method.png

Methodenauswahl

create-post.png

Methodenverwaltungsbildschirm

do-pull.png

Erstellen eines PULL-Modells

model-pull.png

Erstellen eines PUSH-Modells

model-push.png

Festlegen der Anforderungsvalidierung

request-pull.png

PULL-API-Test

test-pull.png

PUSH API-Test

test-push.png

In Bezug auf Nutzungsgebühren

Überprüfen Sie von der Rechnung auf dem Abrechnungsbildschirm.

Es ist noch nicht in Produktion, Als Ergebnis des Sendens und Empfangens von Hunderten von Anfragen / Antworten im Test waren es also 0 Yen Es scheint, dass Sie keine Angst haben sollten, es für Testzwecke zu verwenden.

スクリーンショット 2019-12-05 19.39.49.png

GCP vs AWS

Ich habe mir Sorgen um GCP (Firestore) und AWS (DynamoDB) gemacht, aber ich habe DynamoDB übernommen.

Wenn Sie sich auf der GCP-Seite entscheiden, werden Sie von den vier Datenspeicherdiensten beunruhigt sein. Wenn Sie es als Hobby verwenden, sollten Sie sich für Firestore entscheiden. Wählen Sie eine Datenbank aus: Cloud Firestore oder Echtzeitdatenbank | Firebase

Am Ende

Diese sind meistens Selbststudium, Ich denke, die Fähigkeiten zum Erlernen neuer Fähigkeiten wurden im modernen Umfeld des Unternehmens erworben. Es ist eine großartige Erfahrung für einen starken Ingenieur, in dem Bereich arbeiten zu können, in dem neue Technologien hart eingesetzt werden.

Darüber hinaus ist die Konfiguration auf der Heroku-Seite für die Öffentlichkeit zugänglich. Die Daten sind zum Zeitpunkt der Veröffentlichung leer, können jedoch jederzeit berührt werden. https://collective-intelligence.herokuapp.com/

Recommended Posts

Wissensdatenbank + Web-API, die von NoSQL x PaaS betrieben wird