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

Sviluppo di database Python e MongoDB

Come accennato nella prima parte di questa serie:Python Database Programming con MongoDB, il modulo Python PyMongo è necessario affinché Python sia in grado di comunicare con un database MongoDB. Per installarlo, usa il comando nel prompt dei comandi di Windows:

pip3 install pymongo

L'installazione di PyMongo dovrebbe produrre un output simile a quello mostrato di seguito:

Figura 1 – Installazione del modulo PyMongo

A seconda della configurazione di Python, un modulo aggiuntivo chiamato dnspython potrebbe anche essere necessario:

pip3 install dnspython

Figura 2 – Installazione di dnspython modulo

Come inserire dati in MongoDB con Python

Il codice seguente creerà 15 Artisti generati casualmente e due Album per ciascuno di essi:

# 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

Un'osservazione interessante su questo codice, almeno rispetto agli esempi orientati a SQL in Python Database Programming con SQL Express for Beginners, è che è molto più semplice, poiché non esiste un componente SQL aggiuntivo. Le funzioni JSON fanno già parte di Python e l'unico comando relativo a MongoDB è insert_many() funzioni che vengono eseguite dopo la creazione di ogni set di dati. Ancora più convenienti, questi comandi corrispondono alla stessa sintassi in Python utilizzata nella MongoDB Shell.

Dal punto di vista della sicurezza, problemi come SQL Injection semplicemente non esistono in tale codice, non solo perché non viene eseguito SQL, ma assolutamente nessun codice viene passato al database. La funzionalità Python List si occupa anche di problemi come l'escape delle virgolette.

Invece di mostrare l'output nella finestra del prompt dei comandi, verrà utilizzato un altro pezzo di codice per interrogare il database.

Convalida degli inserti con Python

Il codice seguente interrogherà il database MongoDB per le azioni di inserimento effettuate sopra utilizzando 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

L'output seguente contiene i documenti iniziali creati più in alto nel documento:

Figura 3 – Convalida degli inserti

Interrogazione di dati MongoDB con Python

Il codice sopra può essere adattato in uno strumento interattivo per interrogare i dati con l'input dell'utente. MongoDB fornisce un potente strumento di ricerca di testo per le sue raccolte, ma per abilitarlo, è necessario creare indici di testo sulle raccolte da cercare:

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

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

Listing 8 - Creating Text Indices for each collection

Nota che MongoDB consente solo un indice di testo per raccolta. Il tentativo di creare un altro indice per un nodo diverso in una raccolta causerà un errore. L'output di questi comandi in MongoDB Shell è il seguente:

Figura 4 – Aggiunta di indici di testo

Mentre lo strumento di ricerca del testo può eseguire tutti i tipi di logica di corrispondenza folle che coinvolgono espressioni regolari e corrispondenze parziali con classificazione di prossimità, l'esempio seguente si atterrà alla corrispondenza semplice, al fine di illustrare la dimostrazione del concetto:

# 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

Nota che non è stata necessaria alcuna conversione dei dati in uscita da MongoDB per abbinarli alla versione minuscola del termine di ricerca.

Considerazioni finali sullo sviluppo di Python e MongoDB

Per gli sviluppatori che hanno codificato su database e server di database orientati a SQL, il passaggio a noSQL può sembrare come scalare una curva di apprendimento molto ripida, ma mappando concetti di database SQL familiari alle loro controparti NoSQL, diventa un po' meno scomodo una scalata . Tali sviluppatori potrebbero anche essere scioccati dalla mancanza di "funzionalità" "di base" come l'applicazione di chiavi esterne o l'aspettativa che sia l'applicazione e non il database che dovrebbe applicare le regole di integrità dei dati. Per sviluppatori di database orientati all'SQL molto esperti, anche il solo pensiero di tali idee sembra quasi un'eresia di programmazione!

Ma i database NoSQL come MongoDB aggiungono molte altre funzionalità che fanno valere la pena cambiare modo di pensare. Non c'è bisogno di preoccuparsi dell'ennesima versione di SQL che è "abbastanza diversa" da essere fastidiosa, o di non dover pensare a problemi come SQL injection, essere in grado di inserire più record, err, documenti di dati in modo sicuro senza il fastidio di " migliaia” di affermazioni individuali e forse anche divertenti l'idea "folle" che l'applicazione dei dati all'applicazione riduca un'enorme parte degli sforzi di sviluppo delle applicazioni rende tutto ciò degno di considerazione.