<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Eugene R.</title>
    <description>The latest articles on DEV Community by Eugene R. (@reugn).</description>
    <link>https://dev.to/reugn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F372403%2F6655c7f6-6511-4df1-8f76-09c7e01b6885.jpeg</url>
      <title>DEV Community: Eugene R.</title>
      <link>https://dev.to/reugn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/reugn"/>
    <language>en</language>
    <item>
      <title>Aerospike Trino Connector - Chapter Two</title>
      <dc:creator>Eugene R.</dc:creator>
      <pubDate>Mon, 06 Jun 2022 18:07:28 +0000</pubDate>
      <link>https://dev.to/aerospike/aerospike-trino-connector-chapter-two-13gl</link>
      <guid>https://dev.to/aerospike/aerospike-trino-connector-chapter-two-13gl</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qHcQ2G6D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/0%2AYjst0a2Ieot5M_bg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qHcQ2G6D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/0%2AYjst0a2Ieot5M_bg" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@sl33vo?utm_source=medium&amp;amp;utm_medium=referral"&gt;Danny Sleeuwenhoek&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed up your SQL queries using Aerospike secondary indexes
&lt;/h2&gt;

&lt;p&gt;With &lt;a href="https://aerospike.com/blog/database-queries-json-db-6/"&gt;Aerospike Server 6.0&lt;/a&gt;, we have enhanced secondary index queries to allow for querying by partition, throttling, etc. The Trino connector now leverages this functionality to accelerate your secondary key queries at scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a secondary index?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://docs.aerospike.com/server/architecture/secondary-index"&gt;secondary index&lt;/a&gt; is a data structure used to quickly locate all the records in a namespace, or a set within it, based on a bin value in the record. When a value is updated in the indexed record, the secondary index automatically updates. You can retrieve records whose indexed value matches specified criteria using a secondary index query.&lt;/p&gt;

&lt;p&gt;A query in Trino against a non-primary key bin that does not have a secondary index would invariably trigger a set (table) scan leading to an inefficient query. You can imagine the performance penalty that you would incur when dealing with a billion record table. &lt;a href="https://docs.aerospike.com/tools/aql/index_management"&gt;Creating a secondary index&lt;/a&gt; (sindex) on a high-cardinality bin can help significantly speed up your Trino queries.&lt;/p&gt;

&lt;p&gt;As shown in Figure 1, Aerospike secondary indexes are stored in DRAM for fast look-up, built on every partition in each cluster node, and are co-located with the primary index. Each secondary index entry contains only references to records local to the node.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L4-PbBgB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/0%2A7usxNeb_o8dPOA0J" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L4-PbBgB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/0%2A7usxNeb_o8dPOA0J" width="800" height="641"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1: Secondary index query&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I get started?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Creating a secondary index on a bin in Aerospike is easy. You can use an Aerospike tool, such as asadm, or the API to dynamically create and remove indexes based on bins and data types you want to index. For an indexed bin, updating the record to include the bin updates the index. See &lt;a href="https://docs.aerospike.com/tools/aql/index_management"&gt;how to create a secondary index&lt;/a&gt; for more information.&lt;/p&gt;

&lt;p&gt;The Trino connector automatically analyzes the query and applies a secondary index to it, if one is available. If you know the cardinality of the secondary indexes, you can declare which sindex should be used for your query using the &lt;code&gt;sindex_name&lt;/code&gt; &lt;a href="https://trino.io/docs/current/sql/set-session.html"&gt;session property&lt;/a&gt;. The &lt;code&gt;__sindex&lt;/code&gt; table is created for each schema and provides details on available secondary indexes. You can change its name using the &lt;code&gt;aerospike.index-table-name&lt;/code&gt; configuration property.&lt;/p&gt;

&lt;p&gt;Here is an example of secondary indexes that we’ll see in action later:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v3JhJDxq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/1%2Am0TvtLQzBIkwUUaxLjMwyA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v3JhJDxq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/1%2Am0TvtLQzBIkwUUaxLjMwyA.png" width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We recommend that you provide the sindex to use in the query. The statement below shows an example of declaring a sindex to use:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;set session aerospike.sindex_name=idx1;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you do not declare a sindex for your query when multiple sindexes are available, the connector will pick the sindex with the highest lexical order from the list of available secondary indexes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Will this really improve my Trino SQL query performance?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Prior to supporting secondary indexes, each query that was not a primary key search ended up with a full table scan on the Aerospike side. To illustrate my point, I will use a large (~20M records) data set to compare query response times with and without a secondary index.&lt;/p&gt;

&lt;p&gt;A query for a particular &lt;code&gt;pkup_datetime&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;With a string secondary index:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--18g6JmvC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/1%2A1jnt7PYNuHOjFSB5dVP1cA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--18g6JmvC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/1%2A1jnt7PYNuHOjFSB5dVP1cA.png" width="800" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without a secondary index:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8aGre4rk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/1%2AdAM-lsyGQxXRh9xKwXdCUA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8aGre4rk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/1%2AdAM-lsyGQxXRh9xKwXdCUA.png" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another example of a range query on the &lt;code&gt;id&lt;/code&gt; column:&lt;/p&gt;

&lt;p&gt;Using a numeric secondary index:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SaiIvC3W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/1%2AF_DuaVvf38EBJy1_hfbUnw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SaiIvC3W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/1%2AF_DuaVvf38EBJy1_hfbUnw.png" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without a secondary index:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--chw9Q9Pb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/1%2A5J5mNrOVFYYG9VniUrK9eQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--chw9Q9Pb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/1400/1%2A5J5mNrOVFYYG9VniUrK9eQ.png" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The response time is in seconds and we can see that the performance gain is significant. The primary index (PI) query was ~80 times slower than the secondary index (SI) query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Aerospike secondary indexes can make a huge performance difference to your SQL queries. Make sure you read the official documentation regarding the compatibility and installation.&lt;/p&gt;

&lt;p&gt;And finally, process your data faster than ever with the new &lt;a href="https://docs.aerospike.com/connect/presto"&gt;Aerospike Connect for Presto&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>trino</category>
      <category>secondaryindex</category>
    </item>
    <item>
      <title>Continuous Integration with Aerospike on GitHub</title>
      <dc:creator>Eugene R.</dc:creator>
      <pubDate>Wed, 21 Apr 2021 09:54:36 +0000</pubDate>
      <link>https://dev.to/aerospike/continuous-integration-with-aerospike-on-github-36pn</link>
      <guid>https://dev.to/aerospike/continuous-integration-with-aerospike-on-github-36pn</guid>
      <description>&lt;p&gt;&lt;a href="https://www.aerospike.com/"&gt;Aerospike&lt;/a&gt; is a highly available and scalable NoSQL distributed database used in production to provide blazingly fast performance at a Petabyte scale.&lt;/p&gt;

&lt;p&gt;As a software engineer developing with Aerospike, you probably needed integration tests, and you already have your own way to set up an Aerospike cluster for this.&lt;/p&gt;

&lt;p&gt;In this short post I will show you how to add an Aerospike server to your development workflows using the &lt;a href="https://github.com/marketplace/actions/set-up-aerospike-database"&gt;GitHub Action&lt;/a&gt; in seconds.&lt;/p&gt;

&lt;p&gt;As a GitHub user, you may already know what GitHub actions are. They were &lt;a href="https://github.blog/2018-10-16-future-of-software/"&gt;launched&lt;/a&gt; in late 2018 and set a new standard for CI/CD on GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;The first thing you need is to have your repository hosted on GitHub. Better understand the &lt;a href="https://docs.github.com/en/actions"&gt;GitHub Actions&lt;/a&gt; if you’re new to them.&lt;/p&gt;

