# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Starting with MongoDB

# You can find the complete tutorial in [Get Started with MongoDB Atlas](https://docs.atlas.mongodb.com/getting-started). In this notebook and the mini project, we will be using PyMongoDB driver to connect to our Non-SQL MongoDB database. If you follow the steps in the Mini Project, you should already have `pymongo` in your virtual environment. 
#
# **You should run this jupyter notebook from your virtual environment where you have installed `pymongo`**.

import pymongo

# If you have installed properly, running the above cell should produce no error.
#
# Next, copy the driver code into the cell below. See the screenshot where to get the driver code.
#
# ![](https://www.dropbox.com/s/hqpxmx297pbpjgx/mp3_connect_cluster3.png?raw=1)
#

# +
# Copy the driver code from MongoDB
# replace the "password" with your password that you 
# created for the user

client = None
# -

# ## Creating a New Database
#
# To create a new database called "test" simply run the code below.

# this command creates a new database on your cluster called test
# the variable db points to your database
db = client.test

# ## Creating a Collection
#
# In MongoDB, one Database can contains many collections. You can consider your collection a kind of your table. So in the code below, we are creating a collection called "people".

# this create a collection called people
people = db.people

# ## Creating a New Document
#
# The data inside a collection is what is called Document. Document in MongoDB can be considered like a Dictionary in Python. So to create a document, we simply create a dictionary in Python. For example, we create a dictionary variable called `person_document` in the cell below.

# +
import datetime

person_document = {
    "name": {"first": "Alan", "last": "Turing"},
    "birth": datetime.datetime(1912, 6, 23),
    "death": datetime.datetime(1954, 6, 7),
    "contribs": ["Turing Machine", "Turing test", "Turingery"],
    "views": 125000
}
# -

# ## Inserting Document into Collection
#
# To inser the document into the collection, we use the collection method called `insert_one(document)`. Run the cell below to insert the document.

# this insert the document into your collection:
people.insert_one(person_document)

# We can check if we successfully inserted from the web interface. To do that. Go to your cluster and click "Collection".
#
# ![](https://www.dropbox.com/s/r305dsr789kdle2/mp3_collections.png?raw=1)
#
# You can browse your collection to find "test" and open up to see the documents inside the collection.
#
# ![](https://www.dropbox.com/s/9do5rteqpc3v8ok/mp3_document.png?raw=1)

# ## Viewing Your Data from PyMongo
#
# You can also use collection's method to find and view your data. To find one instance of data in the collection `people`, you can run the following command.

result = people.find_one({"name.last": "Turing"})
print(result)

# Note the following:
#
# - We use the method called `find_one()`.
# - The argument for that method is the criteria for the search. In this case we want the last name to be "Turing".
# - `name` is a child node inside `people` collection.
# - `last` is a child node under `name`. We can access the child node using the dot operator like in `name.last`. 

# ## Database Operations

# We have seen that we can create a collection from a database using something like:
# ```
# collection = db.new_collection
# ```
#
# We can also do the same using dictionary style access
# ```
# collection = db['new_collection']
# ```
#
# The same way is used for both:
#
# - creating a new collection
# - getting access to the collection object

people = db['people']
print(people)

# Let's say if we want to create a new collection for each user name, we can do the following:

username = 'user_1'
collection = db[username]
print(collection)


# ## Collection Operations
#
# ### Inserting Document
# We have seen that we can use `insert_one(document)` and `find_one(criteria)` as part of collection's methods. Before using `insert_one(document)`, we have to create a document as a type of dictionary.

board = [['X', '_', 'O'],
         ['O', 'X', '_'],
         ['X', '_', 'O']]
data = {'cell': board, 'mark': 'X'}
collection.insert_one(data)

# You should see the result in the MongoDB Atlas portal.
#
# ![](https://www.dropbox.com/s/65b56hfcv184g4x/mp3_insert.png?raw=1)

# ### Counting Number of Documents
#
# We can count how many documents are there in the collection using the `count_documents()` method. The argument for this method is the search criteria of the documents you want to count. If you want to count all documents, then you can leave it as empty `{}`:

num = collection.count_documents({})
print(num)

# ### Finding Documents in a Collection
#
# To find one document that satisfies some criteria, we can use `find_one(criteria)` method. For example,

turing = people.find_one({"name.last": "Turing"})
print(turing)

# Note the following:
# - `name` is the one of child nodes in the document under `people` collection.
# - You can access the following child nodes using the dot operator as in `name.last` to access the node `last` under the node `name`.

# You can get more than one documents using the method `find()`. In fact, `find()` gives you an iterator which you can iterate as in the following code.

for item in collection.find():
    print(item['cell'])

# You can also put some criteria in `find()` to limit the search.

result = collection.find({'mark': 'X'})
for item in result:
    print(item['cell'])

# We can also limit the search result using `limit()` method.

result = collection.find().limit(1)
for item in result:
    print(item['cell'])

# Note that the output of `find()` method is a `Cursor` object which is an iterator. You can access the elements using the index and a square bracket.

result = collection.find()
print(result[0])
print(result[0]['cell'])

# # References
# - [pymongo Tutorial](https://pymongo.readthedocs.io/en/stable/tutorial.html)
# - [pymongo Database API](https://pymongo.readthedocs.io/en/stable/api/pymongo/database.html)
# - [pymongo Collection API](https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html)



StarcoderdataJupyterScriptsDedupFiltered