MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Python- und MongoDB-Datenbankentwicklung

Wie im ersten Teil dieser Serie erwähnt:Python Database Programming with MongoDB, das Python-Modul PyMongo ist erforderlich, damit Python mit einer MongoDB-Datenbank kommunizieren kann. Um dies zu installieren, verwenden Sie den Befehl an der Windows-Eingabeaufforderung:

pip3 install pymongo

Die Installation von PyMongo sollte eine Ausgabe ähnlich der unten gezeigten erzeugen:

Abbildung 1 – Installieren des PyMongo-Moduls

Abhängig von der Python-Konfiguration wird ein zusätzliches Modul namens dnspython kann auch erforderlich sein:

pip3 install dnspython

Abbildung 2 – Installation von dnspython Modul

Einfügen von Daten in MongoDB mit Python

Der folgende Code erstellt 15 zufällig generierte Künstler und zwei Alben für jeden von ihnen:

# bad-band-name-maker-nosql.py

import sys
import random
import pymongo

part1 = ["The", "Uncooked", "Appealing", "Larger than Life", "Drooping", "Unwell", "Atrocious", "Glossy", "Barrage", "Unlawful"]
part2 = ["Defeated", "Hi-Fi", "Extraterrestrial", "Adumbration", "Limpid", "Looptid", "Cromulent", "Unsettled", "Soot", "Twinkle"]
part3 = ["Brain", "Segment", "\"Audio\"", "Legitimate Business", "\"Bob\"", "Sound", "Canticle", "Monsoon", "Preserves", "\"Cacophony\""]

part4 = ["Cougar", "Lion", "Lynx", "Ocelot", "Puma", "Jaguar", "Panther"]
part5 = ["Fodder", "Ersatz Goods", "Leftovers", "Infant Formula", "Mush", "Smoothie", "Milkshakes"]


def main(argv):
  # Connect to the RazorDemo database.
  client = pymongo.MongoClient("mongodb+srv://yourUser:[email protected]/RazorDemo?retryWrites=true&w=majority", 
    serverSelectionTimeoutMS=5000)
  artistsCollection = client["RazorDemo"]["Artists"]
  albumsCollection = client["RazorDemo"]["Albums"]

  # Generate 15 bad band names, and try to keep them unique.
  previousNames = ""
  nameCount = 0
  artistJson = []
  while (nameCount < 16):
    rand1 = random.randrange(0, 9)
    rand2 = random.randrange(0, 9)
    rand3 = random.randrange(0, 9)
    badName = part1[rand1] + ' ' + part2[rand2] + ' ' + part3[rand3]
    
    # Unlike with SQL-oriented databases, MongoDB allows for the insertion of multiple documents in a single statement.
    # In this case, the code will build a JSON list of all the band names to be inserted in a one fell swoop.
    if ("|" + previousNames + "|").find("|" + badName + "|") == -1: 
      #print ("Band name [" + str(nameCount) + "] is [" + badName + "]")
      # Don't forget to escape quotation marks!
      
      jsonEntry = { "artist_name" : badName }
      artistJson.append(jsonEntry)
      
      # Because there are no foreign key rules, the album names can be created 
      # and committed to the database before the artist names have been created.
      albumJson = []
      for y in range(1, 3):
        rand4 = random.randrange(0, len(part4))
        rand5 = random.randrange(0, len(part5))
        
        # No checks for uniqueness here. Peter Gabriel had 4 self-titled
        # albums after all.
        albumName = part4[rand4] + " " + part5[rand5]
        albumEntry = { "artist_name" : badName, "album_name" : albumName }
        albumJson.append(albumEntry)
      print (albumJson)
      albumsCollection.insert_many(albumJson)
      
      # Creates a bar-delimited list of previously used names.
      # MongoDB expects the application to enforce data integrity rules.
      if previousNames == "":
        previousNames = badName
      else:
        previousNames = previousNames + "|" + badName
      nameCount = 1 + nameCount
    else:
      print ("Found a duplicate of [" + badName + "]")

  print (artistJson)
  artistsCollection.insert_many(artistJson)

  # Close the Connection
  client.close()
  return 0

if __name__ == "__main__":
	main(sys.argv[1:])

Listing 6 - Creating Random Data

Eine interessante Beobachtung zu diesem Code, zumindest im Vergleich zu den SQL-orientierten Beispielen in Python-Datenbankprogrammierung mit SQL Express für Anfänger, ist, dass er viel einfacher ist, da es keine zusätzliche SQL-Komponente gibt. Die JSON-Funktionen sind bereits Teil von Python und der einzige MongoDB-bezogene Befehl ist insert_many() Funktionen, die ausgeführt werden, nachdem jeder Datensatz erstellt wurde. Noch praktischer ist, dass diese Befehle mit derselben Syntax in Python übereinstimmen, die in der MongoDB-Shell verwendet wird.

Aus Sicherheitsgründen gibt es Probleme wie SQL Injection in solchem ​​Code einfach nicht, nicht nur, weil kein SQL ausgeführt wird, sondern absolut kein Code an die Datenbank übergeben wird. Die Python-Listenfunktion kümmert sich auch um Probleme wie das Escapezeichen von Anführungszeichen.

Anstatt die Ausgabe im Eingabeaufforderungsfenster anzuzeigen, wird stattdessen ein anderer Codeabschnitt verwendet, um die Datenbank abzufragen.

Validieren der Inserts mit Python

Der folgende Code fragt die MongoDB-Datenbank nach den oben mit Python durchgeführten Einfügeaktionen ab:

# bad-band-name-display-nosql.py

import sys
import pymongo

