MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Développement de bases de données Python et MongoDB

Comme mentionné dans la première partie de cette série :Python Database Programming with MongoDB, le module Python PyMongo est nécessaire pour que Python puisse communiquer avec une base de données MongoDB. Pour l'installer, utilisez la commande à l'invite de commande Windows :

pip3 install pymongo

L'installation de PyMongo devrait produire une sortie similaire à celle illustrée ci-dessous :

Figure 1 – Installation du module PyMongo

Selon la configuration Python, un module supplémentaire nommé dnspython peut également être nécessaire :

pip3 install dnspython

Figure 2 – Installation de dnspython module

Comment insérer des données dans MongoDB avec Python

Le code ci-dessous créera 15 artistes générés aléatoirement et deux Albums pour chacun d'eux :

# 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

Une observation intéressante à propos de ce code, du moins par rapport aux exemples orientés SQL dans Python Database Programming with SQL Express for Beginners, est qu'il est beaucoup plus simple, car il n'y a pas de composant SQL supplémentaire. Les fonctions JSON font déjà partie de Python et la seule commande liée à MongoDB est insert_many() fonctions exécutées après la création de chaque ensemble de données. Encore plus pratique, ces commandes correspondent à la même syntaxe en Python que celle utilisée dans le shell MongoDB.

Du point de vue de la sécurité, des problèmes tels que SQL Injection n'existent tout simplement pas dans un tel code, non seulement parce qu'aucun code SQL n'est exécuté, mais absolument aucun code n'est transmis à la base de données. La fonctionnalité Python List prend également en charge des problèmes tels que l'échappement des guillemets.

Au lieu d'afficher la sortie dans la fenêtre d'invite de commande, un autre morceau de code sera utilisé pour interroger la base de données à la place.

Valider les insertions avec Python

Le code ci-dessous interrogera la base de données MongoDB pour les actions d'insertion effectuées ci-dessus à l'aide de 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

La sortie ci-dessous contient les documents initiaux créés plus haut dans le document :

Figure 3 – Validation des insertions

Interroger des données MongoDB avec Python

Le code ci-dessus peut être adapté en un outil interactif pour interroger les données avec l'entrée de l'utilisateur. MongoDB fournit un puissant outil de recherche de texte pour ses collections, mais pour l'activer, des index de texte doivent être créés sur les collections à rechercher :

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

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

Listing 8 - Creating Text Indices for each collection

Notez que MongoDB n'autorise qu'un seul index de texte par collection. Tenter de créer un autre index pour un nœud différent dans une collection provoquera une erreur. La sortie de ces commandes dans MongoDB Shell est ci-dessous :

Figure 4 – Ajout d'index de texte

Alors que l'outil de recherche de texte peut effectuer toutes sortes de logiques de correspondance folles impliquant des expressions régulières et des correspondances partielles avec un classement de proximité, l'exemple ci-dessous s'en tiendra à une correspondance simple, afin d'illustrer la preuve de 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

Notez qu'aucune conversion des données provenant de MongoDB n'a été nécessaire pour les faire correspondre à la version minuscule du terme de recherche.

Réflexions finales sur le développement Python et MongoDB

Pour les développeurs qui ont codé sur des serveurs de bases de données et des bases de données orientés SQL, le saut vers noSQL peut donner l'impression de mettre à l'échelle une courbe d'apprentissage très abrupte, mais en mappant des concepts de base de données SQL familiers à leurs homologues NoSQL, cela devient un peu moins inconfortable d'une montée . Ces développeurs peuvent même être choqués par le manque de "fonctionnalités" "de base" telles que l'application des clés étrangères ou l'attente selon laquelle c'est l'application et non la base de données qui est censée appliquer les règles d'intégrité des données. Pour les développeurs de bases de données orientés SQL très chevronnés, même la simple pensée de telles idées ressemble presque à une hérésie de programmation !

Mais les bases de données NoSQL comme MongoDB ajoutent de nombreuses autres fonctionnalités qui font que le changement de mentalité en vaut la peine. Ne pas avoir à se soucier d'une autre version de SQL qui est "juste assez différente" pour être ennuyeuse, ou ne pas avoir à penser à des problèmes comme l'injection SQL, être capable d'insérer plusieurs enregistrements, euh, des documents de données en toute sécurité sans les tracas de " des milliers" de déclarations individuelles, et peut-être même divertissant l'idée "folle" que le fait que l'application s'occupe de l'application des données supprime une énorme partie des efforts de développement d'applications vaut la peine d'être prise en compte.