sql >> Database teknologi >  >> NoSQL >> MongoDB

Python og MongoDB databaseudvikling

Som nævnt i første del af denne serie:Python-databaseprogrammering med MongoDB, Python-modulet PyMongo er påkrævet for at Python kan kommunikere med en MongoDB-database. For at installere dette skal du bruge kommandoen ved Windows-kommandoprompten:

pip3 install pymongo

Installation af PyMongo skulle producere et output svarende til det, der er vist nedenfor:

Figur 1 – Installation af PyMongo-modulet

Afhængigt af Python-konfigurationen, et ekstra modul ved navn dnspython kan også være nødvendigt:

pip3 install dnspython

Figur 2 – Installation af dnspython modul

Sådan indsætter du data i MongoDB med Python

Koden nedenfor vil skabe 15 tilfældigt genererede kunstnere og to album for hver af dem:

# 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

En interessant observation om denne kode, i det mindste sammenlignet med de SQL-orienterede eksempler i Python Database Programming med SQL Express for Beginners, er, at det er meget enklere, da der ikke er nogen ekstra SQL-komponent. JSON-funktionerne er allerede en del af Python, og den eneste MongoDB-relaterede kommando er insert_many() funktioner, der udføres efter hvert datasæt er oprettet. Endnu mere praktisk, disse kommandoer matcher den samme syntaks i Python, som bruges i MongoDB Shell.

Fra et sikkerhedssynspunkt eksisterer problemer som SQL Injection simpelthen ikke i sådan kode, ikke kun fordi der ikke udføres SQL, men absolut ingen kode overhovedet bliver sendt ind i databasen. Python List-funktionaliteten tager sig også af problemer som at undslippe anførselstegn.

I stedet for at vise outputtet i kommandopromptvinduet, vil et andet stykke kode blive brugt til at forespørge databasen i stedet.

Validering af indsættelserne med Python

Koden nedenfor vil forespørge MongoDB-databasen om indsætningshandlingerne ovenfor ved hjælp af Python:

# 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

Outputtet nedenfor indeholder de indledende dokumenter, der er oprettet længere oppe i dokumentet:

Figur 3 – Validering af indsatserne

Søge MongoDB-data med Python

Ovenstående kode kan tilpasses til et interaktivt værktøj til at forespørge dataene med brugerinput. MongoDB leverer et kraftfuldt tekstsøgningsværktøj til sine samlinger, men for at aktivere det skal der oprettes tekstindekser på de samlinger, der skal søges i:

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

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

Listing 8 - Creating Text Indices for each collection

Bemærk, at MongoDB kun tillader ét tekstindeks pr. samling. Forsøg på at oprette et andet indeks for en anden node i en samling vil forårsage en fejl. Outputtet af disse kommandoer i MongoDB Shell er nedenfor:

Figur 4 – Tilføjelse af tekstindekser

Mens tekstsøgeværktøjet kan udføre alle mulige skøre matchende logikker, der involverer regulære udtryk og delvise matches med nærhedsrangering, vil eksemplet nedenfor holde sig til simpel matchning for at illustrere proof of concept:

# 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

Bemærk, at det ikke var nødvendigt at konvertere de data, der kom ud af MongoDB, for at matche dem med den lille version af søgeordet.

Sidste tanker om Python- og MongoDB-udvikling

For udviklere, der har kodet mod SQL-orienterede databaseservere og databaser, kan springet til noSQL føles som at skalere en meget stejl indlæringskurve, men ved at kortlægge velkendte SQL-databasekoncepter til deres NoSQL-modstykker, bliver det lidt mindre ubehageligt at klatre. . Sådanne udviklere kan endda være chokeret over manglen på "grundlæggende" "funktioner" såsom håndhævelse af fremmednøgler eller forventningen om, at det er applikationen og ikke databasen, der forventes at håndhæve reglerne for dataintegritet. For meget erfarne SQL-orienterede databaseudviklere føles selv tanken om sådanne ideer næsten som at programmere kætteri!

Men NoSQL-databaser som MongoDB tilføjer mange andre funktioner, der gør ændringen i tankegangen det værd. Ikke at skulle bekymre dig om endnu en version af SQL, der er "bare anderledes nok" til at være irriterende, eller ikke behøver at tænke på problemer som SQL-injektion, at kunne indsætte flere poster, fejl, dokumenter af data sikkert uden besværet med " tusindvis af individuelle udsagn, og måske endda underholdende den "skøre" idé om, at lade applikationen udføre datahåndhævelsen barberer en stor del af applikationsudviklingsindsatsen af, gør det hele værd at overveje.


  1. Hvordan henvises til et andet skema i mit Mongoose-skema?

  2. Sådan gendannes en specifik samling i MongoDB ved hjælp af logisk sikkerhedskopiering

  3. Er der en måde at flushall på en klynge, så alle nøgler fra master og slaver slettes fra db

  4. Hvordan finder man sæt skæringspunkter mellem dokumenterne i en enkelt samling i MongoDB?