&lt;p&gt;My Aerospike GitHub action repository is &lt;a href="https://github.com/reugn/github-action-aerospike"&gt;here&lt;/a&gt;, and it is also &lt;a href="https://github.com/marketplace/actions/set-up-aerospike-database"&gt;published&lt;/a&gt; on the GitHub marketplace.&lt;/p&gt;

&lt;p&gt;Now what’s left is to see some&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage examples
&lt;/h2&gt;

&lt;p&gt;You can set up either Aerospike Community Edition or Enterprise Edition. What makes the difference is the &lt;code&gt;feature-key-file&lt;/code&gt; parameter. Specify it to have an Aerospike Server Enterprise Edition.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aerospike Community Edition
&lt;/h3&gt;

&lt;p&gt;To set up an Aerospike Community Edition server with the default configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Aerospike Database&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;reugn/github-action-aerospike@v1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Aerospike Enterprise Edition
&lt;/h3&gt;

&lt;p&gt;To set up an Aerospike Enterprise Edition server by specifying the port, the server configuration and the feature key files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Aerospike Database&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;reugn/github-action-aerospike@v1&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3300&lt;/span&gt;
    &lt;span class="na"&gt;config-file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.github/aerospike/aerospike.conf'&lt;/span&gt;
    &lt;span class="na"&gt;feature-key-file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.github/aerospike/features.conf'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to commit the configuration and the feature key files in your repository and provide the path, they must be in the same directory.&lt;/p&gt;

&lt;p&gt;Now you have your Aerospike server running on Docker and ready for integration tests.&lt;/p&gt;

&lt;p&gt;A complete list of supported inputs is available &lt;a href="https://github.com/reugn/github-action-aerospike#inputs"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;That was fast as I promised. Both the read and the setup. Hope you found this useful, and don’t forget to subscribe to our &lt;a href="https://www.aerospike.com/forms/subscribe-the-aerospike-standup/"&gt;newsletter&lt;/a&gt; to get updated with Aerospike weekly news.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>github</category>
      <category>ci</category>
    </item>
    <item>
      <title>Skyhook: a Redis-compatible interface to Aerospike Database</title>
      <dc:creator>Eugene R.</dc:creator>
      <pubDate>Tue, 20 Apr 2021 16:21:39 +0000</pubDate>
      <link>https://dev.to/aerospike/skyhook-a-redis-compatible-interface-to-aerospike-database-4hjj</link>
      <guid>https://dev.to/aerospike/skyhook-a-redis-compatible-interface-to-aerospike-database-4hjj</guid>
      <description>&lt;p&gt;&lt;a href="https://www.aerospike.com/"&gt;Aerospike&lt;/a&gt; is a highly available and scalable NoSQL distributed database used in production to provide blazingly fast performance at Petabyte scale. Production deployments of Aerospike are almost always serving their data from NVMe drives, though it’s possible to run namespaces in memory.&lt;/p&gt;

&lt;p&gt;Redis is a well loved key-value data store that is widely used by developers, which was designed to run single node (single-threaded originally) and in-memory.&lt;br&gt;
This article might be interesting to developers who are using &lt;a href="https://redis.io/"&gt;Redis&lt;/a&gt; and looking for more scalable and highly available alternatives, or maybe already have some applications running on Aerospike.&lt;/p&gt;

&lt;p&gt;Migrating to a different technology is always a challenging process. You need to train engineers, rewrite the codebase, and set up a production cluster to take over. Using &lt;a href="https://github.com/aerospike/skyhook"&gt;Skyhook&lt;/a&gt;, you can move applications to Aerospike first, then come back to rewrite them as Aerospike native, or if you’re satisfied with their performance, keep them as they are.&lt;br&gt;
Or maybe you’re looking to expose your Aerospike data to external Redis-based applications? We would love to hear how you would use this project.&lt;/p&gt;
&lt;h2&gt;
  
  
  Skyhook to the rescue
&lt;/h2&gt;

&lt;p&gt;We, as a company, observed this need and came up with the highly performant bridge service, which acts as a fully-fledged (with commands support limitation) Redis server, bridging the clients’ commands to Aerospike clusters.&lt;/p&gt;
&lt;h2&gt;
  
  
  Technical details
&lt;/h2&gt;

&lt;p&gt;Skyhook is a standalone server application written in Kotlin, which projects Redis protocol commands to an Aerospike cluster using the Aerospike Java client under the hood. The server supports a single namespace and set configuration, where the incoming commands will be applied. This project uses &lt;a href="https://netty.io/"&gt;Netty&lt;/a&gt; as a non-blocking I/O client-server framework.&lt;/p&gt;

&lt;p&gt;Netty, is a highly performant JVM asynchronous event-driven network application framework. Its customizable thread model and native transport support forge an incredibly performant network communication layer.&lt;/p&gt;

&lt;p&gt;What’s left is to translate Redis commands to Aerospike commands, and here come the async capabilities of the Aerospike Java Client.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installation and configuration
&lt;/h2&gt;

&lt;p&gt;You will need JDK8 and an Aerospike Server version &amp;gt;= 4.9 because Skyhook uses the new scan capabilities which are available starting from that version.&lt;/p&gt;

&lt;p&gt;Clone &lt;a href="https://github.com/aerospike/skyhook"&gt;aerospike/skyhook&lt;/a&gt; or grab a prebuilt executable JAR from the &lt;a href="https://github.com/aerospike/skyhook/releases"&gt;releases&lt;/a&gt; to get started.&lt;/p&gt;

&lt;p&gt;To build the service from the sources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew clean build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will build an executable JAR file.&lt;/p&gt;

&lt;p&gt;Skyhook is configured using a configuration file and it’s in YAML format. You will need to specify it using the &lt;code&gt;-f&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;To run the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; skyhook-[version]-all.jar &lt;span class="nt"&gt;-f&lt;/span&gt; config/server.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An example configuration file can be found in the config folder under the project repository.&lt;/p&gt;

&lt;p&gt;Here are the current configuration properties available.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Default value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;hostList&lt;/td&gt;
&lt;td&gt;The host list to seed the Aerospike cluster.&lt;/td&gt;
&lt;td&gt;localhost:3000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;namespase&lt;/td&gt;
&lt;td&gt;The Aerospike namespace.&lt;/td&gt;
&lt;td&gt;test&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;set&lt;/td&gt;
&lt;td&gt;The Aerospike set name.&lt;/td&gt;
&lt;td&gt;redis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bin&lt;/td&gt;
&lt;td&gt;The Aerospike bin name to set values.&lt;/td&gt;
&lt;td&gt;b&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;redisPort&lt;/td&gt;
&lt;td&gt;The server port to bind to.&lt;/td&gt;
&lt;td&gt;6379&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;workerThreads&lt;sup&gt;1&lt;/sup&gt;
&lt;/td&gt;
&lt;td&gt;The Netty worker group size.&lt;/td&gt;
&lt;td&gt;number of available cores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bossThreads&lt;/td&gt;
&lt;td&gt;The Netty acceptor group size.&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; &lt;code&gt;workerThreads&lt;/code&gt; property is used to configure the size of the Aerospike Java Client EventLoops as well.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;workerThreads&lt;/code&gt; and &lt;code&gt;bossThreads&lt;/code&gt; are the Netty thread pool sizes and can be easily fine-tuned for optimal performance.&lt;br&gt;
After the server is up and running, any Redis client can connect to it as if it were a regular Redis server.&lt;/p&gt;

