{"id":89,"date":"2017-01-30T08:57:46","date_gmt":"2017-01-30T16:57:46","guid":{"rendered":"http:\/\/www.kenwalger.com\/blog\/?p=89"},"modified":"2017-07-09T22:19:15","modified_gmt":"2017-07-10T05:19:15","slug":"mongodb-crud-with-python","status":"publish","type":"post","link":"https:\/\/www.kenwalger.com\/blog\/nosql\/mongodb-crud-with-python\/","title":{"rendered":"MongoDB CRUD with Python"},"content":{"rendered":"<p>In my last post, we looked at how to combat <em>Impostor Syndrome<\/em> and came to the conclusion that deepening our knowledge on a given topic helps to sharpen of knowledge sword to fight our feelings of self doubt. If you missed that post, take a look <a href=\"http:\/\/www.kenwalger.com\/blog\/career\/combating-impostor-syndrome\/\">here<\/a>. This week let&#8217;s\u00a0take a look at using the NoSQL database <a href=\"https:\/\/www.mongodb.com\/\">MongoDB<\/a> with Python. In a <a href=\"http:\/\/www.kenwalger.com\/blog\/python\/bottle-basics\/\">related post<\/a>, I&#8217;ll show how to implement them into web frameworks.<\/p>\n<h3>Planning<\/h3>\n<p>We will start with an exploration of CRUD <a href=\"https:\/\/docs.mongodb.com\/manual\/crud\/\">operations in MongoDB<\/a> using Python and <a href=\"https:\/\/docs.mongodb.com\/ecosystem\/drivers\/python\/\">PyMongo<\/a>. Next, we&#8217;ll have a look at the Python web framework <a href=\"https:\/\/bottlepy.org\/docs\/dev\/\">Bottle<\/a> and then use Bottle with MongoDB to generate a simple web site. Then we&#8217;ll spend a bit of time using MongoDB with the <a href=\"https:\/\/www.djangoproject.com\/\">Django<\/a> web framework to generate a slightly more involved site than our Bottle version.<\/p>\n<p>In this post, we kick off this series with a simple discussion of how to do some simple CRUD operations in Python similar to <a href=\"http:\/\/www.kenwalger.com\/blog\/nosql\/mongodb-and-java\/\">my post for doing CRUD operations in Java<\/a>. Not familiar with CRUD? It stands for\u00a0<strong>C<\/strong>reate,\u00a0<strong>R<\/strong>ead,\u00a0<strong>U<\/strong>pdate, and\u00a0<strong>D<\/strong>elete. Those are the basic operations one will find themselves doing with\u00a0<em>any<\/em> database, not just MongoDB.<\/p>\n<p>In December of 2016, MongoDB released a new version of their database, <a href=\"https:\/\/www.mongodb.com\/mongodb-3.4\">3.4<\/a>, and I&#8217;m using 3.4.1 for this series of posts. While we aren&#8217;t going to go into any release specific features this week, we might in future posts, so I would encourage you to utilize the latest version. We will be touching on some of the features in the latest version of Python, <a href=\"https:\/\/www.python.org\/downloads\/release\/python-360\/\">3.6<\/a>, later on as well so make sure you are utilizing that version as well.<\/p>\n<h3>Python Driver &#8211; PyMongo<\/h3>\n<p>Okay, let&#8217;s concentrate on some basic implementations and general syntax of the Python driver for MongoDB as well as some basic database documents. <a href=\"https:\/\/docs.mongodb.com\/manual\/core\/document\/\">Documents<\/a>, by the way, are similar to a SQL database record.<\/p>\n<p>The project code for this post will be available on GitHub and a link will be included at the end of the post. Let&#8217;s start off with our <code>requirements.txt<\/code> file to list out our project dependencies:<\/p>\n<pre>pymongo=='3.4.0'\n<\/pre>\n<p>With that in place we can do <code>pip install -r requirements.txt<\/code> to install the required version of the libraries for our project.<\/p>\n<p>Another thing we will need for our project to work is a running instance of a MongoDB server. I am using version 3.4.1 and will assume that you have MongoDB 3.4 <a href=\"https:\/\/www.mongodb.com\/download-center\">downloaded<\/a>, installed, and running on the default address of <code>localhost<\/code> and port <code>27017<\/code>. Further, since we are just sharpening our sword of knowledge here and don&#8217;t need MongoDB server authentication, let&#8217;s assume that feature is turned off or not implemented at all on our server.<\/p>\n<p>Great, now that our environment is setup let&#8217;s enter into the planning stages a bit. What do we need to do?<\/p>\n<ul>\n<li>Connect to the database<\/li>\n<li>Insert\u00a0an individual document into the database (<strong>Create<\/strong>)<\/li>\n<li>Find and print a document in the database (<strong>Read<\/strong>)<\/li>\n<li><strong>Update<\/strong> the document in the database<\/li>\n<li>Finally, <strong>Delete<\/strong> the document from the database<\/li>\n<\/ul>\n<p>Let&#8217;s get started!<\/p>\n<h4><strong>Database Connection<\/strong><\/h4>\n<p>To setup our connection we will need to import <code>MongoClient<\/code>\u00a0from <code>pymongo<\/code>, set the host and port we intend on using, and then select the database and collection we need. Remember that in MongoDB a\u00a0<em>collection\u00a0<\/em>is similar to a table in the SQL world in that it is a namespace for our data.<\/p>\n<pre>from pymongo import MongoClient\n\nHOST = 'localhost'\nPORT = 27017\n\nclient = MongoClient(HOST, PORT)\ndatabase = client.cookbook\nrecipes = database.recipes<\/pre>\n<p>Great, we now have a connection to the MongoDB database <code>cookbook<\/code>\u00a0and the collection <code>recipes<\/code>. But wait, we didn&#8217;t ask to specifically create either of those, nor did we put anything\u00a0<em>into<\/em> the collection yet. That&#8217;s correct, MongoDB generates that for us and waits for us to start using <code>cookbook.recipes<\/code>. Now, we need to add a basic recipe to our collection so that we have something with which to work.<\/p>\n<p>We&#8217;ll define a single recipe document and insert it into our collection using the <code>insert_one()<\/code> method. <a href=\"http:\/\/api.mongodb.com\/python\/current\/api\/pymongo\/collection.html\">Here<\/a>&#8216;s a link to further documentation on PyMongo&#8217;s collection level operations.<\/p>\n<pre>recipe = {'title': 'chocolate milk',\n          'description': 'Yummy drink',\n          'ingredients': [\n              {'name': 'milk', 'quantity': 8, 'unit of measure': 'ounce'},\n              {'name': 'chocolate syrup', 'quantity': 2, 'unit of measure': 'ounce'}\n          ],\n          'yield': {'quantity': 1, 'unit': 'glass'},\n          'prep time': 0,\n          'cook time': 0,\n          'author': 'Biff Tannen',\n          'uploaded_by': 'kenwalger',\n          }\n\nrecipes.insert_one(recipe)\n<\/pre>\n<p>That&#8217;s all there is to it. We have just added a <em>Chocolate Milk\u00a0<\/em>recipe to our collection. We just call the <code>insert_one()<\/code> method on our collection and pass in our document as an argument.<\/p>\n<h4><strong>Reading the documents<\/strong><\/h4>\n<p>Getting a document back out is pretty straight forward as well, we can simply use the <code>find_one()<\/code> function, which is a <a href=\"http:\/\/api.mongodb.com\/python\/current\/api\/pymongo\/collection.html\">collection level operator<\/a> from the PyMongo driver. It will, as the name would indicate, find a single document in the collection. This can be very useful to get an idea about the schema of the collection. Since we currently <em>only<\/em> have one record in our database, it should be perfect for getting our information out. I&#8217;m also going to include a new import <code>pprint<\/code> so that when we print out our data in a pretty fashion.<\/p>\n<pre>import pprint\n\nprint(\"\\nPretty Printed document: \\n\")\npprint.pprint(recipes.find_one())\n<\/pre>\n<p>Our output should be as follows, with the <code>_id<\/code> value being different on your system:<\/p>\n<pre>Pretty Print: \n\n{'_id': ObjectId('588541a0146bde28a08217d4'),\n 'author': 'Biff Tannen',\n 'cook time': 0,\n 'description': 'Yummy drink',\n 'ingredients': [{'name': 'milk', 'quantity': 8, 'unit of measure': 'ounce'},\n                 {'name': 'chocolate syrup',\n                  'quantity': 2,\n                  'unit of measure': 'ounce'}],\n 'prep time': 0,\n 'title': 'chocolate milk',\n 'uploaded_by': 'kenwalger',\n 'yield': {'quantity': 1, 'unit': 'glass'}}\n<\/pre>\n<p>Cool! We have seen how to do two of the four <strong>CRUD<\/strong> tasks already! And through the <code>pymongo<\/code> driver, it has been relatively straightforward to do so. We have a basic recipe for chocolate milk in our cookbook.<\/p>\n<h4>Update and Delete<\/h4>\n<p>But wait, we incorrectly attributed the recipe to <em>Biff Tannen<\/em>. As any fan of the <a href=\"https:\/\/www.amazon.com\/gp\/product\/B011Q0H3JS\/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=B011Q0H3JS&amp;linkCode=as2&amp;tag=kenwalgersite-20&amp;linkId=c2f08be5dff801a10b748a1785922ab6\" target=\"_blank\" rel=\"noopener\">Back to the Future<\/a><img loading=\"lazy\" decoding=\"async\" style=\"border: none !important; margin: 0px !important;\" src=\"\/\/ir-na.amazon-adsystem.com\/e\/ir?t=kenwalgersite-20&amp;l=am2&amp;o=1&amp;a=B011Q0H3JS\" alt=\"\" width=\"1\" height=\"1\" border=\"0\" \/> movie series knows, chocolate milk is George McFly&#8217;s drink, not his arch enemy Biff&#8217;s. Let&#8217;s <strong>U<\/strong>pdate our database with that change using the <code>update_one()<\/code> method with the <a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/operator\/update\/set\/\"><code>$set<\/code> operator<\/a> and print out the new record to make sure it accomplished what we wanted.<\/p>\n<pre>recipes.update_one({'title': 'chocolate milk'},\n                   {'$set': {'author': 'George McFly'}\n                    }\n                   )\nprint(\"\\nShould be George McFly: \")\npprint.pprint(recipes.find_one({'author': 'George McFly'}))\n<\/pre>\n<p>Great, and our output should now reflect that change and we can tell it is the same record because the collection unique <code>_id<\/code> value is still the same.<\/p>\n<pre>Should be George McFly: \n{'_id': ObjectId('588541a0146bde28a08217d4'),\n 'author': 'George McFly',\n 'cook time': 0,\n 'description': 'Yummy drink',\n 'ingredients': [{'name': 'milk', 'quantity': 8, 'unit of measure': 'ounce'},\n                 {'name': 'chocolate syrup',\n                  'quantity': 2,\n                  'unit of measure': 'ounce'}],\n 'prep time': 0,\n 'title': 'chocolate milk',\n 'uploaded_by': 'kenwalger',\n 'yield': {'quantity': 1, 'unit': 'glass'}}\n<\/pre>\n<p>We have one task left, <strong>D<\/strong>elete. Which uses the <code>delete_one()<\/code> method. We need to pass in an argument for which document to delete which, given that our current collection only has one recipe in there we could use a variety of things to select it. Traditionally we would want to utilize the unique identifier <code>_id<\/code> to ensure that we are only deleting the document that we want.<\/p>\n<pre>recipes.delete_one('_id': ObjectId('588541a0146bde28a08217d4'))\n<\/pre>\n<p>Is all we need to do and our collection is empty again.<\/p>\n<h3>CRUD Wrap Up<\/h3>\n<p>In summary, we learned how to\u00a0<strong>C<\/strong>reate,\u00a0<strong>R<\/strong>ead,\u00a0<strong>U<\/strong>pdate,\u00a0and\u00a0<strong>D<\/strong>elete documents in MongoDB in Python using the PyMongo driver. There is much improvement on the code to be made though by refactoring\u00a0things into functions, error handling, etc. As mentioned at the top of this post, the next post will be on Bottle specifically to get up and running with that framework. After that, we will integrate MongoDB\u00a0<em>with<\/em> Bottle at which time we will see some best practices for error handling and making these CRUD steps into functions.<\/p>\n<p>Please let me know what you think in the comments below or reach out on Twitter where I am <a href=\"https:\/\/twitter.com\/kenwalger\">@kenwalger<\/a>.<\/p>\n<p>The code for this post can be seen in the GitHub repository <a href=\"https:\/\/github.com\/kenwalger\/Python_MongoDB_CRUD\">here<\/a>.<\/p>\n<p>Happy coding!<\/p>\n<a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-facebook nolightbox\" data-provider=\"facebook\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Facebook\" href=\"https:\/\/www.facebook.com\/sharer.php?u=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F89&#038;t=MongoDB%20CRUD%20with%20Python&#038;s=100&#038;p&#091;url&#093;=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F89&#038;p&#091;images&#093;&#091;0&#093;=https%3A%2F%2Fi0.wp.com%2Fwww.kenwalger.com%2Fblog%2Fwp-content%2Fuploads%2F2017%2F01%2FMongoDB_CRUD_Blog-FEATURE-e1485140867146.png%3Ffit%3D100%252C100%26ssl%3D1&#038;p&#091;title&#093;=MongoDB%20CRUD%20with%20Python\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" alt=\"Facebook\" title=\"Share on Facebook\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/i0.wp.com\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/facebook.png?resize=48%2C48&#038;ssl=1\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-twitter nolightbox\" data-provider=\"twitter\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Twitter\" href=\"https:\/\/twitter.com\/intent\/tweet?url=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F89&#038;text=Hey%20check%20this%20out\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" alt=\"twitter\" title=\"Share on Twitter\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/i0.wp.com\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/twitter.png?resize=48%2C48&#038;ssl=1\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-reddit nolightbox\" data-provider=\"reddit\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Reddit\" href=\"https:\/\/www.reddit.com\/submit?url=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F89&#038;title=MongoDB%20CRUD%20with%20Python\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" alt=\"reddit\" title=\"Share on Reddit\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/i0.wp.com\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/reddit.png?resize=48%2C48&#038;ssl=1\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-linkedin nolightbox\" data-provider=\"linkedin\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Linkedin\" href=\"https:\/\/www.linkedin.com\/shareArticle?mini=true&#038;url=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F89&#038;title=MongoDB%20CRUD%20with%20Python\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" alt=\"linkedin\" title=\"Share on Linkedin\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/i0.wp.com\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/linkedin.png?resize=48%2C48&#038;ssl=1\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-mail nolightbox\" data-provider=\"mail\" rel=\"nofollow\" title=\"Share by email\" href=\"mailto:?subject=MongoDB%20CRUD%20with%20Python&#038;body=Hey%20check%20this%20out:%20https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F89\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" alt=\"mail\" title=\"Share by email\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/i0.wp.com\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/mail.png?resize=48%2C48&#038;ssl=1\" \/><\/a>","protected":false},"excerpt":{"rendered":"<p>In my last post, we looked at how to combat Impostor Syndrome and came to the conclusion that deepening our knowledge on a given topic helps to sharpen of knowledge sword to fight our feelings of self doubt. If you missed that post, take a look here. This week let&#8217;s\u00a0take a look at using the &hellip; <a href=\"https:\/\/www.kenwalger.com\/blog\/nosql\/mongodb-crud-with-python\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;MongoDB CRUD with Python&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":108,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"pmpro_default_level":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4,3,7],"tags":[79],"yst_prominent_words":[149,146,159,148,160,152,156,161,154,150,164,147,163,162,153,157,155,145,151,158],"class_list":["post-89","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-mongodb","category-nosql","category-python","tag-pymongo","pmpro-has-access"],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.kenwalger.com\/blog\/wp-content\/uploads\/2017\/01\/MongoDB_CRUD_Blog-FEATURE-e1485140867146.png?fit=100%2C100&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8lx70-1r","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/posts\/89","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/comments?post=89"}],"version-history":[{"count":16,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/posts\/89\/revisions"}],"predecessor-version":[{"id":442,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/posts\/89\/revisions\/442"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/media\/108"}],"wp:attachment":[{"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/media?parent=89"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/categories?post=89"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/tags?post=89"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/yst_prominent_words?post=89"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}