sql >> Base de Datos >  >> NoSQL >> MongoDB

Desarrollo de bases de datos Python y MongoDB

Como se mencionó en la primera parte de esta serie:Programación de base de datos de Python con MongoDB, el módulo de Python PyMongo es necesario para que Python pueda comunicarse con una base de datos MongoDB. Para instalar esto, use el comando en el símbolo del sistema de Windows:

pip3 install pymongo

La instalación de PyMongo debería generar un resultado similar al que se muestra a continuación:

Figura 1:instalación del módulo PyMongo

Dependiendo de la configuración de Python, un módulo adicional llamado dnspython también puede ser necesario:

pip3 install dnspython

Figura 2:instalación de dnspython módulo

Cómo insertar datos en MongoDB con Python

El siguiente código creará 15 Artistas generados aleatoriamente y dos Álbumes para cada uno de ellos:

# 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

Una observación interesante sobre este código, al menos en comparación con los ejemplos orientados a SQL en Programación de base de datos Python con SQL Express para principiantes, es que es mucho más simple, ya que no hay un componente SQL adicional. Las funciones JSON ya forman parte de Python y el único comando relacionado con MongoDB es insert_many() funciones que se ejecutan después de crear cada conjunto de datos. Aún más conveniente, estos comandos coinciden con la misma sintaxis en Python que se usa en MongoDB Shell.

Desde el punto de vista de la seguridad, problemas como la inyección de SQL simplemente no existen en dicho código, no solo porque no se está ejecutando SQL, sino que no se está pasando absolutamente ningún código a la base de datos. La función Lista de Python también soluciona problemas como las comillas de escape.

En lugar de mostrar el resultado en la ventana del símbolo del sistema, se usará otra pieza de código para consultar la base de datos.

Validación de las inserciones con Python

El siguiente código consultará la base de datos de MongoDB para las acciones de inserción realizadas anteriormente usando 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

El siguiente resultado contiene los documentos iniciales creados más arriba en el documento:

Figura 3:Validación de las inserciones

Consultar datos de MongoDB con Python

El código anterior se puede adaptar a una herramienta interactiva para consultar los datos con la entrada del usuario. MongoDB proporciona una poderosa herramienta de búsqueda de texto para sus colecciones, pero para habilitarla, se deben crear índices de texto en las colecciones que se buscarán:

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

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

Listing 8 - Creating Text Indices for each collection

Tenga en cuenta que MongoDB solo permite un índice de texto por colección. Intentar crear otro índice para un nodo diferente en una colección generará un error. El resultado de estos comandos en MongoDB Shell es el siguiente:

Figura 4:Adición de índices de texto

Si bien la herramienta de búsqueda de texto puede realizar todo tipo de lógica de coincidencia loca que involucre expresiones regulares y coincidencias parciales con clasificación de cercanía, el siguiente ejemplo seguirá con la coincidencia simple para ilustrar la prueba de concepto:

# 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

Tenga en cuenta que no se necesitó ninguna conversión de los datos provenientes de MongoDB para hacerlos coincidir con la versión en minúsculas del término de búsqueda.

Reflexiones finales sobre el desarrollo de Python y MongoDB

Para los desarrolladores que han estado programando contra bases de datos y servidores de bases de datos orientados a SQL, el salto a noSQL puede sentirse como escalar una curva de aprendizaje muy empinada, pero al mapear los conceptos familiares de bases de datos SQL a sus contrapartes NoSQL, se vuelve un poco menos incómodo. . Dichos desarrolladores pueden incluso sorprenderse por la falta de "características" "básicas", como la aplicación de claves externas o la expectativa de que es la aplicación y no la base de datos la que se espera que haga cumplir las reglas de integridad de datos. Para los desarrolladores de bases de datos orientados a SQL muy experimentados, ¡incluso el mero pensamiento de tales ideas casi se siente como una herejía de programación!

Pero las bases de datos NoSQL como MongoDB agregan muchas otras características que hacen que valga la pena el cambio de pensamiento. No tener que preocuparse por otra versión de SQL que sea "lo suficientemente diferente" como para ser molesta, o no tener que pensar en cuestiones como la inyección de SQL, poder insertar múltiples registros, err, documentos de datos de forma segura sin la molestia de " miles” de declaraciones individuales, y tal vez incluso entretenidas la idea "loca" de que hacer que la aplicación se encargue de la aplicación de datos elimina una gran parte de los esfuerzos de desarrollo de la aplicación hace que valga la pena considerarlo.