このシリーズの最初のパートで述べたように、MongoDBを使用したPythonデータベースプログラミング、Pythonモジュール PyMongo PythonがMongoDBデータベースと通信できるようにするために必要です。これをインストールするには、Windowsコマンドプロンプトで次のコマンドを使用します:
pip3 install pymongo
PyMongoをインストールすると、以下に示すような出力が生成されます。
図1-PyMongoモジュールのインストール
Pythonの構成に応じて、 dnspythonという名前の追加モジュール 必要な場合もあります:
pip3 install dnspython
図2– dnspythonのインストール モジュール
Pythonを使用してMongoDBにデータを挿入する方法
以下のコードは、ランダムに生成された15人のアーティストを作成します および2つのアルバム それぞれについて:
# 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
このコードに関する興味深い観察の1つは、少なくとも初心者向けSQL Expressを使用したPythonデータベースプログラミングのSQL指向の例と比較すると、追加のSQLコンポーネントがないため、はるかに単純であるということです。 JSON関数はすでにPythonの一部であり、MongoDB関連のコマンドは insert_many()のみです。 各データセットの作成後に実行される関数。さらに便利なことに、これらのコマンドは、MongoDBシェルで使用されているPythonの同じ構文と一致します。
セキュリティの観点から、SQLインジェクションのような問題は、SQLが実行されていないという理由だけでなく、データベースに渡されているコードがまったくないという理由だけで、そのようなコードには存在しません。 Pythonリスト機能は、引用符のエスケープなどの問題も処理します。
コマンドプロンプトウィンドウに出力を表示する代わりに、別のコードを使用してデータベースにクエリを実行します。
Pythonを使用したインサートの検証
以下のコードは、Pythonを使用して上記で行われた挿入アクションについてMongoDBデータベースにクエリを実行します。
# 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–インサートの検証
Pythonを使用したMongoDBデータのクエリ
上記のコードは、ユーザー入力でデータをクエリするためのインタラクティブツールに適合させることができます。 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では、コレクションごとに1つのテキストインデックスしか使用できないことに注意してください。コレクション内の別のノードに別のインデックスを作成しようとすると、エラーが発生します。 MongoDBシェルでのこれらのコマンドの出力は次のとおりです。
図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指向のデータベース開発者にとって、そのようなアイデアを考えただけでも、プログラミングは異端のように感じられます!
しかし、MongoDBのようなNoSQLデータベースには、考え方を変える価値のある他の多くの機能が追加されています。煩わしいほど「十分に異なる」SQLのさらに別のバージョンについて心配する必要はありません。または、SQLインジェクションなどの問題について考える必要がなく、複数のレコード、エラー、データのドキュメントを安全に挿入できます。何千もの個別のステートメント、そしておそらく面白い アプリケーションにデータの適用を行わせるという「クレイジー」な考えは、アプリケーション開発の膨大な労力を削減するため、すべて検討する価値があります。