In this project you will learn how to use the MapR-DB JSON using Python:
- Create new tables
- Create, Read, Update and Delete documents (CRUD)
MapR Data Platform 6.1 introduced the MapR Data Access Gateway (DAG) that exposes MapR-DB JSON Tables using a lightweight protocol based on (gRPC and OJAI JSON Syntax ).
This gateway is used by the MapR DB JSON Python client.
In this article you will learn how to buid a simple "To do" Web application with MapR Python client and Flask.
You system should have the following components:
- MapR Data Platform 6.1 with the Data Access Gateway
- Python 2.7 or later
- Pip
Clone and build the repository using the following commands:
$ git clone https://github.com/mapr-demos/maprdb-json-python-todo-list.git
Install Python dependencies for Flask and MapR-DB
$ pip install flask
$ pip install flask-wtf
$ pip install
$ maprdb-python-client
$ ojai-python-api
Optionally you can create a requirements
file using:
$ pip freeze > requirements.txt
Start the application using the following command:
$ cd maprdb-json-python-todo-list
$ python run.py
The applicaton starts on port 5000
.
Open your internet browser and go to:
Use the simple form to:
- Create new entry
- Update the entry
- Click on the status (Open/Close) to change the status
Most of the logic is happening in the ./app/views.py
file.
from mapr.ojai.ojai_query.QueryOp import QueryOp
from mapr.ojai.storage.ConnectionFactory import ConnectionFactory
The MapR Python client connects to the cluster using the gateway, the application must use a connection string that use the gateway host, port and authentication method
connection_string = "mapr-gateway-host:5678?auth=basic;user=mapr;password=mapr;ssl=false;"
connection = ConnectionFactory.get_connection(connection_str=connection_string)
The connection_string
is composed of:
- hostname
- port, the default port of the MapR Data Access Gateway is 5678
- the
auth
parameter describe the authentication type, in MapR 6.1 the default and only value is basic user
andpassword
to set the user that will be used to access the databasessl
true of false. When the cluster is secured the gateway will use SSL and you have to specify additional parameter about the SSL certificate
Once you have a connection you can start to use it to work with JSON Tables
The following code check if the table exists and if it does not it create it using the create_store
method.
if connection.is_store_exists(store_path='/apps/todos'):
todos_table = connection.get_store(store_path='/apps/todos')
print("Table exists")
else:
todos_table = connection.create_store(store_path='/apps/todos')
print("Table created")
The application has now access to the todos_table
variable that point to the /apps/todos
table.
You can use this table in all the routes of your application.
For example in the home page that match the /
route you need to do a find
query and put the result of this query into a variable that will be use by the flask templates:
open_todos_query = {'$select': ['*'] }
query_result = todos_table.find( open_todos_query , options=options)
return render_template('index.html', form = form, tasks = query_result)
-
open_todos_query
is a dictionnary that define the OJAI query to use to find the taks. In this specific example you just takes all the fields. You can change the query and add any of the OJAI attributes like$where
,$limit
,$orderby
for example- if you want to sort the tasks starting with the opened ones:
open_todos_query = {'$select': ['*'], '$orderby' : {'status':'desc'} }
- if you want only the opened taks you can use:
open_todos_query = {'$select': ['*'], '$where' : {'$eq' : {'status' : 'Open'} } }
- if you want to sort the tasks starting with the opened ones:
-
Once you have the query as JSON/Dictionnary you can retrieve the document using
todos_table.find()
method -
the
query_result
is passed to to therender_template
and printed in the index.html template.
The application use the /
route to also insert/update task using the "POST" HTTP verb.
if form.validate_on_submit():
# Create document
task = { "_id" : form.id.data , "title": form.title.data , "status": "Open" };
document_to_save = connection.new_document(dictionary=task)
todos_table.insert_or_replace(doc=document_to_save)
return redirect(url_for('index'))
- When the form is submitted
form.validate_on_submit()
a new task object is created using form dataform.id.data
andform.title.data
- Then a new OJAI document is created from this object uding the
new_document
method - And the document is saved into the DB Using the
todos_table.insert_or_replace
. In this case if the document already exist with this_id
it is simply replaced.
The last interaction this simple application is to change the status of a Task from Open to Close (or Close to Open) when the user clicks on the status.
For this the @app.route('/changes_status/<id>/<status>', methods = ['GET'])
has been created.
@app.route('/changes_status/<id>/<status>', methods = ['GET'])
def change_status(id, status):
# Move the status to "close" for the task
new_status = 'Close'
if status=='Close':
new_status = 'Open'
doc_mutation = connection.new_mutation().set_or_replace('status', new_status )
todos_table.update(id, doc_mutation)
return redirect(url_for('index'))
- The route contains the Id
<id>
of the document and current status of the task<status>
- Then you have to create a "mutation" to set the status in the JSON document to the new status
connection.new_mutation().set_or_replace('status', new_status )
- Then you use the mutation object in the
todos_table.update(id, doc_mutation)
with the Id of the document to update
This last operation allows your application to only change the mutated fields (on the network and on disk), this means it is really efficient even when the document that is stored is a big one.
This application is a very basic application that allows you to discover the MapR-DB JSON Python client, and how it could be used in a Flask Web application.
You can add many other features to the application to make it richer such as:
- Authentication
- To do by user
- Creating categories
- Date/Due Data management
- Comments
- Delete tasks
- and many more...
The methods that you will be using in a more complex application will be the same as the one that have been describe during this simple tutorial