&lt;p&gt;For the test purposes you can use redis-cli or even the nc (or netcat) utility:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"GET key1&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | nc localhost 6379
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benchmarking
&lt;/h2&gt;

&lt;p&gt;From the very beginning, the project was built with an attention to performance, and the results speak for themselves.&lt;/p&gt;

&lt;p&gt;Running this Redis benchmark:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-benchmark &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; 100000 &lt;span class="nt"&gt;-n&lt;/span&gt; 1000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We had the following results on local Skyhook with a single-node default configuration Aerospike cluster on Docker:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Summary:&lt;/em&gt;&lt;br&gt;
 &lt;em&gt;throughput summary: 13453.88 requests per second&lt;/em&gt;&lt;br&gt;
 &lt;em&gt;latency summary (msec):&lt;/em&gt;&lt;br&gt;
   &lt;em&gt;avg       min       p50       p95       p99    max&lt;/em&gt;&lt;br&gt;
   &lt;em&gt;3.627     0.864     3.263     5.583     7.463  1012.223&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While those were the results for the Redis node running on Docker:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Summary:&lt;/em&gt;&lt;br&gt;
 &lt;em&gt;throughput summary: 14967.15 requests per second&lt;/em&gt;&lt;br&gt;
 &lt;em&gt;latency summary (msec):&lt;/em&gt;&lt;br&gt;
   &lt;em&gt;avg       min       p50       p95       p99    max&lt;/em&gt;&lt;br&gt;
   &lt;em&gt;3.275     0.608     2.935     5.087     6.679  1006.591&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can see that they are really close. More than that, we can multiply the number of the Skyhook nodes and significantly improve performance working with the same aerospike cluster. For instance, you can use the Round-robin DNS or any popular load balancer like HAProxy. This will not require any specific configuration since Skyhook is completely stateless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The project is constantly evolving, having more and more commands being supported. You can find the coverage of the supported Redis commands in the &lt;a href="https://github.com/aerospike/skyhook"&gt;repo readme&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It will be really great to hear from you about the experience of using it. Also, your contributions to the project are very welcome.&lt;/p&gt;

&lt;p&gt;If you encounter a bug, please report it or &lt;a href="https://github.com/aerospike/skyhook/issues"&gt;open an issue&lt;/a&gt; stating the commands you would like to be supported.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>redis</category>
      <category>gateway</category>
      <category>nosql</category>
    </item>
    <item>
      <title>Deploy Aerospike and Trino based analytics platform using Docker</title>
      <dc:creator>Eugene R.</dc:creator>
      <pubDate>Mon, 19 Apr 2021 18:15:35 +0000</pubDate>
      <link>https://dev.to/aerospike/deploy-aerospike-and-trino-based-analytics-platform-using-docker-2akd</link>
      <guid>https://dev.to/aerospike/deploy-aerospike-and-trino-based-analytics-platform-using-docker-2akd</guid>
      <description>&lt;p&gt;&lt;a href="https://www.aerospike.com/blog/accelerate-time-to-insight-presto/"&gt;Aerospike Connect for Presto&lt;/a&gt; was released earlier this year to address the need to convert data stored in Aerospike into valuable insights quickly using the Trino (formerly known as PrestoSQL) distribution of Presto. Based on the feedback that we received from our users, we are pleased to announce that you can now deploy the Presto connector along with Trino quickly using Docker.&lt;/p&gt;

&lt;p&gt;Here are the salient features of our Docker based solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Supports multiple deployment modes depending on your use case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standalone - both coordinator and worker are launched within the same container, which when coupled with Aerospike launched within a separate container can help you with rapid prototyping. Consider trying it out with the Aerospike single-node Enterprise edition to test the waters.&lt;/li&gt;
&lt;li&gt;Distributed - coordinator and several workers are launched within separate containers across a Trino cluster to offer the scale needed for production workloads.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provides the flexibility to your CI pipeline for building a single image that consists of the connector and the Trino version of your choice so that you can launch the combined image later using the simple docker run command.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allows you to easily configure the connector container using either &lt;a href="https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file"&gt;environment variables&lt;/a&gt; or using &lt;a href="https://docs.docker.com/storage/bind-mounts/"&gt;bind-mounts&lt;/a&gt; to mount your connector configuration files, schema JSON files along with the Trino configuration files.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Build Presto and Connector images
&lt;/h2&gt;

&lt;p&gt;Aerospike does not provide pre-built Trino images, hence you need to build a Trino and the connector image by choosing the versions of your choice, so that you can run it using a docker command. The Trino version is available on the Trino release page and the connector versions can be found on the Connector release page. Here are the steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;git clone &lt;a href="https://github.com/aerospike/trino-aerospike.docker"&gt;https://github.com/aerospike/trino-aerospike.docker&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Change directory to  trino-aerospike.docker&lt;/li&gt;
&lt;li&gt;docker build . -t trino-aerospike&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The above command will build TRINO version 351 and the latest connector version. If you plan to use a different version of Trino and/or the connector, you can pass the TRINO_VERSION and the CONNECTOR_VERSION as build arguments with the docker build command. For example, use the below command to build TRINO version 353:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;--build-arg&lt;/span&gt; &lt;span class="nv"&gt;TRINO_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;353 &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; trino-aerospike-353
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure and run the image
&lt;/h2&gt;

&lt;p&gt;There are a couple options available to deploy the connector by modifying the docker run command.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: Launch Trino along with the connector in standalone mode
&lt;/h3&gt;

&lt;p&gt;Standalone mode i.e. Trino coordinator and worker run on a single node mode, is suitable for testing purposes.  For example, if your Aerospike server is running on port 3000, you can use the following command to run the connector container on a Mac. See the configuration section for more information on how to configure the connector container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;AS_HOSTLIST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;docker.for.mac.host.internal:3000 &lt;span class="nt"&gt;--name&lt;/span&gt; trino-aerospike trino-aerospike-353
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on our testing, you can launch a Trino cluster with the connector in the standalone mode with defaults in under 5 minutes. &lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: Launch along with the connector in distributed mode
&lt;/h3&gt;

&lt;p&gt;Distributed mode i.e. a single coordinator and multiple workers, is usually preferred for production deployments. See the configuration section for more information on how to configure the connector container.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start a Trino coordinator.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;TRINO_NODE_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;coordinator &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;AS_HOSTLIST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;docker.for.mac.host.internal:3000 &lt;span class="nt"&gt;--name&lt;/span&gt; trino-aerospike-coordinator trino-aerospike-353
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Start a Trino worker, specify the TRINO_DISCOVERY_URI to be the URI of the Trino coordinator. For example,
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;TRINO_NODE_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;worker &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;AS_HOSTLIST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;docker.for.mac.host.internal:3000 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;TRINO_DISCOVERY_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://example.net:8080 &lt;span class="nt"&gt;--name&lt;/span&gt; trino-aerospike-worker1 trino-aerospike-353
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace example.net:8080 to match the host and port of the Trino coordinator. This URI must not end in a slash. Note that the above command will only run a single docker container instance of the worker. If you would like to spin up multiple worker instances, create a bash script and include the below command as many times as the number of workers desired, for automation. However, you would have to change the name of the worker instance e.g. trino-aerospike-worker-2, and so on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;TRINO_NODE_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;worker &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;AS_HOSTLIST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;docker.for.mac.host.internal:3000 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;TRINO_DISCOVERY_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://example.net:8080 &lt;span class="nt"&gt;--name&lt;/span&gt; trino-aerospike-worker2 trino-aerospike-353
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can configure the Trino connector using either environment variables or mounting configuration files to the container.  For more information on how to configure the Trino connector and launch the Trino and connector containers, visit our &lt;a href="https://aerospike.com/docs/connect/access/presto/presto-connector-docker.html"&gt;documentation&lt;/a&gt; website.&lt;/p&gt;