def main(argv):
  # Connect to the RazorDemo database.
  client = pymongo.MongoClient("mongodb+srv://yourUser:[email protected]/RazorDemo?retryWrites=true&w=majority", 
    serverSelectionTimeoutMS=5000)
  artistsCollection = client["RazorDemo"]["Artists"]
  albumsCollection = client["RazorDemo"]["Albums"]

  print ("Albums:")
  artists = artistsCollection.find()
  
  for artist in artists:
    print (str(artist["artist_name"]))
    albumQuery = { "artist_name": {"$eq" : str(artist["artist_name"])} }
    albumsForThisArtist = albumsCollection.find(albumQuery)
    for album in albumsForThisArtist:
      print ("\t" + str(album["album_name"]))

  # Close the Connection
  client.close()
  return 0

if __name__ == "__main__":
	main(sys.argv[1:])

Listing 7 - Validating the Insert Actions

Die folgende Ausgabe enthält die Anfangsdokumente, die weiter oben im Dokument erstellt wurden:

Abbildung 3 – Validierung der Einfügungen

MongoDB-Daten mit Python abfragen

Der obige Code kann in ein interaktives Tool angepasst werden, um die Daten mit Benutzereingaben abzufragen. MongoDB bietet ein leistungsstarkes Textsuchwerkzeug für seine Sammlungen, aber um es zu aktivieren, müssen Textindizes für die zu durchsuchenden Sammlungen erstellt werden:

db.Artists.createIndex({artist_name: "text"})

db.Albums.createIndex({artist_name: "text", album_name: "text"})

Listing 8 - Creating Text Indices for each collection

Beachten Sie, dass MongoDB nur einen Textindex pro Sammlung zulässt. Der Versuch, einen anderen Index für einen anderen Knoten in einer Sammlung zu erstellen, führt zu einem Fehler. Die Ausgabe dieser Befehle in der MongoDB-Shell ist unten:

Abbildung 4 – Hinzufügen von Textindizes

Während das Textsuchtool alle möglichen verrückten Matching-Logiken mit regulären Ausdrücken und partiellen Matches mit Näherungsranking ausführen kann, bleibt das folgende Beispiel bei einem einfachen Matching, um den Machbarkeitsnachweis zu veranschaulichen:

# bad-band-name-query-nosql.py

import sys
import pymongo

def main(argv):
  searchValue = input("Enter something: ")
  # Cap the length at something reasonable. The first 20 characters.
  searchValue = searchValue[0:20]
  # Set the search value to lower case so we can perform case-insensitive matching:
  searchValue = searchValue.lower()

  # Connect to the RazorDemo database.
  client = pymongo.MongoClient("mongodb+srv://yourUser:[email protected]/RazorDemo?retryWrites=true&w=majority", 
    serverSelectionTimeoutMS=5000)
  artistsCollection = client["RazorDemo"]["Artists"]
  albumsCollection = client["RazorDemo"]["Albums"]

  matchedArtists = "";
  artists = artistsCollection.find( { "$text":{ "$search": searchValue} })

  for artist in artists:
    matchedArtists = matchedArtists + "\t" + str(artist["artist_name"]) + "\r\n"
  if "" == matchedArtists:
    print ("No matched artists.")
  else:
    print ("Matched Artists:")
    print (matchedArtists)

  
  albums = albumsCollection.find( { "$text":{ "$search": searchValue} })
  matchedAlbums = ""
  for album in albums:
    matchedAlbums = matchedAlbums + "\t" + str(album["artist_name"]) + " - " + str(album["album_name"]) + "\r\n"
    
  if "" == matchedAlbums:
    print ("No matched albums.")
  else:
    print ("Matched Albums:")
    print (matchedAlbums)
    
  # Close the Connection
  client.close()
  return 0

if __name__ == "__main__":
	main(sys.argv[1:])


Listing 9 - Querying the data

Beachten Sie, dass keine Konvertierung der aus MongoDB kommenden Daten erforderlich war, um sie mit der kleingeschriebenen Version des Suchbegriffs abzugleichen.

Abschließende Gedanken zur Python- und MongoDB-Entwicklung

Für Entwickler, die mit SQL-orientierten Datenbankservern und Datenbanken kodiert haben, kann sich der Sprung zu noSQL anfühlen, als würde man eine sehr steile Lernkurve erklimmen, aber durch das Abbilden vertrauter SQL-Datenbankkonzepte auf ihre NoSQL-Pendants wird der Aufstieg etwas weniger unangenehm . Solche Entwickler sind möglicherweise sogar schockiert über das Fehlen „grundlegender“ „Funktionen“ wie die Durchsetzung von Fremdschlüsseln oder die Erwartung, dass es die Anwendung und nicht die Datenbank ist, von der erwartet wird, dass sie die Datenintegritätsregeln durchsetzt. Für sehr erfahrene SQL-orientierte Datenbankentwickler fühlt sich sogar der bloße Gedanke an solche Ideen fast wie Ketzerei beim Programmieren an!

Aber NoSQL-Datenbanken wie MongoDB fügen viele weitere Funktionen hinzu, die das Umdenken lohnenswert machen. Sich nicht um eine weitere Version von SQL kümmern zu müssen, die „gerade anders genug“ ist, um lästig zu sein, oder sich nicht über Probleme wie SQL-Injection Gedanken machen zu müssen, in der Lage zu sein, mehrere Datensätze, ähm, Datendokumente sicher einzufügen, ohne den Aufwand von „ Tausende“ von Einzelaussagen und vielleicht sogar unterhaltsam Die „verrückte“ Idee, dass die Datendurchsetzung durch die Anwendung einen großen Teil des Aufwands für die Anwendungsentwicklung einspart, ist eine Überlegung wert.