From 236fe16918843cfb69d13ecdc1b1f8c8e2131254 Mon Sep 17 00:00:00 2001 From: joerg84 Date: Mon, 24 Feb 2020 16:07:48 +0100 Subject: [PATCH] Added GOT tutorial. --- notebooks/ArangoDB_GOT_Tutorial.ipynb | 405 ++++++++++++++++++++++++++ 1 file changed, 405 insertions(+) create mode 100644 notebooks/ArangoDB_GOT_Tutorial.ipynb diff --git a/notebooks/ArangoDB_GOT_Tutorial.ipynb b/notebooks/ArangoDB_GOT_Tutorial.ipynb new file mode 100644 index 0000000..24c7c9b --- /dev/null +++ b/notebooks/ArangoDB_GOT_Tutorial.ipynb @@ -0,0 +1,405 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "ArangoDB_GOT_Tutorial.ipynb", + "provenance": [], + "collapsed_sections": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + } + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "7vn7qQcVHejm", + "colab_type": "text" + }, + "source": [ + "![alt text](https://www.arangodb.com/wp-content/uploads/2013/03/ArangoDB-logo.png)\n", + "Welcome to the ArangoDB Games OF Thrones Tutorial. \n", + "This is an introduction to ArangoDB’s query language AQL, built around a small dataset of characters from the novel and fantasy drama television series Game of Thrones (as of season 1). It includes character traits in two languages, some family relations, and last but not least a small set of filming locations, which makes for an interesting mix of data to work with." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "lPKaqikzz60n", + "colab_type": "code", + "outputId": "ab91f5f8-90f2-4557-f789-e5fdc50fb5f2", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 136 + } + }, + "source": [ + "# Install required packages\n", + "!pip install python-arango\n", + "\n", + "import requests\n", + "import json\n", + "from arango import ArangoClient\n" + ], + "execution_count": 8, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Requirement already satisfied: python-arango in /usr/local/lib/python3.6/dist-packages (5.2.1)\n", + "Requirement already satisfied: six in /usr/local/lib/python3.6/dist-packages (from python-arango) (1.12.0)\n", + "Requirement already satisfied: requests in /usr/local/lib/python3.6/dist-packages (from python-arango) (2.21.0)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests->python-arango) (2019.11.28)\n", + "Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests->python-arango) (3.0.4)\n", + "Requirement already satisfied: urllib3<1.25,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from requests->python-arango) (1.24.3)\n", + "Requirement already satisfied: idna<2.9,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests->python-arango) (2.8)\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ImZHgsvrJ8pQ", + "colab_type": "text" + }, + "source": [ + "Before we get started we need to create a temporary database with our [managed database service Oasis](https://cloud.arangodb.com). Please note the database will be automatically deleted after 2 hours." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "un7CV5mf0M1X", + "colab_type": "code", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + }, + "outputId": "f80f0b04-7424-43fe-9e1e-9ba91428d89a" + }, + "source": [ + "url = 'https://a0434a558688.arangodb.cloud:8529/_db/_system/tutorialDB/tutorialDB'\n", + "headers = {'Content-Type': 'application/json'}\n", + "payload = {'username': 'testFromColab'}\n", + "getDB = requests.post(url, headers=headers, data=json.dumps({'':''}))\n", + "results = getDB.json()\n", + "print(results)" + ], + "execution_count": 2, + "outputs": [ + { + "output_type": "stream", + "text": [ + "{'dbName': 'TUT55az3kzn9mtoo69j3qtftb', 'username': 'TUTasxqh4y1dwalttxrlijphs', 'password': 'TUTvsnxtxkw0pal05thk2ex9', 'hostname': 'a0434a558688.arangodb.cloud', 'port': 8529}\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "E3v4R-SHNuAU", + "colab_type": "text" + }, + "source": [ + "Let us connect to our temporary database:" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "9L7fzpJW8Xcd", + "colab_type": "code", + "outputId": "98bd5917-1250-468d-8667-cb6c496e3435", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "\n", + "host = 'https://' + results['hostname'] + ':' + str(results['port'])\n", + "client = ArangoClient(hosts=host)\n", + "print(client)\n", + "db = client.db(results['dbName'], username=results['username'], password=results['password'])\n" + ], + "execution_count": 9, + "outputs": [ + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "nsHRCB7eQ3Vq", + "colab_type": "text" + }, + "source": [ + "\n", + "With the above credentials we can also login into the ArangoDB UI: https://a0434a558688.arangodb.cloud:8529/:\n", + "\n", + "![alt text](https://www.arangodb.com/docs/stable/images/loginView.png)" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "PApkAUfp-sel", + "colab_type": "code", + "outputId": "c14f83bb-03ca-4862-f789-7dcf00360269", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "aql = db.aql\n", + "\n", + "if db.has_collection('Characters'):\n", + " Characters = db.collection('Characters')\n", + "else:\n", + " Characters = db.create_collection('Characters')\n", + "\n", + "cursor = aql.execute(\n", + " 'INSERT {'\n", + " '\"name\": \"Ned\",'\n", + " '\"surname\": \"Stark\",'\n", + " '\"alive\": true,'\n", + " '\"age\": 41,'\n", + " '\"traits\": [\"A\",\"H\",\"C\",\"N\",\"P\"]'\n", + " '} INTO Characters'\n", + ")\n", + "\n", + "\n", + "print(db[\"Characters\"])" + ], + "execution_count": 10, + "outputs": [ + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "iLwNVOp-CH9C", + "colab_type": "text" + }, + "source": [ + "Let’s add a bunch of other characters in a single query:\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Weaf_1lMCJ7-", + "colab_type": "code", + "colab": {} + }, + "source": [ + "cursor = aql.execute(\n", + "'LET data = [\\\n", + " { \"name\": \"Robert\", \"surname\": \"Baratheon\", \"alive\": false, \"traits\": [\"A\",\"H\",\"C\"] },\\\n", + " { \"name\": \"Jaime\", \"surname\": \"Lannister\", \"alive\": true, \"age\": 36, \"traits\": [\"A\",\"F\",\"B\"] },\\\n", + " { \"name\": \"Catelyn\", \"surname\": \"Stark\", \"alive\": false, \"age\": 40, \"traits\": [\"D\",\"H\",\"C\"] },\\\n", + " { \"name\": \"Cersei\", \"surname\": \"Lannister\", \"alive\": true, \"age\": 36, \"traits\": [\"H\",\"E\",\"F\"] },\\\n", + " { \"name\": \"Daenerys\", \"surname\": \"Targaryen\", \"alive\": true, \"age\": 16, \"traits\": [\"D\",\"H\",\"C\"] },\\\n", + " { \"name\": \"Jorah\", \"surname\": \"Mormont\", \"alive\": false, \"traits\": [\"A\",\"B\",\"C\",\"F\"] },\\\n", + " { \"name\": \"Petyr\", \"surname\": \"Baelish\", \"alive\": false, \"traits\": [\"E\",\"G\",\"F\"] },\\\n", + " { \"name\": \"Viserys\", \"surname\": \"Targaryen\", \"alive\": false, \"traits\": [\"O\",\"L\",\"N\"] },\\\n", + " { \"name\": \"Jon\", \"surname\": \"Snow\", \"alive\": true, \"age\": 16, \"traits\": [\"A\",\"B\",\"C\",\"F\"] },\\\n", + " { \"name\": \"Sansa\", \"surname\": \"Stark\", \"alive\": true, \"age\": 13, \"traits\": [\"D\",\"I\",\"J\"] },\\\n", + " { \"name\": \"Arya\", \"surname\": \"Stark\", \"alive\": true, \"age\": 11, \"traits\": [\"C\",\"K\",\"L\"] },\\\n", + " { \"name\": \"Robb\", \"surname\": \"Stark\", \"alive\": false, \"traits\": [\"A\",\"B\",\"C\",\"K\"] },\\\n", + " { \"name\": \"Theon\", \"surname\": \"Greyjoy\", \"alive\": true, \"age\": 16, \"traits\": [\"E\",\"R\",\"K\"] },\\\n", + " { \"name\": \"Bran\", \"surname\": \"Stark\", \"alive\": true, \"age\": 10, \"traits\": [\"L\",\"J\"] },\\\n", + " { \"name\": \"Joffrey\", \"surname\": \"Baratheon\", \"alive\": false, \"age\": 19, \"traits\": [\"I\",\"L\",\"O\"] },\\\n", + " { \"name\": \"Sandor\", \"surname\": \"Clegane\", \"alive\": true, \"traits\": [\"A\",\"P\",\"K\",\"F\"] },\\\n", + " { \"name\": \"Tyrion\", \"surname\": \"Lannister\", \"alive\": true, \"age\": 32, \"traits\": [\"F\",\"K\",\"M\",\"N\"] },\\\n", + " { \"name\": \"Khal\", \"surname\": \"Drogo\", \"alive\": false, \"traits\": [\"A\",\"C\",\"O\",\"P\"] },\\\n", + " { \"name\": \"Tywin\", \"surname\": \"Lannister\", \"alive\": false, \"traits\": [\"O\",\"M\",\"H\",\"F\"] },\\\n", + " { \"name\": \"Davos\", \"surname\": \"Seaworth\", \"alive\": true, \"age\": 49, \"traits\": [\"C\",\"K\",\"P\",\"F\"] },\\\n", + " { \"name\": \"Samwell\", \"surname\": \"Tarly\", \"alive\": true, \"age\": 17, \"traits\": [\"C\",\"L\",\"I\"] },\\\n", + " { \"name\": \"Stannis\", \"surname\": \"Baratheon\", \"alive\": false, \"traits\": [\"H\",\"O\",\"P\",\"M\"] },\\\n", + " { \"name\": \"Melisandre\", \"alive\": true, \"traits\": [\"G\",\"E\",\"H\"] },\\\n", + " { \"name\": \"Margaery\", \"surname\": \"Tyrell\", \"alive\": false, \"traits\": [\"M\",\"D\",\"B\"] },\\\n", + " { \"name\": \"Jeor\", \"surname\": \"Mormont\", \"alive\": false, \"traits\": [\"C\",\"H\",\"M\",\"P\"] },\\\n", + " { \"name\": \"Bronn\", \"alive\": true, \"traits\": [\"K\",\"E\",\"C\"] },\\\n", + " { \"name\": \"Varys\", \"alive\": true, \"traits\": [\"M\",\"F\",\"N\",\"E\"] },\\\n", + " { \"name\": \"Shae\", \"alive\": false, \"traits\": [\"M\",\"D\",\"G\"] },\\\n", + " { \"name\": \"Talisa\", \"surname\": \"Maegyr\", \"alive\": false, \"traits\": [\"D\",\"C\",\"B\"] },\\\n", + " { \"name\": \"Gendry\", \"alive\": false, \"traits\": [\"K\",\"C\",\"A\"] },\\\n", + " { \"name\": \"Ygritte\", \"alive\": false, \"traits\": [\"A\",\"P\",\"K\"] },\\\n", + " { \"name\": \"Tormund\", \"surname\": \"Giantsbane\", \"alive\": true, \"traits\": [\"C\",\"P\",\"A\",\"I\"] },\\\n", + " { \"name\": \"Gilly\", \"alive\": true, \"traits\": [\"L\",\"J\"] },\\\n", + " { \"name\": \"Brienne\", \"surname\": \"Tarth\", \"alive\": true, \"age\": 32, \"traits\": [\"P\",\"C\",\"A\",\"K\"] },\\\n", + " { \"name\": \"Ramsay\", \"surname\": \"Bolton\", \"alive\": true, \"traits\": [\"E\",\"O\",\"G\",\"A\"] },\\\n", + " { \"name\": \"Ellaria\", \"surname\": \"Sand\", \"alive\": true, \"traits\": [\"P\",\"O\",\"A\",\"E\"] },\\\n", + " { \"name\": \"Daario\", \"surname\": \"Naharis\", \"alive\": true, \"traits\": [\"K\",\"P\",\"A\"] },\\\n", + " { \"name\": \"Missandei\", \"alive\": true, \"traits\": [\"D\",\"L\",\"C\",\"M\"] },\\\n", + " { \"name\": \"Tommen\", \"surname\": \"Baratheon\", \"alive\": true, \"traits\": [\"I\",\"L\",\"B\"] },\\\n", + " { \"name\": \"Jaqen\", \"surname\": \"Hghar\", \"alive\": true, \"traits\": [\"H\",\"F\",\"K\"] },\\\n", + " { \"name\": \"Roose\", \"surname\": \"Bolton\", \"alive\": true, \"traits\": [\"H\",\"E\",\"F\",\"A\"] },\\\n", + " { \"name\": \"The High Sparrow\", \"alive\": true, \"traits\": [\"H\",\"M\",\"F\",\"O\"] }\\\n", + " ]\\\n", + " FOR d IN data INSERT d INTO Characters'\n", + " )" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "u_ftzlE3D0Po", + "colab_type": "text" + }, + "source": [ + "The LET keyword defines a variable with name data and an array of objects as value, so LET variableName = valueExpression and the expression being a literal array definition like [ {...}, {...}, ... ].\n", + "\n", + "FOR variableName IN expression is used to iterate over each element of the data array. In each loop, one element is assigned to the variable d. This variable is then used in the INSERT statement instead of a literal object definition. What is does is basically:" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Bk-EvGk-GeFH", + "colab_type": "code", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 799 + }, + "outputId": "041407a3-51f1-473c-d36e-acd3e6e9964c" + }, + "source": [ + "# Print all characters from Python Driver\n", + "for character in db.collection('Characters'):\n", + " print(\"- %s\" % character['name'])" + ], + "execution_count": 11, + "outputs": [ + { + "output_type": "stream", + "text": [ + "- Ned\n", + "- Robert\n", + "- Jaime\n", + "- Catelyn\n", + "- Cersei\n", + "- Daenerys\n", + "- Jorah\n", + "- Petyr\n", + "- Viserys\n", + "- Jon\n", + "- Sansa\n", + "- Arya\n", + "- Robb\n", + "- Theon\n", + "- Bran\n", + "- Joffrey\n", + "- Sandor\n", + "- Tyrion\n", + "- Khal\n", + "- Tywin\n", + "- Davos\n", + "- Samwell\n", + "- Stannis\n", + "- Melisandre\n", + "- Margaery\n", + "- Jeor\n", + "- Bronn\n", + "- Varys\n", + "- Shae\n", + "- Talisa\n", + "- Gendry\n", + "- Ygritte\n", + "- Tormund\n", + "- Gilly\n", + "- Brienne\n", + "- Ramsay\n", + "- Ellaria\n", + "- Daario\n", + "- Missandei\n", + "- Tommen\n", + "- Jaqen\n", + "- Roose\n", + "- The High Sparrow\n", + "- Robert\n", + "- Jaime\n", + "- Ned\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Scw6LAZZD06P", + "colab_type": "code", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + }, + "outputId": "d477c77b-816e-4ab8-a1f6-548c401f5981" + }, + "source": [ + "cursor = aql.execute('INSERT {'\n", + " '\"name\": \"Robert\",'\n", + " '\"surname\": \"Baratheon\",'\n", + " '\"alive\": false,'\n", + " '\"traits\": [\"A\",\"H\",\"C\"]'\n", + "'} INTO Characters'\n", + ")\n", + "cursor = aql.execute(\n", + " 'INSERT {'\n", + " '\"name\": \"Jaime\",'\n", + " '\"surname\": \"Lannister\",'\n", + " '\"alive\": true,'\n", + " '\"age\": 36,'\n", + " '\"traits\": [\"A\",\"F\",\"B\"]'\n", + "'} INTO Characters'\n", + ")\n", + "\n", + "print(cursor)" + ], + "execution_count": 7, + "outputs": [ + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "BzlILU_sEtAp", + "colab_type": "text" + }, + "source": [ + "Note: AQL does not permit multiple INSERT operations that target the same collection in a single query. It is allowed as body of a FOR loop however, inserting multiple documents like we did with above query." + ] + } + ] +} \ No newline at end of file