&lt;p&gt;Once you have successfully launched the Presto and the aerospike connector containers, you can generate insights from 100’s of TB of data stored in Aerospike using the &lt;a href="https://trino.io/docs/current/installation/cli.html"&gt;Trino CLI&lt;/a&gt;, &lt;a href="https://medium.com/aerospike-developer-blog/bi-dashboarding-with-presto-aerospike-and-tableau-a9869854aa08"&gt;create insightful dashboards using Tableau&lt;/a&gt;, or manipulate data using Presto and Python libraries via the &lt;a href="https://aerospike.com/docs/connect/access/presto/jupyter-notebook.html"&gt;PyHive Python interface&lt;/a&gt;. If you would like to quickly try  out our Docker based solution with a single node Aerospike Enterprise Edition, please follow the instructions &lt;a href="https://www.aerospike.com/lp/try-now/"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>trino</category>
      <category>presto</category>
      <category>docker</category>
    </item>
    <item>
      <title>Aerospike as a Backend Storage for HashiCorp Vault</title>
      <dc:creator>Eugene R.</dc:creator>
      <pubDate>Mon, 05 Apr 2021 17:48:50 +0000</pubDate>
      <link>https://dev.to/aerospike/aerospike-as-a-backend-storage-for-hashicorp-vault-3inf</link>
      <guid>https://dev.to/aerospike/aerospike-as-a-backend-storage-for-hashicorp-vault-3inf</guid>
      <description>&lt;p&gt;&lt;a href="https://www.vaultproject.io/"&gt;Vault&lt;/a&gt; 1.7.0 is released, and it includes my contribution to support the &lt;a href="https://www.aerospike.com/"&gt;Aerospike&lt;/a&gt; database as backend storage. See the &lt;a href="https://www.vaultproject.io/docs/release-notes/1.7.0"&gt;release notes&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;From now on, Aerospike users can store their sensitive data using Vault almost seamlessly.&lt;/p&gt;

&lt;p&gt;I will not talk about the benefits of using Vault and will jump into the installation and configuration details right away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;First thing you’ll need is to &lt;a href="https://learn.hashicorp.com/tutorials/vault/getting-started-install#install-vault"&gt;install Vault&lt;/a&gt; if you haven’t done this yet.&lt;br&gt;
Make sure that the Vault binary is available on the PATH. See &lt;a href="https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux"&gt;this page&lt;/a&gt; for instructions on setting the PATH on Linux and Mac. &lt;a href="https://stackoverflow.com/questions/1618280/where-can-i-set-path-to-make-exe-on-windows"&gt;This page&lt;/a&gt; contains instructions for setting the PATH on Windows.&lt;/p&gt;

