MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Desenvolvimento de banco de dados Python e MongoDB


Conforme mencionado na primeira parte desta série:Python Database Programming with MongoDB, o módulo Python PyMongo é necessário para que o Python possa se comunicar com um banco de dados MongoDB. Para instalar isso, use o comando no prompt de comando do Windows:
pip3 install pymongo

A instalação do PyMongo deve produzir uma saída semelhante à mostrada abaixo:



Figura 1 – Instalando o módulo PyMongo

Dependendo da configuração do Python, um módulo adicional chamado dnspython também pode ser necessário:
pip3 install dnspython



Figura 2 – Instalando o dnspython módulo

Como inserir dados no MongoDB com Python


O código abaixo criará 15 Artistas gerados aleatoriamente e dois álbuns para cada um deles:
# 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

Uma observação interessante sobre esse código, pelo menos em comparação com os exemplos orientados a SQL em Python Database Programming with SQL Express for Beginners, é que ele é muito mais simples, pois não há componente SQL adicional. As funções JSON já fazem parte do Python e o único comando relacionado ao MongoDB é o insert_many() funções que são executadas após a criação de cada conjunto de dados. Ainda mais conveniente, esses comandos correspondem à mesma sintaxe em Python usada no Shell do MongoDB.

Do ponto de vista da segurança, questões como SQL Injection simplesmente não existem nesse código, não apenas porque não há SQL sendo executado, mas absolutamente nenhum código está sendo passado para o banco de dados. A funcionalidade Lista do Python também cuida de problemas como o escape de aspas.

Em vez de mostrar a saída na janela do prompt de comando, outro pedaço de código será usado para consultar o banco de dados.

Validando as inserções com Python


O código abaixo irá consultar o banco de dados MongoDB para as ações de inserção feitas acima 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

A saída abaixo contém os documentos iniciais criados mais adiante no documento:



Figura 3 – Validando as inserções

Consultando dados do MongoDB com Python


O código acima pode ser adaptado em uma ferramenta interativa para consultar os dados com entrada do usuário. O MongoDB fornece uma poderosa ferramenta de pesquisa de texto para suas coleções, mas para habilitá-la, os índices de texto devem ser criados nas coleções a serem pesquisadas:
db.Artists.createIndex({artist_name: "text"})

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

Listing 8 - Creating Text Indices for each collection

Observe que o MongoDB permite apenas um índice de texto por coleção. A tentativa de criar outro índice para um nó diferente em uma coleção causará um erro. A saída desses comandos no MongoDB Shell está abaixo:



Figura 4 – Adicionando índices de texto

Embora a ferramenta de pesquisa de texto possa executar todos os tipos de lógica de correspondência maluca envolvendo expressões regulares e correspondências parciais com classificação de proximidade, o exemplo abaixo ficará com correspondência simples, para ilustrar a prova de conceito:
# 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

Observe que nenhuma conversão dos dados provenientes do MongoDB foi necessária para combiná-los com a versão minúscula do termo de pesquisa.

Considerações finais sobre desenvolvimento em Python e MongoDB


Para desenvolvedores que codificam em servidores de banco de dados e bancos de dados orientados a SQL, o salto para o noSQL pode parecer uma curva de aprendizado muito íngreme, mas mapear conceitos familiares de banco de dados SQL para seus equivalentes NoSQL, torna-se um pouco menos desconfortável de subir . Esses desenvolvedores podem até ficar chocados com a falta de “recursos” “básicos”, como aplicação de chave estrangeira ou a expectativa de que é o aplicativo e não o banco de dados que deve impor regras de integridade de dados. Para desenvolvedores de banco de dados orientados a SQL muito experientes, até mesmo o simples pensamento de tais ideias quase parece uma heresia de programação!

Mas bancos de dados NoSQL como o MongoDB adicionam muitos outros recursos que fazem a mudança de pensamento valer a pena. Não precisando se preocupar com mais uma versão do SQL que é “apenas diferente o suficiente” para ser irritante, ou não ter que pensar em questões como injeção de SQL, poder inserir vários registros, err, documentos de dados de forma segura sem o incômodo de “ milhares” de declarações individuais e talvez até divertidas a ideia “louca” de que o aplicativo faça a aplicação de dados reduz uma grande parte dos esforços de desenvolvimento de aplicativos faz com que tudo isso valha a pena.