{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Aerospike Java Client – Reading and Updating Lists\n", "*Last updated: June 22, 2021*\n", "\n", "This notebook demonstrates Java Aerospike CRUD operations (Create, Read, Update, Delete) for lists of data, focusing on server-side **read** and **update** operations, including **sort**. \n", "\n", "This [Jupyter Notebook](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html) requires the Aerospike Database running locally with Java kernel and Aerospike Java Client. To create a Docker container that satisfies the requirements and holds a copy of these notebooks, visit the [Aerospike Notebooks Repo](https://github.com/aerospike-examples/interactive-notebooks)." ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true }, "source": [ "# Notebook Setup \n", "\n", "Run these first to initialize Jupyter, download the Java Client, and make sure the Aerospike Database is running." ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "## Import Jupyter Java Integration \n", "\n", "Make it easier to work with Java in Jupyter." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "hidden": true }, "outputs": [], "source": [ "import io.github.spencerpark.ijava.IJava;\n", "import io.github.spencerpark.jupyter.kernel.magic.common.Shell;\n", "\n", "IJava.getKernelInstance().getMagics().registerMagics(Shell.class);" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "## Start Aerospike\n", "\n", "Ensure Aerospike Database is running locally." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "hidden": true }, "outputs": [], "source": [ "%sh asd" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "## Download the Aerospike Java Client\n", "\n", "Ask Maven to download and install the project object model (POM) of the Aerospike Java Client." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "hidden": true }, "outputs": [], "source": [ "%%loadFromPOM\n", "\n", " \n", " com.aerospike\n", " aerospike-client\n", " 5.0.0\n", " \n", "" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "## Start the Aerospike Java Client and Connect\n", "\n", "Create an instance of the Aerospike Java Client, and connect to the demo cluster.\n", "\n", "The default cluster location for the Docker container is *localhost* port *3000*. If your cluster is not running on your local machine, modify *localhost* and *3000* to the values for your Aerospike cluster." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "hidden": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Initialized the client and connected to the cluster.\n" ] } ], "source": [ "import com.aerospike.client.AerospikeClient;\n", "\n", "AerospikeClient client = new AerospikeClient(\"localhost\", 3000);\n", "System.out.println(\"Initialized the client and connected to the cluster.\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# CREATING Lists in Aerospike" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create and Print List Data\n", "\n", "Create and print a String list and an Integer List. " ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "String List: [Annette, Redwood, Aquamarine, Pineapple]\n", "Integer List: [81, 3, 27, 9, 27, 1]\n" ] } ], "source": [ "import java.util.ArrayList;\n", "import java.util.Arrays;\n", "import java.util.List;\n", "import java.util.Map;\n", "\n", "ArrayList listStr = new ArrayList();\n", "listStr.add(\"Annette\");\n", "listStr.add(\"Redwood\");\n", "listStr.add(\"Aquamarine\");\n", "listStr.add(\"Pineapple\");\n", "System.out.println(\"String List: \" + listStr);\n", "\n", "ArrayList listInt = new ArrayList();\n", "listInt.add(81);\n", "listInt.add(3);\n", "listInt.add(27);\n", "listInt.add(9);\n", "listInt.add(27);\n", "listInt.add(1);\n", "System.out.println(\"Integer List: \" + listInt);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Insert the Lists into Aerospike" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create a Key Object\n", "\n", "A **Key** uniquely identifies a specific **Record** in your Aerospike server or cluster. Each key must have a **Namespace** and optionally a **Set** name. \n", "\n", "* In Aerospike, a **Namespace** is like a relational database's tablespace. \n", "* A **Set** is like a relational database table in Aerospike.\n", "* A **Record** is like a row in a relational database table.\n", "\n", "The namespace *test* is configured on your Aerospike server or cluster. The rest can be defined and modified by Aerospike Java Client Code.\n", "\n", "For additional information on the [Aerospike Data Model](https://www.aerospike.com/docs/architecture/data-model.html), go [here](https://www.aerospike.com/docs/architecture/data-model.html). " ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Key created.\n" ] } ], "source": [ "import com.aerospike.client.Key;\n", "\n", "String listSet = \"listset1\";\n", "String listNamespace = \"test\";\n", "\n", "Integer theKey = 0;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "System.out.println(\"Key created.\" );" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create a Bin Object for Each List\n", "\n", "A **Bin** is a data field in an Aerospike record." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created liststrbin:[Annette, Redwood, Aquamarine, Pineapple] and listintbin:[81, 3, 27, 9, 27, 1].\n" ] } ], "source": [ "import com.aerospike.client.Bin;\n", "\n", "String listStrBinName = \"liststrbin\";\n", "String listIntBinName = \"listintbin\";\n", "\n", "Bin bin1 = new Bin(listStrBinName, listStr);\n", "Bin bin2 = new Bin(listIntBinName, listInt);\n", "System.out.println( \"Created \" + bin1 + \" and \" + bin2 + \".\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create a Policy Object for Record Insertion \n", "\n", "A **Policy** tells Aerospike the intent of a database operation. \n", "\n", "For more information on policies, go [here](https://www.aerospike.com/docs/guide/policies.html)." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created a client policy.\n" ] } ], "source": [ "import com.aerospike.client.policy.ClientPolicy;\n", "\n", "ClientPolicy clientPolicy = new ClientPolicy();\n", "System.out.println(\"Created a client policy.\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Put the List Data into Aerospike" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Key: 0, liststrbin: [Annette, Redwood, Aquamarine, Pineapple], listintbin: [81, 3, 27, 9, 27, 1]\n" ] } ], "source": [ "client.put(clientPolicy.writePolicyDefault, key, bin1, bin2);\n", "System.out.println(\"Key: \" + theKey + \", \" + listStrBinName + \": \" + listStr + \", \" + listIntBinName + \": \" + listInt);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# READING Lists Elements From the Server\n", "\n", "Now that the lists are in Aerospike, the client can return full or partial lists from **bin** contents. No data is modified by these ops." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Get the Record\n", "\n", "A record can be retrieved using the **key**, **namespace**, and **set** name.\n", "\n", "In the output: \n", "* **gen** is the generation number, the number of record writes. \n", "* **exp** is the expiration counter for the record.\n", "\n", "For more information on [both generation number and expiration](https://www.aerospike.com/docs/guide/FAQ.html), see the [Aerospike FAQ](https://www.aerospike.com/docs/guide/FAQ.html)." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(gen:1),(exp:359404607),(bins:(liststrbin:[Annette, Redwood, Aquamarine, Pineapple]),(listintbin:[81, 3, 27, 9, 27, 1]))\n" ] } ], "source": [ "import com.aerospike.client.Record;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "Record record = client.get(null, key);\n", "System.out.println(record);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Get String Elements By Index and Rank\n", "\n", "The Aerospike API contains the operations to get list elements using index and rank." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Get the Last String\n", "\n", "Aerospike provides operations to read list element(s) by **index**. As a convenience, the client returns the specified value as the contents of the bin.\n", "\n", "Aerospike operations allow indexing forward from the beginning of the list using zero-based numbering. Negative numbers index backwards from the end of a list. \n", "\n", "For more examples of indexes, go [here](https://www.aerospike.com/apidocs/java/com/aerospike/client/cdt/ListOperation.html). " ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The string list: [Annette, Redwood, Aquamarine, Pineapple]\n", "The last string: Pineapple\n" ] } ], "source": [ "import com.aerospike.client.Operation;\n", "import com.aerospike.client.Value;\n", "import com.aerospike.client.cdt.ListOperation;\n", "\n", "int last = -1;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "Record record = client.get(null, key);\n", "Record lastString = client.operate(null, key, \n", " ListOperation.get(listStrBinName, last)\n", " );\n", " \n", "System.out.println(\"The string list: \" + record.getValue(listStrBinName));\n", "System.out.println(\"The last string: \" + lastString.getValue(listStrBinName));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Get the Highest Rank Item\n", "\n", "Aerospike provides operations to read list item(s) by **Rank**. The API methods contain options prescribing what type of data to return from an operation. \n", "\n", "For information on list ranking, go [here](https://en.wikipedia.org/wiki/List_ranking).\n", "\n", "For the list of return type options, go [here](https://www.aerospike.com/apidocs/java/com/aerospike/client/cdt/ListReturnType.html). " ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The string list: [Annette, Redwood, Aquamarine, Pineapple]\n", "The highest rank string: Redwood\n" ] } ], "source": [ "import com.aerospike.client.cdt.ListReturnType;\n", "\n", "int highestRank = -1;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "Record record = client.get(null, key);\n", "Record highestRankString = client.operate(null, key, \n", " ListOperation.getByRank(listStrBinName, highestRank, ListReturnType.VALUE)\n", " );\n", " \n", "System.out.println(\"The string list: \" + record.getValue(listStrBinName));\n", "System.out.println(\"The highest rank string: \" + highestRankString.getValue(listStrBinName));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Get Integer Elements By Value Range and Rank Range\n", "\n", "Read integer values from the Aerospike Server or Cluster using value range or rank range. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Get Integers Between 3 and 27\n", "\n", "In addition to reading list elements by rank and index, Aerospike operations can return a **Range** of elements by value.\n", "* The lower bound of a range is included.\n", "* The upper bound of a range is excluded.\n", "\n", "For more examples of ranges, go [here](https://www.aerospike.com/apidocs/java/com/aerospike/client/cdt/ListOperation.html). " ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The integer list: [81, 3, 27, 9, 27, 1]\n", "The integers between 3 and 27: [3, 9]\n" ] } ], "source": [ "int lowerBound = 3;\n", "int upperBound = 27;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "Record record = client.get(null, key);\n", "Record between3And27 = client.operate(null, key, \n", " ListOperation.getByValueRange(listIntBinName, Value.get(lowerBound), Value.get(upperBound), \n", " ListReturnType.VALUE)\n", " );\n", "\n", "System.out.println(\"The integer list: \" + record.getValue(listIntBinName));\n", "System.out.println(\"The integers between \" + lowerBound + \" and \" + upperBound + \": \" \n", " + between3And27.getValue(listIntBinName));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Get the 2nd and 3rd Ranked Integers\n", "\n", "Aerospike provides operations to return a range of elements by rank. Rank is zero-based. " ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The integer list: [81, 3, 27, 9, 27, 1]\n", "The 2nd and 3rd ranked integers: [9, 3]\n" ] } ], "source": [ "int secondRank = 1;\n", "int rangeRankSize = 2;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "Record record = client.get(null, key);\n", "Record rank1And2 = client.operate(client.writePolicyDefault, key, \n", " ListOperation.getByRankRange(listIntBinName, secondRank, rangeRankSize, ListReturnType.VALUE)\n", " );\n", " \n", "System.out.println(\"The integer list: \" + record.getValue(listIntBinName));\n", "System.out.println(\"The 2nd and 3rd ranked integers: \" + rank1And2.getValue(listIntBinName));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# UPDATING Lists on the Aerospike Server\n", "\n", "Aerospike's [list operations](https://www.aerospike.com/apidocs/java/com/aerospike/client/cdt/ListOperation.html) can also modify data in the Aerospike Database." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Update the String List in Aerospike" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Insert a Fish into the Second and Second-from-last Position\n", "\n", "Aerospike's list insert operation inserts before the item at an index, and increases the index of the item at the index and all subsequent items in the list." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Before – [Annette, Redwood, Aquamarine, Pineapple]\n", " After – [Annette, Koi, Redwood, Aquamarine, Koi, Pineapple]\n" ] } ], "source": [ "String Fish = \"Koi\";\n", "int secondPosition = 1;\n", "int beforeLastPosition = -1;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "Record origRecord = client.get(null, key);\n", "System.out.println(\"Before – \" + origRecord.getValue(listStrBinName));\n", "\n", "origRecord = client.operate(client.writePolicyDefault, key, \n", " ListOperation.insert(listStrBinName, beforeLastPosition, Value.get(Fish)),\n", " ListOperation.insert(listStrBinName, secondPosition, Value.get(Fish))\n", " );\n", "\n", "Record finalRecord = client.get(null, key);\n", "System.out.println(\" After – \" + finalRecord.getValue(listStrBinName));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Remove By Index from the String List" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Before – [Annette, Koi, Redwood, Aquamarine, Koi, Pineapple]\n", " After – [Koi, Redwood, Aquamarine, Koi, Pineapple]\n" ] } ], "source": [ "int firstPosition = 0;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "Record origRecord = client.get(null, key);\n", "System.out.println(\"Before – \" + origRecord.getValue(listStrBinName));\n", "\n", "origRecord = client.operate(client.writePolicyDefault, key, \n", " ListOperation.remove(listStrBinName, firstPosition)\n", " );\n", "\n", "Record finalRecord = client.get(null, key);\n", "System.out.println(\" After – \" + finalRecord.getValue(listStrBinName));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Update the Integer List in Aerospike" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Append 17 to the List" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Before – [81, 3, 27, 9, 27, 1]\n", " After – [81, 3, 27, 9, 27, 1, 17]\n" ] } ], "source": [ "int seventeen = 17;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "Record origRecord = client.get(null, key);\n", "System.out.println(\"Before – \" + origRecord.getValue(listIntBinName));\n", "\n", "origRecord = client.operate(client.writePolicyDefault, key, \n", " ListOperation.append(listIntBinName, Value.get(seventeen))\n", " );\n", "\n", "Record finalRecord = client.get(null, key);\n", "System.out.println(\" After – \" + finalRecord.getValue(listIntBinName));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Increment the 4th Integer by 111\n", "\n", "Indexes into lists start at 0." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Before – [81, 3, 27, 9, 27, 1, 17]\n", " After – [81, 3, 27, 120, 27, 1, 17]\n" ] } ], "source": [ "int incNum = 111;\n", "int incIndex = 3;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "Record origRecord = client.get(null, key);\n", "System.out.println(\"Before – \" + origRecord.getValue(listIntBinName) );\n", "\n", "origRecord = client.operate(client.writePolicyDefault, key, \n", " ListOperation.increment(listIntBinName, incIndex, Value.get(incNum))\n", " );\n", "\n", "Record finalRecord = client.get(null, key);\n", "System.out.println(\" After – \" + finalRecord.getValue(listIntBinName) );" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Sorting the Lists in the Aerospike Java Client\n", "\n", "Aerospike also provides both:\n", "1. An operation to **sort** lists in the client and optionally remove duplicates.\n", "2. An operation to store list data in **order**. \n", "\n", "For information on maintaining list data in order, go [here](https://www.aerospike.com/apidocs/java/com/aerospike/client/cdt/ListOrder.html)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Sort the String and Drop Duplicates\n", "\n", "For information on the flags specifying whether to remove duplicates, go [here](https://www.aerospike.com/apidocs/java/com/aerospike/client/cdt/ListSortFlags.html). " ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Unsorted – [Koi, Redwood, Aquamarine, Koi, Pineapple]\n", " Sorted – [Aquamarine, Koi, Pineapple, Redwood]\n" ] } ], "source": [ "import com.aerospike.client.cdt.ListSortFlags;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "Record origRecord = client.get(null, key);\n", "System.out.println(\"Unsorted – \" + origRecord.getValue(listStrBinName));\n", "\n", "origRecord = client.operate(client.writePolicyDefault, key, \n", " ListOperation.sort(listStrBinName, ListSortFlags.DROP_DUPLICATES)\n", " );\n", "\n", "Record finalRecord = client.get(null, key);\n", "System.out.println(\" Sorted – \" + finalRecord.getValue(listStrBinName));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Sort the Integer List and Keep Duplicates" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Unsorted – [81, 3, 27, 120, 27, 1, 17]\n", " Sorted – [1, 3, 17, 27, 27, 81, 120]\n" ] } ], "source": [ "Key key = new Key(listNamespace, listSet, theKey);\n", "Record origRecord = client.get(null, key);\n", "System.out.println(\"Unsorted – \" + origRecord.getValue(listIntBinName));\n", "\n", "origRecord = client.operate(client.writePolicyDefault, key, \n", " ListOperation.sort(listIntBinName, ListSortFlags.DEFAULT)\n", " );\n", "\n", "Record finalRecord = client.get(null, key);\n", "System.out.println(\" Sorted – \" + finalRecord.getValue(listIntBinName));" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true }, "source": [ "# Notebook Cleanup" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "## Truncate the Set\n", "Truncate the set from the Aerospike Database." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "hidden": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set truncated.\n" ] } ], "source": [ "import com.aerospike.client.policy.InfoPolicy;\n", "InfoPolicy infoPolicy = new InfoPolicy();\n", "\n", "client.truncate(infoPolicy, listNamespace, listSet, null);\n", "System.out.println(\"Set truncated.\");" ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "## Close the Connection to Aerospike" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "hidden": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Server connection closed.\n" ] } ], "source": [ "client.close();\n", "System.out.println(\"Server connection closed.\");" ] }, { "cell_type": "markdown", "metadata": { "heading_collapsed": true }, "source": [ "# Code Summary\n", "\n", "Here is a collection of all of the non-Jupyter code from this tutorial." ] }, { "cell_type": "markdown", "metadata": { "hidden": true }, "source": [ "## Overview\n", "\n", "1. Import Java Libraries.\n", "2. Import Aerospike Client Libraries.\n", "3. Start the Aerospike Client.\n", "4. Create Test Data.\n", "5. Put Record into Aerospike.\n", "6. Get Data from Aerospike.\n", " 1. Get the Record.\n", " 2. Get the Last String and Highest Rank.\n", " 3. Get Integers Between 3 and 27.\n", " 4. Get 2 Integers By Rank Starting with the Second Rank Item. \n", "7. Update the Record in Aerospike\n", " 1. Add Koi twice to the String List.\n", " 2. Remove the Name from the String List.\n", " 3. Append 17 to the Integer List.\n", " 4. Increment the 4th Integer by 111.\n", " 5. Sort the Strings and Drop Duplicates.\n", " 6. Sort the Integers and Keep Duplicates.\n", "8. Truncate the Set.\n", "9. Close the Client Connections." ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "hidden": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Initialized the client and connected to the cluster.\n", "Created String List: [Annette, Redwood, Aquamarine, Pineapple]\n", "Created Integer List: [81, 3, 27, 9, 27, 1]\n", "Inserted Key: 0, liststrbin: [Annette, Redwood, Aquamarine, Pineapple], listintbin: [81, 3, 27, 9, 27, 1]\n", "Read the Full Record From Aerospike:(gen:1),(exp:359404610),(bins:(liststrbin:[Annette, Redwood, Aquamarine, Pineapple]),(listintbin:[81, 3, 27, 9, 27, 1]))\n", "The last string: Pineapple\n", "The highest rank string: Redwood\n", "The integers between 3 and 27: [3, 9]\n", "The 2nd and 3rd ranked integers: [9, 3]\n", "Inserted Koi; liststrbin size is now: 5\n", "Inserted Koi; liststrbin size is now: 6\n", "Removed item at index 0; removed 1 item\n", "Appended 17, listintbin size is now 7\n", "Incremented item at index 3 by 111; new value is: 120\n", "Sorted both lists and removed duplicates in liststrbin\n", "After Record Edits – (gen:2),(exp:359404610),(bins:(liststrbin:[Aquamarine, Koi, Pineapple, Redwood]),(listintbin:[1, 3, 17, 27, 27, 81, 120]))\n", "Set truncated.\n", "Closed client connections.\n" ] } ], "source": [ "// Import Java Libraries.\n", "\n", "import java.util.ArrayList;\n", "import java.util.Arrays;\n", "import java.util.List;\n", "import java.util.Map;\n", "\n", "\n", "// Import Aerospike Client Libraries.\n", "\n", "import com.aerospike.client.AerospikeClient;\n", "import com.aerospike.client.Key;\n", "import com.aerospike.client.Bin;\n", "import com.aerospike.client.policy.ClientPolicy;\n", "import com.aerospike.client.Record;\n", "import com.aerospike.client.Operation;\n", "import com.aerospike.client.Value;\n", "import com.aerospike.client.cdt.ListOperation;\n", "import com.aerospike.client.cdt.ListReturnType;\n", "import com.aerospike.client.cdt.ListSortFlags;\n", "import com.aerospike.client.policy.InfoPolicy;\n", "\n", "\n", "// Start the Aerospike Client.\n", "\n", "AerospikeClient client = new AerospikeClient(\"localhost\", 3000);\n", "System.out.println(\"Initialized the client and connected to the cluster.\");\n", "\n", "\n", "// Create Test Data.\n", "\n", "ArrayList listStr = new ArrayList();\n", "listStr.add(\"Annette\");\n", "listStr.add(\"Redwood\");\n", "listStr.add(\"Aquamarine\");\n", "listStr.add(\"Pineapple\");\n", "System.out.println(\"Created String List: \" + listStr);\n", "\n", "ArrayList listInt = new ArrayList();\n", "listInt.add(81);\n", "listInt.add(3);\n", "listInt.add(27);\n", "listInt.add(9);\n", "listInt.add(27);\n", "listInt.add(1);\n", "System.out.println(\"Created Integer List: \" + listInt);\n", "\n", "\n", "// Put Record into Aerospike.\n", "\n", "String listSet = \"listset1\";\n", "String listNamespace = \"test\";\n", "String listStrBinName = \"liststrbin\";\n", "String listIntBinName = \"listintbin\";\n", "ClientPolicy clientPolicy = new ClientPolicy();\n", "InfoPolicy infoPolicy = new InfoPolicy();\n", "\n", "\n", "Integer theKey = 0;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "Bin bin1 = new Bin(listStrBinName, listStr);\n", "Bin bin2 = new Bin(listIntBinName, listInt);\n", "client.put(clientPolicy.writePolicyDefault, key, bin1, bin2);\n", "System.out.println(\"Inserted Key: \" + theKey + \", \" + listStrBinName + \": \" + listStr + \", \" + listIntBinName + \": \" + listInt);\n", "\n", "\n", "// Get Data from Aerospike.\n", "// 1. Get Record.\n", "// 2. Get the Last String and Highest Rank.\n", "// 3. Get Integers Between 3 and 27.\n", "// 4. Get 2 Integers By Rank Starting with the Second Rank Item. \n", "\n", "int last = -1;\n", "int highestRank = -1;\n", "int lowerBound = 3;\n", "int upperBound = 27;\n", "int secondRank = 1;\n", "int rangeRankSize = 2;\n", "\n", "Key key = new Key(listNamespace, listSet, theKey);\n", "Record record = client.get(null, key);\n", "Record postOp = client.operate(client.writePolicyDefault, key, \n", " ListOperation.get(listStrBinName, last),\n", " ListOperation.getByRank(listStrBinName, highestRank, ListReturnType.VALUE),\n", " ListOperation.getByValueRange(listIntBinName, Value.get(lowerBound), Value.get(upperBound), \n", " ListReturnType.VALUE),\n", " ListOperation.getByRankRange(listIntBinName, secondRank, rangeRankSize, ListReturnType.VALUE)\n", " );\n", "\n", "List returnStr = postOp.getList(listStrBinName);\n", "List returnIntList = postOp.getList(listIntBinName); \n", "\n", "System.out.println(\"Read the Full Record From Aerospike:\" + record);\n", "System.out.println(\"The last string: \" + returnStr.get(0));\n", "System.out.println(\"The highest rank string: \" + returnStr.get(1));\n", "System.out.println(\"The integers between \" + lowerBound + \" and \" + upperBound + \": \" \n", " + returnIntList.get(0));\n", "System.out.println(\"The 2nd and 3rd ranked integers: \" + returnIntList.get(1));\n", "\n", "\n", "// Update the Record in Aerospike\n", "// 1. Add Koi twice to the String List.\n", "// 2. Remove the Name from the String List.\n", "// 3. Append 17 to the Integer List.\n", "// 4. Increment the 4th Integer by 111.\n", "// 5. Sort the Strings and Drop Duplicates.\n", "// 6. Sort the Integers and Keep Duplicates.\n", "\n", "String Fish = \"Koi\";\n", "int fishIndex0 = 1;\n", "int fishIndex1 = -1;\n", "int nameIndex = 0;\n", "int seventeen = 17;\n", "int incNum = 111;\n", "int incIndex = 3;\n", "\n", "origRecord = client.operate(client.writePolicyDefault, key, \n", " ListOperation.insert(listStrBinName, fishIndex0, Value.get(Fish)),\n", " ListOperation.insert(listStrBinName, fishIndex1, Value.get(Fish)),\n", " ListOperation.remove(listStrBinName, nameIndex),\n", " ListOperation.append(listIntBinName, Value.get(seventeen)),\n", " ListOperation.increment(listIntBinName, incIndex, Value.get(incNum)),\n", " ListOperation.sort(listStrBinName, ListSortFlags.DROP_DUPLICATES),\n", " ListOperation.sort(listIntBinName, ListSortFlags.DEFAULT)\n", " );\n", "\n", "List opStrResults = origRecord.getList(listStrBinName);\n", "List opIntResults = origRecord.getList(listIntBinName);\n", "\n", "Record finalRecord = client.get(null, key);\n", "System.out.println(\"Inserted \" + Fish + \"; \" + listStrBinName + \" size is now: \" + opStrResults.get(0));\n", "System.out.println(\"Inserted \" + Fish + \"; \" + listStrBinName + \" size is now: \" + opStrResults.get(1));\n", "System.out.println(\"Removed item at index \" + nameIndex + \"; removed \" + opStrResults.get(2) + \" item\");\n", "System.out.println(\"Appended \" + seventeen + \", \" + listIntBinName + \" size is now \" + opIntResults.get(0));\n", "System.out.println(\"Incremented item at index \" + incIndex + \" by \" + incNum + \"; new value is: \" + opIntResults.get(1));\n", "System.out.println(\"Sorted both lists and removed duplicates in \" + listStrBinName);\n", "System.out.println(\"After Record Edits – \" + finalRecord);\n", "\n", "\n", "// Truncate the Set.\n", "\n", "client.truncate(infoPolicy, listNamespace, listSet, null);\n", "System.out.println(\"Set truncated.\");\n", "\n", "// Close the Client Connections.\n", "\n", "client.close();\n", "System.out.println(\"Closed client connections.\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Takeaway – Aerospike Does Lists\n", "\n", "Aerospike and its Java Client are up to the task of working with your list data. APIs contain rich operations to read and update list data using index, value, and rank. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# What's Next?\n", "\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Next Steps\n", "\n", "Have questions? Don't hesitate to reach out if you have additional questions about working with lists at https://discuss.aerospike.com/.\n", "\n", "Want to learn about modeling using Lists? See, [Modeling Using Lists](java-modeling_using_lists.ipynb).\n", " \n", "\n", "Want to check out other Java notebooks?\n", "1. [Hello, World](hello_world.ipynb)\n", "2. [Reading and Updating Maps](java-working_with_maps.ipynb)\n", "3. [Aerospike Query and UDF](query_udf.ipynb)\n", "\n", "Are you running this from Binder? [Download the Aerospike Notebook Repo](https://github.com/aerospike-examples/interactive-notebooks) and work with Aerospike Database and Jupyter locally using a Docker container." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Additional Resources\n", "\n", "* Want to get started with Java? [Download](https://www.aerospike.com/download/client/) or [install](https://github.com/aerospike/aerospike-client-java) the Aerospike Java Client. \n", "* What other ways can we work with Lists? Take a look at [Aerospike's List Operations](https://www.aerospike.com/apidocs/java/com/aerospike/client/cdt/ListOperation.html).\n", "* What are Namespaces, Sets, and Bins? Check out the [Aerospike Data Model](https://www.aerospike.com/docs/architecture/data-model.html). \n", "* How robust is the Aerospike Database? Browse the [Aerospike Database Architecture](https://www.aerospike.com/docs/architecture/index.html)." ] } ], "metadata": { "kernelspec": { "display_name": "Java", "language": "java", "name": "java" }, "language_info": { "codemirror_mode": "java", "file_extension": ".jshell", "mimetype": "text/x-java-source", "name": "Java", "pygments_lexer": "java", "version": "11.0.8+10-LTS" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": true } }, "nbformat": 4, "nbformat_minor": 4 }