Както бе споменато в първата част на тази серия:Програмиране на база данни на Python с MongoDB, модулът на Python PyMongo е необходимо, за да може Python да комуникира с база данни MongoDB. За да инсталирате това, използвайте командата в командния ред на Windows:
pip3 install pymongo
Инсталирането на PyMongo трябва да доведе до изход, подобен на показания по-долу:
Фигура 1 – Инсталиране на модула PyMongo
В зависимост от конфигурацията на Python, допълнителен модул с име dnspython може също да е необходимо:
pip3 install dnspython
Фигура 2 – Инсталиране на dnspython модул
Как да вмъкнете данни в MongoDB с Python
Кодът по-долу ще създаде 15 произволно генерирани Изпълнители и два албума за всеки от тях:
# 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
Едно интересно наблюдение за този код, поне в сравнение с ориентираните към SQL примери в програмирането на база данни на Python със SQL Express за начинаещи е, че той е много по-прост, тъй като няма допълнителен SQL компонент. JSON функциите вече са част от Python и единствената команда, свързана с MongoDB, е insert_many() функции, които се изпълняват след създаване на всеки набор от данни. Още по-удобно, тези команди съвпадат със същия синтаксис в Python, който се използва в MongoDB Shell.
От гледна точка на сигурността, проблеми като SQL инжекцията просто не съществуват в такъв код, не само защото не се изпълнява SQL, но абсолютно никакъв код не се предава в базата данни. Функционалността на Python List също се грижи за проблеми като избягване на кавички.
Вместо да се показва изходът в прозореца на командния ред, друго парче код ще бъде използвано за запитване на базата данни.
Проверка на вложките с Python
Кодът по-долу ще поиска от базата данни MongoDB за действията за вмъкване, направени по-горе с помощта на 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
Резултатът по-долу съдържа първоначалните документи, създадени по-нагоре в документа:
Фигура 3 – Проверка на вложките
Запитване на MongoDB данни с Python
Кодът по-горе може да бъде адаптиран в интерактивен инструмент за запитване на данните с въвеждане от потребителя. MongoDB предоставя мощен инструмент за търсене на текст за своите колекции, но за да го активирате, трябва да бъдат създадени текстови индекси в колекциите, които ще бъдат търсени:
db.Artists.createIndex({artist_name: "text"}) db.Albums.createIndex({artist_name: "text", album_name: "text"}) Listing 8 - Creating Text Indices for each collection
Имайте предвид, че MongoDB позволява само един текстов индекс на колекция. Опитът за създаване на друг индекс за различен възел в колекция ще доведе до грешка. Резултатът от тези команди в MongoDB Shell е по-долу:
Фигура 4 – Добавяне на текстови индекси
Докато инструментът за търсене на текст може да изпълнява всякакъв вид безумна логика на съвпадение, включваща регулярни изрази и частични съвпадения с класиране по близост, примерът по-долу ще се придържа към просто съвпадение, за да илюстрира доказателството на концепцията:
# 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
Имайте предвид, че не е било необходимо преобразуване на данните, излизащи от MongoDB, за да се съпоставят с малката версия на думата за търсене.
Окончателни мисли за разработката на Python и MongoDB
За разработчиците, които са кодирали срещу SQL-ориентирани сървъри на бази данни и бази данни, скокът към noSQL може да изглежда като мащабиране на много стръмна крива на обучение, но чрез съпоставяне на познати концепции на SQL база данни с техните NoSQL колеги, става малко по-малко неудобно изкачване . Такива разработчици може дори да бъдат шокирани от липсата на „основни“ „функции“ като прилагане на външни ключове или очакването, че се очаква приложението, а не базата данни да налага правилата за целостта на данните. За много опитни разработчици на бази данни, ориентирани към SQL, дори самата мисъл за подобни идеи изглежда почти като програмна ерес!
Но NoSQL бази данни като MongoDB добавят много други функции, които правят промяната в мисленето си заслужаваща. Не е необходимо да се тревожите за още една версия на SQL, която е „достатъчно различна“, за да бъде досадна, или да не се налага да мислите за проблеми като SQL инжектиране, възможност за вмъкване на множество записи, err, документи с данни сигурно без караницата на „ хиляди” индивидуални изявления и може би дори забавни „лудата“ идея, че налагането на прилагането на данните от приложението прави огромна част от усилията за разработка на приложения, прави всичко това да си заслужава да бъде разгледано.