Som nämnts i den första delen av denna serie:Python-databasprogrammering med MongoDB, Python-modulen PyMongo krävs för att Python ska kunna kommunicera med en MongoDB-databas. För att installera detta, använd kommandot vid Windows kommandotolk:
pip3 install pymongo
Installation av PyMongo bör producera en utdata som liknar det som visas nedan:
Figur 1 – Installera PyMongo-modulen
Beroende på Python-konfigurationen, en extra modul med namnet dnspython kan också vara nödvändigt:
pip3 install dnspython
Figur 2 – Installera dnspython modul
Hur man infogar data i MongoDB med Python
Koden nedan kommer att skapa 15 slumpmässigt genererade Artister och två album för var och en av 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 intressant observation om denna kod, åtminstone jämfört med de SQL-orienterade exemplen i Python Database Programmering med SQL Express för nybörjare, är att det är mycket enklare, eftersom det inte finns någon extra SQL-komponent. JSON-funktionerna är redan en del av Python och det enda MongoDB-relaterade kommandot är insert_many() funktioner som exekveras efter att varje datauppsättning har skapats. Ännu bekvämare, dessa kommandon matchar samma syntax i Python som används i MongoDB-skalet.
Ur säkerhetssynpunkt existerar problem som SQL Injection helt enkelt inte i sådan kod, inte bara för att det inte finns någon SQL som exekveras, utan absolut ingen kod överhuvudtaget skickas in i databasen. Python List-funktionaliteten tar också hand om problem som att undvika citattecken.
Istället för att visa utdata i kommandotolksfönstret, kommer en annan kod att användas för att fråga databasen istället.
Validera inläggen med Python
Koden nedan kommer att fråga MongoDB-databasen efter infogningsåtgärderna ovan med 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
Utdata nedan innehåller de första dokumenten som skapats längre upp i dokumentet:
Figur 3 – Validera inläggen
Fråga MongoDB-data med Python
Koden ovan kan anpassas till ett interaktivt verktyg för att fråga data med användarinmatning. MongoDB tillhandahåller ett kraftfullt textsökverktyg för sina samlingar, men för att aktivera det måste textindex skapas på samlingarna som ska sökas i:
db.Artists.createIndex({artist_name: "text"}) db.Albums.createIndex({artist_name: "text", album_name: "text"}) Listing 8 - Creating Text Indices for each collection
Observera att MongoDB endast tillåter ett textindex per samling. Ett försök att skapa ett annat index för en annan nod i en samling kommer att orsaka ett fel. Utdata från dessa kommandon i MongoDB Shell är nedan:
Figur 4 – Lägga till textindex
Medan textsökningsverktyget kan utföra alla typer av galen matchningslogik som involverar reguljära uttryck och partiella matchningar med närhetsrankning, kommer exemplet nedan att hålla sig till enkel matchning, för att illustrera 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
Observera att ingen konvertering av data som kom från MongoDB behövdes för att matcha den med den gemena versionen av söktermen.
Sluta tankar om Python och MongoDB-utveckling
För utvecklare som har kodat mot SQL-orienterade databasservrar och databaser kan språnget till noSQL kännas som att skala en mycket brant inlärningskurva, men genom att kartlägga välbekanta SQL-databaskoncept till sina NoSQL-motsvarigheter blir det lite mindre obekvämt att klättra . Sådana utvecklare kan till och med bli chockade över avsaknaden av "grundläggande" "funktioner" såsom upprätthållande av främmande nyckel eller förväntan att det är applikationen och inte databasen som förväntas upprätthålla regler för dataintegritet. För mycket erfarna SQL-orienterade databasutvecklare känns till och med tanken på sådana idéer nästan som att programmera kätteri!
Men NoSQL-databaser som MongoDB lägger till många andra funktioner som gör förändringen i tänkandet värt det. Att inte behöva oroa sig för ännu en version av SQL som är "bara tillräckligt annorlunda" för att vara irriterande, eller inte behöva tänka på problem som SQL-injektion, att kunna infoga flera poster, fel, dokument med data säkert utan krångel med " tusentals” enskilda uttalanden, och kanske till och med underhållande den "galna" idén att låta applikationen göra datatillämpningen rakar bort en stor del av applikationsutvecklingsinsatser gör det värt att överväga.