&lt;p&gt;Verify the installation worked by opening a new terminal session and checking that the vault binary is available.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;vault version
Vault v1.7.0 &lt;span class="o"&gt;(&lt;/span&gt;4e222b85c40a810b74400ee3c54449479e32bb9f&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Outside of development mode, Vault servers are configured using a file. The format of this file is &lt;a href="https://github.com/hashicorp/hcl"&gt;HCL&lt;/a&gt;. Let’s configure our Aerospike cluster to be the Vault’s backend storage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="s2"&gt;"aerospike"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;hostname&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"localhost"&lt;/span&gt;
  &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"3300"&lt;/span&gt;
  &lt;span class="nx"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"test"&lt;/span&gt;
  &lt;span class="nx"&gt;set&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vault"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;listener&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;address&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"127.0.0.1:8200"&lt;/span&gt;
  &lt;span class="nx"&gt;tls_disable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find more information about the Aerospike backend configuration &lt;a href="https://www.vaultproject.io/docs/configuration/storage/aerospike"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To start the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault server &lt;span class="nt"&gt;-config&lt;/span&gt; aerospike_backend.hcl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Vault server is up and running on the default 8200 port.&lt;/p&gt;

&lt;p&gt;Now open a new terminal window and go through the &lt;a href="https://learn.hashicorp.com/tutorials/vault/getting-started-deploy#initializing-the-vault"&gt;guide&lt;/a&gt; to initialize the Vault server.&lt;br&gt;
It is a little bit cumbersome with all those unseals and login, but you’ll figure it out.&lt;/p&gt;

&lt;p&gt;After the successful login, we need to enable a version 1 kv store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vault secrets &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;-version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 kv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Now is the time to try things out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;vault kv put kv/my-secret my-value&lt;span class="o"&gt;=&lt;/span&gt;s3cr3t
Success! Data written to: kv/my-secret

&lt;span class="nv"&gt;$ &lt;/span&gt;vault kv get kv/my-secret
&lt;span class="o"&gt;======&lt;/span&gt; Data &lt;span class="o"&gt;======&lt;/span&gt;
Key         Value
&lt;span class="nt"&gt;---&lt;/span&gt;         &lt;span class="nt"&gt;-----&lt;/span&gt;
my-value    s3cr3t
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your first secret was successfully stored and retrieved from Aerospike using Vault!&lt;/p&gt;




&lt;p&gt;In this short introduction blog post, we covered the setup of Vault using Aerospike as a storage backend.&lt;/p&gt;

&lt;p&gt;The Aerospike backend supports both CE and EE and doesn’t expose all the configuration properties available. We will work to include those in future releases.&lt;/p&gt;

&lt;p&gt;I hope you are excited about this new Vault capability. Please &lt;a href="https://discuss.aerospike.com/"&gt;let us know&lt;/a&gt; if you encounter any issues using it.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>vault</category>
      <category>nosql</category>
    </item>
    <item>
      <title>Introducing Aerospike JDBC Driver</title>
      <dc:creator>Eugene R.</dc:creator>
      <pubDate>Mon, 15 Mar 2021 14:24:49 +0000</pubDate>
      <link>https://dev.to/aerospike/introducing-aerospike-jdbc-driver-4l14</link>
      <guid>https://dev.to/aerospike/introducing-aerospike-jdbc-driver-4l14</guid>
      <description>&lt;p&gt;One of the most common ways to interact with databases on JVM is the &lt;a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/"&gt;JDBC API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;JDBC stands for Java Database Connectivity, which is a standard Java API for database-independent connectivity between the Java programming language and a wide range of databases.&lt;/p&gt;

&lt;p&gt;Aerospike is a fast and durable No-SQL database. It has its own Java client, but this article will introduce you to a supplementary way of interacting with it using SQL.&lt;/p&gt;

&lt;p&gt;Get yourself a hot cup of tea or coffee (for the true Java look and feel) and we will dive into the details of the Aerospike journey into the JDBC world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The Aerospike JDBC driver requires Java 8 and is compliant with JDBC 4.2. Also, Aerospike server 5.2+ is required, because the driver uses the new &lt;a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/"&gt;Filter expressions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first release of the JDBC driver supports the following SQL statements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SELECT&lt;/li&gt;
&lt;li&gt;INSERT&lt;/li&gt;
&lt;li&gt;UPDATE&lt;/li&gt;
&lt;li&gt;DELETE&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also add WHERE conditions and LIMIT your queries. JOINS, ORDER BY and GROUP BY are not supported.&lt;br&gt;
From the very beginning, the driver was designed to support operations that could be done using the regular Java client, without UDFs and other compute and memory hungry components. So, the original intention is to keep it small and easy to start, without workarounds to support features that aren’t native to the Aerospike Database.&lt;/p&gt;

&lt;p&gt;The driver doesn’t support SQL functions as well as the Aerospike &lt;a href="https://www.aerospike.com/docs/guide/cdt.html"&gt;collection data types (CDTs)&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Install the Aerospike JDBC driver and add the location of it to your classpath.&lt;br&gt;
You can take the JAR file from the &lt;a href="https://github.com/aerospike/aerospike-jdbc/releases"&gt;releases&lt;/a&gt;, add a &lt;a href="https://mvnrepository.com/artifact/com.aerospike/aerospike-jdbc"&gt;Maven dependency&lt;/a&gt;, or build it from the &lt;a href="https://github.com/aerospike/aerospike-jdbc#build"&gt;sources&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Aerospike JDBC driver is statically registered in the AerospikeDriver class. So the only thing required is to load this class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Class.forName("com.aerospike.jdbc.AerospikeDriver").newInstance();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next thing you’ll need to do is to specify the JDBC URL. The URL template is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jdbc:aerospike:HOST[:PORT][/NAMESPACE][?PARAM1=VALUE1[&amp;amp;PARAM2=VALUE2]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example the &lt;code&gt;jdbc:aerospike:localhost&lt;/code&gt; URL will connect to the Aerospike database running on a local machine and listening on the default port (3000). The &lt;code&gt;jdbc:aerospike:172.17.0.5:3300/test&lt;/code&gt; URL connects to the test namespace on the Aerospike database running on 172.17.0.5:3300.&lt;/p&gt;

&lt;p&gt;After the initial setup let’s see a simple usage example of it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"jdbc:aerospike:localhost:3000/test"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Connection&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DriverManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getConnection&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"select * from ns1 limit 10"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;ResultSet&lt;/span&gt; &lt;span class="n"&gt;resultSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createStatement&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;executeQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;bin1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resultSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bin1"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bin1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  JDBC Client tools
&lt;/h2&gt;

&lt;p&gt;You can browse and manipulate data in Aerospike with any of the available SQL client tools using the JDBC driver.&lt;/p&gt;

&lt;p&gt;There are a number of multiplatform and free database tools available like &lt;a href="https://dbeaver.io/"&gt;DBeaver&lt;/a&gt;, &lt;a href="http://squirrel-sql.sourceforge.net/"&gt;SQuirreL&lt;/a&gt;, and others.&lt;/p&gt;

&lt;p&gt;Here are the steps to configure the DBeaver SQL Browser with the Aerospike JDBC driver:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database -&amp;gt; Driver Manager -&amp;gt; New
Fill in settings:

&lt;ul&gt;
&lt;li&gt;Driver Name: Aerospike&lt;/li&gt;
&lt;li&gt;Driver Type: Generic&lt;/li&gt;
&lt;li&gt;Class Name: &lt;code&gt;com.aerospike.jdbc.AerospikeDriver&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;URL Template: &lt;code&gt;jdbc:aerospike:{host}[:{port}]/[{database}]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Default Port: 3000&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Click the &lt;code&gt;Add File&lt;/code&gt; button and add the JDBC jar file.&lt;/li&gt;
&lt;li&gt;Click the &lt;code&gt;Find Class&lt;/code&gt; button.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;OK&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a connection:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database -&amp;gt; New Database Connection&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;Aerospike&lt;/code&gt; and click &lt;code&gt;Next&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Fill in the connection settings

&lt;ul&gt;
&lt;li&gt;Host and Port&lt;/li&gt;
&lt;li&gt;Database/Schema: the namespace you are connecting to&lt;/li&gt;
&lt;li&gt;Username and Password if you have security turned on in Aerospike Database Enterprise Edition&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Finish&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you can open an SQL editor and query your Aerospike cluster:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqyf6cn99ardx9ve4513.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqyf6cn99ardx9ve4513.png" alt="Alt Text" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The Aerospike JDBC driver is in its very early stages. It will be great if you could try it and give us some feedback. Any contributions to the &lt;a href="https://github.com/aerospike/aerospike-jdbc"&gt;project&lt;/a&gt; are very welcome.&lt;/p&gt;

&lt;p&gt;Check out my previous Aerospike SQL series if you haven’t done this yet.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.aerospike.com/blog/introducing-aerospike-connect-for-presto/"&gt;Introducing Aerospike Connect for Presto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/aerospike-developer-blog/aerospike-data-browser-c70c05b34a5f"&gt;Aerospike Data Browser&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And don’t forget to subscribe to the Aerospike developer blog to get updated with our latest news.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>nosql</category>
      <category>jdbc</category>
      <category>java</category>
    </item>
    <item>
      <title>Aerospike Data Browser</title>
      <dc:creator>Eugene R.</dc:creator>
      <pubDate>Mon, 01 Feb 2021 16:19:32 +0000</pubDate>
      <link>https://dev.to/aerospike/aerospike-data-browser-p86</link>
      <guid>https://dev.to/aerospike/aerospike-data-browser-p86</guid>
      <description>&lt;p&gt;Aerospike is an extremely fast and reliable data store that supports millions of transactions with incredibly low read and write latency. SQL is the lingua franca for data analysis. The key challenge here is that Aerospike is a NoSQL database, hence you cannot use standard SQL tools to analyze data stored in it. Aerospike offers &lt;a href="https://www.aerospike.com/docs/tools/aql/" rel="noopener noreferrer"&gt;AQL&lt;/a&gt; for lightweight administrative tasks for database maintenance. However, our developer community has been asking for a tool that would enable them to quickly browse or discover data stored in the Aerospike clusters visually along with the ability to run ANSI SQL queries. This has provided the impetus for our effort to create a data browser.&lt;/p&gt;

&lt;p&gt;There are a few open-source data browsers such as &lt;a href="https://github.com/rashidmayes/Clairvoyance" rel="noopener noreferrer"&gt;Clairvoyance&lt;/a&gt; that can help you view data stored in Aerospike however, but none of them are feature-complete or actively maintained.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Aerospike Data Browser
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://trino.io/" rel="noopener noreferrer"&gt;Presto&lt;/a&gt; is a highly parallel and distributed SQL query engine. We recently announced the GA of the &lt;a href="https://aerospike.com/docs/connect/access/presto/index.html" rel="noopener noreferrer"&gt;Aerospike Connect for Presto&lt;/a&gt;, which can be used to run ANSI SQL queries to perform in-place, on-demand analytics on massive amounts of data in the Aerospike database via Presto.&lt;/p&gt;

&lt;p&gt;So, it was a logical next step for us to leverage Presto and the Presto connector for our data browser design.&lt;/p&gt;

&lt;p&gt;Aerospike Data Browser is basically a stack that consists of &lt;a href="https://github.com/wix/quix" rel="noopener noreferrer"&gt;Quix&lt;/a&gt;, &lt;a href="https://trino.io/" rel="noopener noreferrer"&gt;Presto&lt;/a&gt;, and the &lt;a href="https://www.aerospike.com/docs/connect/access/presto/index.html" rel="noopener noreferrer"&gt;Aerospike Connector for Presto&lt;/a&gt;, and is dockerized. Figure 1 depicts an under the hood view. The Quix UI provides a DB Explorer and a SQL editor, in addition to a notebook manager for managing your notebooks. Presto exposes a JDBC interface to Quix and uses the Aerospike Connector to translate SQL queries into API calls to the DB. Building a stack with the aforementioned components for a desktop installation is not trivial by any means. Presto can scale to 100’s of nodes for a large scale deployment, but we wanted to limit the data browser to a single Presto instance that would run both the coordinator and worker in the developer's desktop environment. Our initial size of the Presto docker image was over 2GB, which was not acceptable. Hence, we stripped out all but the Aerospike connector from the plugin directory. Similarly, we had to downsize the Quix connector. Finally, we got the compressed docker image size under 1GB. We also made a design decision to default to schema inference so that a user that does not know the schema apriori is not left out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4fxpnmr9emryy32jea5a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4fxpnmr9emryy32jea5a.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1 - Under the hood view&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should you care?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The data browser enables you to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View namespace/set/schema of data stored in Aerospike, without the need to know the schema apriori, across multiple Aerospike clusters.&lt;/li&gt;
&lt;li&gt;Run ANSI SQL queries for data exploration, including &lt;a href="https://trino.io/docs/current/functions/aggregate.html" rel="noopener noreferrer"&gt;aggregate functions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Visualize data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It can be installed very easily using docker. See the &lt;a href="https://github.com/aerospike/aerospike-data-browser" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt; for details on installation, configuration, and usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  See it in action
&lt;/h2&gt;

&lt;p&gt;The DB explorer component of the UI allows you to browse the database and list catalogs, namespaces, and sets that are available as shown in Figure 2. Note that a catalog corresponds to an Aerospike cluster name, schema to a namespace, and table to an Aerospike set name. See &lt;a href="https://trino.io/docs/current/sql.html#sql--page-root" rel="noopener noreferrer"&gt;SQL syntax page&lt;/a&gt; for examples and more information.&lt;/p&gt;

&lt;p&gt;Also, there is an option to save your queries to a notebook for future use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuslwmpw3eycsh5u9sndp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuslwmpw3eycsh5u9sndp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2 - DB Explorer&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supported SQL statements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SHOW CATALOGS&lt;/li&gt;
&lt;li&gt;SHOW SCHEMAS&lt;/li&gt;
&lt;li&gt;USE&lt;/li&gt;
&lt;li&gt;SHOW TABLES&lt;/li&gt;
&lt;li&gt;DESCRIBE&lt;/li&gt;
&lt;li&gt;SELECT&lt;/li&gt;
&lt;li&gt;INSERT INTO&lt;/li&gt;
&lt;li&gt;EXPLAIN&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Figure 3 depicts the result of a query that was written in the query editor built into the UI. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;aerospike&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;covid_stats&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1p9jyu70dgitqt3krqdm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1p9jyu70dgitqt3krqdm.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3 - Query Editor&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can also visualize the data using the charting capabilities built into the UI as depicted in Figure 4.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkptirllad46jb1aggsg6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkptirllad46jb1aggsg6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4 - Visualizer&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Finally, you can use &lt;a href="https://trino.io/docs/current/functions/aggregate.html" rel="noopener noreferrer"&gt;aggregate functions&lt;/a&gt; as depicted in Figure 5.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzypu5weitzfgaqihcyhm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzypu5weitzfgaqihcyhm.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 5 - Using aggregate functions&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;If you find your data in the Aerospike database staring at you waiting to be quickly discovered, look no further. Use the Aerospike Data Browser to browse through the namespaces and sets to understand the schema of the data. Further, you can run supported ANSI SQL queries against it to generate quick insights. And finally, create some cool visualization. So, try it out by downloading the &lt;a href="https://www.aerospike.com/lp/aerospike-community-edition/" rel="noopener noreferrer"&gt;Aerospike Community edition&lt;/a&gt; if you don’t have an existing Aerospike deployment, and follow the instructions in the data browser repo.&lt;/p&gt;

&lt;p&gt;Keep in mind that the data browser is not an analytics tool and should not be used for complex analysis of large datasets. You should consider using the &lt;a href="https://www.aerospike.com/blog/accelerate-time-to-insight-presto/" rel="noopener noreferrer"&gt;Aerospike Connect for Presto&lt;/a&gt; for analytics use cases.&lt;/p&gt;

&lt;p&gt;Spoiler alert! We are working on the Aerospike JDBC driver, which is lightweight, more aligned with the Aerospike server functionality, and easily droppable in any JDBC data browser application. Stay tuned!&lt;/p&gt;

&lt;p&gt;Subscribe to the &lt;a href="https://medium.com/aerospike-developer-blog" rel="noopener noreferrer"&gt;Aerospike Developer Blog&lt;/a&gt; for interesting blogs and other info.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>nosql</category>
      <category>data</category>
      <category>visualization</category>
    </item>
    <item>
      <title>Authentication and Authorization using Aerospike REST Client</title>
      <dc:creator>Eugene R.</dc:creator>
      <pubDate>Thu, 30 Jul 2020 11:19:04 +0000</pubDate>
      <link>https://dev.to/aerospike/authentication-and-authorization-using-aerospike-rest-client-10p9</link>
      <guid>https://dev.to/aerospike/authentication-and-authorization-using-aerospike-rest-client-10p9</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvv3uf0gkzzadneg2c351.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvv3uf0gkzzadneg2c351.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article we will explain and give some examples of the authentication and authorization flows with the &lt;a href="https://github.com/aerospike/aerospike-client-rest" rel="noopener noreferrer"&gt;Aerospike REST client&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you’re new to the Aerospike REST client please read the &lt;a href="https://medium.com/aerospike-developer-blog/aerospike-rest-client-cb7e5967f423" rel="noopener noreferrer"&gt;introduction blog post&lt;/a&gt; by Robert Marks.&lt;/p&gt;

&lt;p&gt;Starting from version 1.0.0, the Aerospike REST Client has support for a user and password configuration used to login to the Aerospike cluster. Database administrators need to create these credentials first with the required permissions.&lt;/p&gt;

&lt;p&gt;It’s important to mention that the Access Control feature is available only in Aerospike &lt;a href="https://www.aerospike.com/products/product-matrix/" rel="noopener noreferrer"&gt;Enterprise Edition&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This setup works perfectly, but what if we want to support multiple users to enable multi-tenancy?&lt;/p&gt;

&lt;p&gt;In this case, customers might establish multiple Aerospike REST client clusters, authenticated with different credentials, and route the traffic accordingly. But this setup will require tedious installation operations and will tend to waste resources most of the time.&lt;/p&gt;

&lt;p&gt;Starting withAerospike REST client v1.6.0, multi-user authentication is supported. So how does it work? As we already know, the REST client uses the Java client under the hood. Using the single authentication configuration, the REST client shares a singleton authenticated Java client for all requests.&lt;/p&gt;

&lt;p&gt;The multi-user feature introduces an LRU based Java client cache. To start using it, customers will need to send Aerospike login credentials using &lt;a href="https://en.wikipedia.org/wiki/Basic_access_authentication" rel="noopener noreferrer"&gt;Basic access authentication&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For example, using the default &lt;code&gt;admin:admin&lt;/code&gt; credentials, send the &lt;code&gt;Authorization: Basic YWRtaW46YWRtaW4=&lt;/code&gt; header with your requests to make authenticated queries.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The REST client will seek for a properly authenticated Java client in the LRU cache and if such does not exist, it will create a new one using the given username and password.&lt;br&gt;
If the cache capacity is exceeded, the least recently used client will be dropped.&lt;/p&gt;

&lt;p&gt;To use the new feature, set the following configuration variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;aerospike.restclient.requireAuthentication&lt;/strong&gt; - Set this boolean flag to true to require Basic Authentication on each request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;aerospike.restclient.pool.size&lt;/strong&gt; - Represents the max size of the authenticated clients LRU cache (default value: 16). Please note that an oversized client cache will consume a lot of resources and affect performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refer to the &lt;a href="https://github.com/aerospike/aerospike-client-rest/blob/master/docs/installation-and-config.md" rel="noopener noreferrer"&gt;Installation and Configuration&lt;/a&gt; REST client page for installation, configuration and running manual.&lt;/p&gt;

&lt;p&gt;All this is good but we should talk about different approaches to setting up a multi-user environment, right? Let’s move to the next one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Kubernetes
&lt;/h2&gt;

&lt;p&gt;To deploy the Aerospike REST client in &lt;a href="https://kubernetes.io/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt; please use the official &lt;a href="https://github.com/aerospike/aerospike-client-rest-kubernetes" rel="noopener noreferrer"&gt;Helm chart&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The installation and configuration details are available in the readme file, but still, here are the first steps we need to get started.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Aerospike repository
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;helm repo add aerospike https://aerospike.github.io/aerospike-kubernetes-enterprise&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install the chart
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;helm install rest-client aerospike/aerospike-rest-client --set config.hostname=&amp;lt;aerospike_hostname&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can configure &lt;a href="https://kubernetes.io/docs/concepts/services-networking/ingress/" rel="noopener noreferrer"&gt;Ingress&lt;/a&gt; and route the traffic to different K8s deployments. Kubernetes will manage the resources for us. The multi-user header based authentication is available here as well though.&lt;/p&gt;




&lt;h2&gt;
  
  
  Using a proxy server authentication middleware
&lt;/h2&gt;

&lt;p&gt;This approach changes the way we handle auth flows and shifts it to a third party software layer instead of using the Aerospike cluster Access Control (hey there Community Edition folks...)&lt;/p&gt;

&lt;p&gt;To get things up and running we need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A proxy server. It can be Traefik, Envoy, Nginx or any other proxy that we like with the auth middleware support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An authentication and authorization software to handle the auth requests (like &lt;a href="https://auth0.com/" rel="noopener noreferrer"&gt;Auth0&lt;/a&gt; or any other &lt;a href="https://en.wikipedia.org/wiki/OAuth" rel="noopener noreferrer"&gt;OAuth&lt;/a&gt; provider).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Aerospike REST client itself.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The proxy will require authorization from the auth middleware and if the check passed will route the request to the REST client. See the following &lt;a href="https://github.com/aerospike-examples/aerospike-rest-client-auth" rel="noopener noreferrer"&gt;example&lt;/a&gt; implementing this architecture.&lt;/p&gt;

&lt;p&gt;I’ll paste here the architecture diagram just in case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9dcnw00076d80vf9ij42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9dcnw00076d80vf9ij42.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, you may find the &lt;a href="https://github.com/aerospike-examples/rest-client-gateway-spa-example" rel="noopener noreferrer"&gt;REST client gateway example&lt;/a&gt; using an API Gateway and Auth0 to be useful.&lt;/p&gt;




&lt;p&gt;In this article we’ve listed a number of approaches on how to use the authentication and authorization with the Aerospike REST client and have seen some examples.&lt;/p&gt;

&lt;p&gt;I hope it was interesting and beneficial at the same time. If you have any questions regarding the Aerospike REST client, don’t hesitate to open an issue under the &lt;a href="https://github.com/aerospike/aerospike-client-rest" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; or contact our team on the &lt;a href="https://discuss.aerospike.com/" rel="noopener noreferrer"&gt;https://discuss.aerospike.com/&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>rest</category>
      <category>authentication</category>
      <category>authorization</category>
    </item>
    <item>
      <title>Dealing with Predicate Expression Filters in Aerospike REST Client (Part 2)</title>
      <dc:creator>Eugene R.</dc:creator>
      <pubDate>Sun, 26 Apr 2020 16:02:56 +0000</pubDate>
      <link>https://dev.to/aerospike/dealing-with-predicate-expression-filters-in-aerospike-rest-client-part-2-58m9</link>
      <guid>https://dev.to/aerospike/dealing-with-predicate-expression-filters-in-aerospike-rest-client-part-2-58m9</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VU7h25wL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1535406208535-1429839cfd13%3Fixlib%3Drb-1.2.1%26auto%3Dformat%26fit%3Dcrop%26w%3D900%26q%3D60" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VU7h25wL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1535406208535-1429839cfd13%3Fixlib%3Drb-1.2.1%26auto%3Dformat%26fit%3Dcrop%26w%3D900%26q%3D60" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the previous &lt;a href="https://dev.to/aerospike/dealing-with-predicate-expression-filters-in-aerospike-rest-client-part-1-3njl"&gt;part&lt;/a&gt; we spoke about using simple Predicate Expression Filters with the Aerospike REST Client. In this post I want to dive deeper and show how special filter operators could come in handy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LAST_UPDATE&lt;/strong&gt;&lt;br&gt;
Asserts the last update time before processing the transaction.&lt;/p&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;comparison operator &lt;/li&gt;
&lt;li&gt;time in seconds since the epoch time (1970-01-01)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;code&gt;LAST_UPDATE(&amp;gt;=, 1577880000)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Java equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recLastUpdate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1577880000000000000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;//in nano&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerGreaterEq&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;VOID_TIME&lt;/strong&gt;&lt;br&gt;
Asserts the record’s expiration time before processing the transaction.&lt;/p&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;comparison operator&lt;/li&gt;
&lt;li&gt;time in seconds since the epoch time (1970-01-01)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;code&gt;VOID_TIME(&amp;gt;=, 1577880000)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Java equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recVoidTime&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1577880000000000000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;//in nano&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerGreaterEq&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;DIGEST_MODULO&lt;/strong&gt;&lt;br&gt;
Asserts a modulo against the record’s digest. The 160 bits (20 Bytes) digest field is generated by hashing the set name and the user key using the RipeMD-160 hashing function.&lt;/p&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;modulo divisor&lt;/li&gt;
&lt;li&gt;comparison operator&lt;/li&gt;
&lt;li&gt;expected remainder value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example for digest(key) % 3 == 1:&lt;br&gt;
&lt;code&gt;DIGEST_MODULO(3, ==, 1)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Java equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recDigestModulo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerEqual&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;STRING_REGEX&lt;/strong&gt;&lt;br&gt;
Asserts that the regular expression matches the string valued bin.&lt;/p&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;string bin name&lt;/li&gt;
&lt;li&gt;regular expression&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;code&gt;STRING_REGEX(str, [0-9]*)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Java equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stringBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"str"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stringValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[0-9]*"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stringRegex&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RegexFlag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NONE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;LIST_ITERATE_OR&lt;/strong&gt;&lt;br&gt;
Creates a predicate expression to match &lt;strong&gt;any&lt;/strong&gt; item in a list value bin.&lt;/p&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;list bin name&lt;/li&gt;
&lt;li&gt;comparison operator&lt;/li&gt;
&lt;li&gt;value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
Find records where any list item v = "hello" in list bin x.&lt;br&gt;
&lt;code&gt;LIST_ITERATE_OR(x, ==, hello)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Java equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stringVar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stringValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stringEqual&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listIterateOr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;LIST_ITERATE_AND&lt;/strong&gt;&lt;br&gt;
Creates a predicate expression to match &lt;strong&gt;all&lt;/strong&gt; items in a list value bin.&lt;/p&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;list bin name&lt;/li&gt;
&lt;li&gt;comparison operator&lt;/li&gt;
&lt;li&gt;value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
Find records where all list elements v != "world" in list bin x.&lt;br&gt;
&lt;code&gt;LIST_ITERATE_AND(x, !=, world)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Java equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stringVar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stringValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stringUnequal&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listIterateAnd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;MAPKEY_ITERATE_OR&lt;/strong&gt;&lt;br&gt;
Creates a predicate expression to match &lt;strong&gt;any&lt;/strong&gt; map key.&lt;/p&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;map bin name&lt;/li&gt;
&lt;li&gt;comparison operator&lt;/li&gt;
&lt;li&gt;value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
Find records where any map key k = 7 in map bin m.&lt;br&gt;
&lt;code&gt;MAPKEY_ITERATE_OR(m, ==, 7)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Java equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerVar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"k"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerEqual&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"m"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapKeyIterateOr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"k"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;MAPVAL_ITERATE_OR&lt;/strong&gt;&lt;br&gt;
Creates a predicate expression to match &lt;strong&gt;any&lt;/strong&gt; map value.&lt;/p&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;map bin name&lt;/li&gt;
&lt;li&gt;comparison operator&lt;/li&gt;
&lt;li&gt;value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
Find records where any map value v &amp;gt; 100 in map bin m.&lt;br&gt;
&lt;code&gt;MAPVAL_ITERATE_OR(m, &amp;gt;, 100)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Java equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerVar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerGreater&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"m"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapValIterateOr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;MAPKEY_ITERATE_AND&lt;/strong&gt;&lt;br&gt;
Creates a predicate expression to match &lt;strong&gt;all&lt;/strong&gt; map keys.&lt;/p&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;map bin name&lt;/li&gt;
&lt;li&gt;comparison operator&lt;/li&gt;
&lt;li&gt;value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
Find records where all map keys k &amp;lt; 5 in map bin m.&lt;br&gt;
&lt;code&gt;MAPKEY_ITERATE_AND(m, &amp;lt;, 5)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Java equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerVar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"k"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerLess&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"m"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapKeyIterateAnd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"k"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;MAPVAL_ITERATE_AND&lt;/strong&gt;&lt;br&gt;
Creates a predicate expression to match &lt;strong&gt;all&lt;/strong&gt; map values.&lt;/p&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;map bin name&lt;/li&gt;
&lt;li&gt;comparison operator&lt;/li&gt;
&lt;li&gt;value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
Find records where all map values v &amp;gt; 500 in map bin m.&lt;br&gt;
&lt;code&gt;MAPVAL_ITERATE_AND(m, &amp;gt;, 500)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Java equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerVar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;integerGreater&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"m"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;PredExp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapValIterateAnd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the end you can glue those with logical operators (and | or) mixing with simple filters, Base64-encode the whole expression and send it as a GET parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;KVS_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8080/v1/kvs&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;# In this example I put all metadata checks first, because Aerospike doesn't have an
# optimizer that knows how to shuffle predicates around more efficiently. This way, if the
# data is on an SSD, we can save on reading the record.
&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(c &amp;gt;= 11 and not c &amp;lt; 20) or LAST_UPDATE(&amp;gt;=, 1577880000) or DIGEST_MODULO(3, ==, 1)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;encoded_exp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;predexp_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{base}/{ns}/{setname}/{userkey}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;KVS_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;setname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userkey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;userkey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;predexp_uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;predexp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;encoded_exp&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To summarize, we’ve seen that Predicate Expression Filters are a very powerful tool and learned how to use them with the Aerospike REST Client.&lt;/p&gt;

&lt;p&gt;If you still haven’t tried Aerospike REST Client and want to do so, you can find it &lt;a href="https://github.com/aerospike/aerospike-client-rest"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>rest</category>
    </item>
    <item>
      <title>Dealing with Predicate Expression Filters in Aerospike REST Client (Part 1)</title>
      <dc:creator>Eugene R.</dc:creator>
      <pubDate>Thu, 23 Apr 2020 17:36:16 +0000</pubDate>
      <link>https://dev.to/aerospike/dealing-with-predicate-expression-filters-in-aerospike-rest-client-part-1-3njl</link>
      <guid>https://dev.to/aerospike/dealing-with-predicate-expression-filters-in-aerospike-rest-client-part-1-3njl</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--neUdu9b2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1568993703320-07e80bc8e7ab%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D2550%26q%3D80" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--neUdu9b2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1568993703320-07e80bc8e7ab%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D2550%26q%3D80" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're already an Aerospike user, you’ve likely developed with one of the client libraries available on &lt;a href="https://github.com/aerospike"&gt;GitHub&lt;/a&gt;, and might be familiar with &lt;a href="https://www.aerospike.com/docs/guide/predicate.html"&gt;Predicate Expression filters&lt;/a&gt;, which became available for all transactions starting from Aerospike Server v4.8.&lt;/p&gt;

&lt;p&gt;I want to show how you would use PredExp filters with the REST client.&lt;/p&gt;

&lt;p&gt;So what is the PredExp filter and why do we need it? Predicate expression filters are applied to scan, query and key-value results on the server. Meaning, if an expression evaluates to false, the transaction is ignored.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/aerospike/aerospike-client-rest"&gt;REST client&lt;/a&gt; uses the &lt;a href="https://github.com/aerospike/aerospike-client-java"&gt;Java client&lt;/a&gt; under the covers, where PredExp filters should be declared as an array in postfix notation. This form is hard to read and not intuitive. Having that in mind, how can we send such a construction using the REST API?&lt;/p&gt;

&lt;p&gt;To solve this issue, I created a sort of DSL in infix notation, which uses well known logical operators and supports a special filters syntax.&lt;/p&gt;

&lt;p&gt;A lot of theory till now, let's jump to some examples.&lt;/p&gt;

&lt;p&gt;Here’s an example of a Java client PredExp filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PredExp.integerBin("bin2"),
PredExp.integerValue(126),
PredExp.integerGreater(),
PredExp.integerBin("bin2"),
PredExp.integerValue(140),
PredExp.integerLessEq(),
PredExp.and(2),
PredExp.integerBin("bin2"),
PredExp.integerValue(360),
PredExp.integerEqual(),
PredExp.or(2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which actually expresses the following expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(bin2 &amp;gt; 126 and bin2 &amp;lt;= 140) or bin2 == 360
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isn't the latter more concise and intuitive?&lt;/p&gt;

&lt;p&gt;What is left, is to Base64 encode it, and send it as a GET parameter with the request.&lt;/p&gt;

&lt;p&gt;Want the bin value to be a String? Just wrap it with double quotes like this. For  non-numeric values we can omit the quotes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(bin2 == "126" and bin2 != "140") or bin2 == ten
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before I wrap up, let's talk about some PredExp use cases.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Let's say you have a counter, but you only want to increment it if the value is under a certain number (for example 100).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't alter the record if its expiration time is above or under some particular value (here you'll need to write a special filter VOID_TIME which is not covered in this post).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was a very simple example of how to use Predicate Expression Filters in the Aerospike REST Client. In my next post, I plan to write about special filter operators and their syntax.&lt;/p&gt;

&lt;p&gt;If you still haven't tinkered with the Aerospike REST client, you can find it here:&lt;br&gt;
&lt;a href="https://github.com/aerospike/aerospike-client-rest"&gt;https://github.com/aerospike/aerospike-client-rest&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take care, stay tuned and continue to Aerospike. Till next time.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>rest</category>
    </item>
  </channel>
</rss>
