<?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>Forem: Aerospike</title>
    <description>The latest articles on Forem by Aerospike (@aerospike).</description>
    <link>https://forem.com/aerospike</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%2Forganization%2Fprofile_image%2F1732%2Febe8eeb0-6228-4dd2-8423-c119ac0cade6.png</url>
      <title>Forem: Aerospike</title>
      <link>https://forem.com/aerospike</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/aerospike"/>
    <language>en</language>
    <item>
      <title>Introducing Aerospike Graph Database 3.0: Faster, simpler, and built for the terabyte scale era</title>
      <dc:creator>Aerospike</dc:creator>
      <pubDate>Tue, 29 Jul 2025 20:49:32 +0000</pubDate>
      <link>https://forem.com/aerospike/introducing-aerospike-graph-database-30-faster-simpler-and-built-for-the-terabyte-scale-era-4g2l</link>
      <guid>https://forem.com/aerospike/introducing-aerospike-graph-database-30-faster-simpler-and-built-for-the-terabyte-scale-era-4g2l</guid>
      <description>&lt;p&gt;&lt;em&gt;Discover Aerospike Graph 3.0, built for billion-scale speed, ease, and cost-efficiency in fraud, identity, and personalization graph workloads.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Author&lt;/strong&gt;: Ishaan Biswas, Director of Product Management - Graph&lt;/p&gt;




&lt;p&gt;Today, we’re announcing the release of &lt;a href="https://aerospike.com/products/graph-database/" rel="noopener noreferrer"&gt;Aerospike Graph Database 3.0&lt;/a&gt;, bringing major improvements across the three dimensions that matter most: &lt;strong&gt;developer ease&lt;/strong&gt; with multi-property and native datetime support, &lt;strong&gt;10x faster ingest performance, and up to 50% better cost efficiency&lt;/strong&gt; through reduced storage footprint. Built for teams managing the most demanding graph workloads in identity resolution, fraud prevention, and real-time personalization, Aerospike Graph Database 3.0 is our biggest step forward in making high-scale, graph data fast, accessible, and affordable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Easier to develop
&lt;/h2&gt;

&lt;p&gt;Aerospike Graph Database 3.0 introduces two key capabilities that make modeling and querying graph data more natural and powerful:&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-property support
&lt;/h3&gt;

&lt;p&gt;Vertices can now store multiple values under the same property key. This simplifies how you can model complex signal relationships, such as multiple timestamps, scores, or segments, without complex workarounds or nested structures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Store multiple tags on a user vertex&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;g.addV('User')&lt;br&gt;
.property('T.id', 'user-123')&lt;br&gt;
.property(VertexProperty.Cardinality.list, 'tag', 'frequent-buyer')&lt;br&gt;
.property(VertexProperty.Cardinality.list, 'tag', 'mobile-user')&lt;br&gt;
.property(VertexProperty.Cardinality.list, 'tag', 'high-LTV')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query all tags for the user&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;g.V().has('id', 'user-123').values('tag')&lt;br&gt;
// Output: ['frequent-buyer', 'mobile-user', 'high-LTV']&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Or query Users with a tag&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;.V().has(“tag”, “high-LTV”)&lt;br&gt;
// Output: [user-123]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is especially useful in AdTech, identity graphs, fraud, and personalization graphs, where entities accumulate multiple attributes over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Native Datetime support
&lt;/h2&gt;

&lt;p&gt;Timestamps are now supported as a first-class property type. You can store, filter, and compare temporal data directly with no need to convert or encode datetime fields manually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Add a timestamp to a session vertex&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;g.addV('Session')&lt;br&gt;
 .property('id', 'sessionid-123456')&lt;br&gt;
 .property('startedAt', datetime('2025-07-08T14:22:00Z'))&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Query sessions that started in the last 24 hours&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;g.V().hasLabel('Session')&lt;br&gt;
 .has('startedAt', gt(datetime('2025-07-07T14:22:00Z')))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;These capabilities make the platform more expressive and developer-friendly, especially for time-based and signal-rich domains.&lt;/p&gt;

&lt;h2&gt;
  
  
  Faster to load
&lt;/h2&gt;

&lt;p&gt;Aerospike Graph 3.0 ships with a re-architected bulk loader that dramatically reduces ingest time, especially at large scale.&lt;/p&gt;

&lt;p&gt;In production-scale benchmark tests, we loaded &lt;strong&gt;a terabyte of data in under three hours&lt;/strong&gt;, down from over 32 hours with version 2.6. That’s a &lt;strong&gt;&amp;gt;10x performance gain&lt;/strong&gt;, with the same infrastructure. &lt;/p&gt;

&lt;p&gt;This performance unlocks faster iteration and experimentation cycles, allowing teams to load large datasets quickly, validate changes, and refresh data frequently, without needing to scale up infrastructure or wait for a long time to see the results of their changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cheaper to run
&lt;/h2&gt;

&lt;p&gt;Aerospike Graph Database 3.0 also delivers substantial gains in storage efficiency and overall total cost of ownership.&lt;/p&gt;

&lt;p&gt;Improvements to on-disk data layout reduce storage footprint by &lt;strong&gt;up to 50%&lt;/strong&gt;, which means fewer nodes are required to store the same data. This directly reduces cluster size and infrastructure costs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Operate a &lt;strong&gt;terabyte-scale graph&lt;/strong&gt; for a fraction of the cost of any other graph database&lt;/li&gt;
&lt;li&gt;Enjoy predictable cost scaling, with $/GB dropping as data volume increases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Combined with Aerospike’s &lt;a href="https://aerospike.com/blog/hybrid-memory-architecture-optimization/" rel="noopener noreferrer"&gt;Hybrid Memory Architecture&lt;/a&gt; and the ability to scale compute and storage independently via the Aerospike Graph Service, Aerospike Graph offers the most cost-efficient ways to run high-performance graph workloads, without the constraints of RAM-bound architectures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;

&lt;p&gt;Aerospike Graph Database 3.0 is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easier to build on - with multi-property vertex support and native datetime types&lt;/li&gt;
&lt;li&gt;Faster to load - with &amp;gt;10x ingest speed for billion-scale datasets&lt;/li&gt;
&lt;li&gt;Cheaper to run -  with smaller clusters, lower storage footprint, and reduced total cost of ownership at scale &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re solving large-scale graph problems that power real-time decisions, Aerospike Graph Database 3.0 is built for you.&lt;/p&gt;

&lt;p&gt;→ [&lt;strong&gt;Read the &lt;a href="https://aerospike.com/docs/graph/release/3-0-0/" rel="noopener noreferrer"&gt;release notes&lt;/a&gt;&lt;/strong&gt;]&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>graphdb</category>
      <category>developer</category>
      <category>database</category>
    </item>
    <item>
      <title>How Criteo scaled 290M QPS and cut its server footprint by 78%</title>
      <dc:creator>Aerospike</dc:creator>
      <pubDate>Thu, 24 Jul 2025 21:36:16 +0000</pubDate>
      <link>https://forem.com/aerospike/how-criteo-scaled-290m-qps-and-cut-its-server-footprint-by-78-e80</link>
      <guid>https://forem.com/aerospike/how-criteo-scaled-290m-qps-and-cut-its-server-footprint-by-78-e80</guid>
      <description>&lt;p&gt;&lt;strong&gt;Author&lt;/strong&gt;: Steve Tuohy - Director of Product Marketing&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Discover how Criteo scaled to 290M queries-per-second, swapped Couchbase + Memcached for Aerospike, cut servers by 78%, and kept sub-ms latency.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://aerospike.com/resources/customer-stories/criteo-real-time-ad-bidding/" rel="noopener noreferrer"&gt;Criteo&lt;/a&gt; serves more than 700 million users daily with personalized ads, processing billions of events in milliseconds. At its peak, Criteo’s infrastructure handles 290 million key-value queries per second (QPS).&lt;/p&gt;

&lt;p&gt;Until recently, this real-time engine ran on a complex stack of &lt;a href="https://aerospike.com/compare/couchbase-vs-aerospike/" rel="noopener noreferrer"&gt;Couchbase&lt;/a&gt; and Memcached, propped up by custom C clients and costly operational overhead. Performance during rebalancing was fragile, cache warming required manual traffic shaping, and &lt;a href="https://aerospike.com/solutions/use-cases/improving-database-cost-through-efficiency/" rel="noopener noreferrer"&gt;RAM costs were high&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But when Criteo rebuilt its stack using Aerospike’s patented Hybrid Memory Architecture (HMA), the company consolidated two systems into one, simplified operations, and cut its server footprint by 78%, all while maintaining sub-millisecond latency at global scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maintaining real-time access at AdTech scale
&lt;/h2&gt;

&lt;p&gt;Criteo isn’t just serving banner ads. It runs real-time auctions on the open web, responding to 20 million bid requests per second. Each request requires dozens of micro-decisions: audience scoring, campaign pacing, frequency caps, and more.&lt;/p&gt;

&lt;p&gt;"Our key-value storage system peaks at about 290 million queries per second, which is fairly large,” said Maxime Brugidou, vice president of engineering, Criteo.&lt;/p&gt;

&lt;p&gt;All of that happens in under 100 ms. The stack is written in C, runs on premises across 40,000 servers and seven data centers, and operates through Kubernetes and Apache Mesos.&lt;/p&gt;

&lt;p&gt;The demands on storage? Sub-millisecond latency, no downtime during rebalancing or upgrades, and a globally distributed footprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  The legacy stack: Couchbase + Memcached + custom C logic
&lt;/h2&gt;

&lt;p&gt;Before adopting Aerospike, Criteo’s real-time infrastructure relied on Couchbase for the data, with Memcached as a caching layer. A custom-built C client orchestrated dual writes and replication between tiers, and maintained consistency between the two systems. “It was very difficult to make it perform well during rebalancing or maintenance,” Brugidou said. “It was quite unstable.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuqcbfn007t3wz95clg0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuqcbfn007t3wz95clg0a.png" alt="Criteo's tech stack in 2020" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Operationally, this design required careful tuning and careful rerouting of traffic. Any node failure or rebalance event degraded performance and had to be dealt with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdovl8ettsfvnyovs8x22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdovl8ettsfvnyovs8x22.png" alt="Drawbacks faced in legacy stack" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The turning point: Aerospike’s Hybrid Memory Architecture (HMA)&lt;/p&gt;

&lt;p&gt;Aerospike’s HMA changed the game. It decouples index storage from data storage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Indexes stay in RAM for fast access.&lt;/li&gt;
&lt;li&gt;Data lives on SSDs, such as NVMe drives, in Criteo's case.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnouwonoccguas6wjpsyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnouwonoccguas6wjpsyb.png" alt="Criteo's tech stack in 2024" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This model gave Criteo Memcached-level low latency with the durability of disk and let the company collapse its architecture from two databases into one.  "There was this nice design with the index being in memory and the data on disk,” Brugidou said. “It allowed for really good tradeoffs." &lt;/p&gt;

&lt;p&gt;By keeping indexes in memory and serving records from fast SSDs, Aerospike hit sub-millisecond reads without needing RAM to hold entire datasets. For Criteo, this not only simplified its system design but also saved money.&lt;/p&gt;

&lt;p&gt;"Aerospike combined with NVMe disks… we had basically Memcached performance except that we were using persistent storage,” Brugidou said. “That was quite impressive…Aerospike was able to keep reading steadily at high throughput and very, very low latency despite all the mess we were putting on the servers." &lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes-native deployment: From custom scripts to automated ops
&lt;/h2&gt;

&lt;p&gt;Criteo replaced both Couchbase and Memcached with Aerospike. The company removed its custom client drivers, adopted Aerospike’s native C client, and rolled out a Kubernetes-native deployment on-prem with the &lt;a href="https://aerospike.com/products/kubernetes-operator/" rel="noopener noreferrer"&gt;Aerospike Kubernetes Operator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Operational wins included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatic node recovery and rebalancing via Kubernetes&lt;/li&gt;
&lt;li&gt;Eliminating the custom C client, reducing complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Multi-bin optimization: Collapsing data models for performance
&lt;/h2&gt;

&lt;p&gt;Aerospike’s multi-bin optimization simplified things even more. Criteo merged multiple datasets into one namespace, which helped reduce index memory usage and improve access efficiency. "You can write to some bins very easily and read all the bins at once. You only pay for indexing once in memory. That was quite a significant win," Brugidou said.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5ddwits17osmgrxxrpu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5ddwits17osmgrxxrpu.png" alt="Criteo's bin strategy" width="753" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aerospike also made rebalancing and node failure recovery seamless to the team. "We do that transparently,” Brugidou said. Aerospike is able to rebalance so easily… This is fully automated and very easy to do with the Kubernetes Operator.” Multi-bin optimization also meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduced index memory usage by avoiding duplication&lt;/li&gt;
&lt;li&gt;Faster lookups, because all bins could be read in one fetch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This move simplified things even more, aligning with Criteo's infrastructure-as-code strategy and reducing human intervention during failure recovery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrastructure impact: 78% server reduction and lower carbon footprint
&lt;/h2&gt;

&lt;p&gt;By replacing Couchbase and Memcached with Aerospike, Criteo reduced server count from more than 3,000 to just 720. This meant: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lowered total RAM and disk footprint&lt;/li&gt;
&lt;li&gt;Reduced power consumption and cooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Began running on 100% renewable energy in 2022, accomplished with the purchase of certificates and relocation of data centers to more sustainable locations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvoibr4ylrpwk823lspbf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvoibr4ylrpwk823lspbf.png" alt="Criteo's data center's electricity consumption: 2016 - 2024" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;“We’re doing many more queries for less electricity in the end. Way less,” said Brugidou. This migration supports Criteo’s science-based climate target to reduce electricity consumption by 42% by 2030.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons learned: Performance tuning, not over-engineering
&lt;/h2&gt;

&lt;p&gt;Despite the performance of the new system, Criteo didn’t jump straight to exotic optimizations. Instead, it prioritized simplicity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoided pre-loading datasets in RAM&lt;/li&gt;
&lt;li&gt;Let Aerospike handle replication and rebalancing&lt;/li&gt;
&lt;li&gt;Tuned bin and namespace configs incrementally based on workload metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Brugidou emphasized that consistency and throughput remained stable even under stress tests, without resorting to low-level tuning. &lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway: Scaling real-time systems without scaling costs
&lt;/h2&gt;

&lt;p&gt;By replacing a brittle, multi-tiered stack with Aerospike’s real-time engine, Criteo gained both technical efficiency and reduced costs. It consolidated two systems into one, improved performance, reduced latency, and slashed infrastructure overhead, without sacrificing resiliency or scale.&lt;/p&gt;

&lt;p&gt;For teams building real-time systems with massive QPS and tight SLAs, Criteo’s experience shows what becomes possible with the right storage architecture.&lt;/p&gt;

&lt;p&gt;With Aerospike, Criteo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consolidated two systems into one&lt;/li&gt;
&lt;li&gt;Maintained sub-millisecond latency&lt;/li&gt;
&lt;li&gt;Reduced infrastructure costs and energy use&lt;/li&gt;
&lt;li&gt;Gained reliability through automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Want to learn more? Check out the webinar replay or talk to our team about what real-time data infrastructure can do for you.&lt;/p&gt;

</description>
      <category>adtech</category>
      <category>webdev</category>
      <category>devrel</category>
      <category>developer</category>
    </item>
    <item>
      <title>Aerospike Rust client preview: Introducing a native integration for high-performance systems</title>
      <dc:creator>Aerospike</dc:creator>
      <pubDate>Thu, 17 Jul 2025 17:18:30 +0000</pubDate>
      <link>https://forem.com/aerospike/aerospike-rust-client-preview-introducing-a-native-integration-for-high-performance-systems-20pf</link>
      <guid>https://forem.com/aerospike/aerospike-rust-client-preview-introducing-a-native-integration-for-high-performance-systems-20pf</guid>
      <description>&lt;p&gt;&lt;strong&gt;Brian Porter - Principal Product Manager, Database&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Explore Aerospike's new official Rust client, built for memory-safe, low-latency systems. See features, roadmap, and how to start integrating today.&lt;/em&gt;&lt;br&gt;
_&lt;/p&gt;




&lt;p&gt;Developers building high-throughput, low-latency applications in Rust now have access to a high-performance client developed and maintained by Aerospike with the preview release of its &lt;a href="https://github.com/aerospike/aerospike-client-rust/tree/v2" rel="noopener noreferrer"&gt;official Rust client&lt;/a&gt;. This milestone represents more than just a new client library; it marks a shift from a community-supported project to one that business leaders can feel safe adopting.&lt;/p&gt;

&lt;p&gt;Driven by increasing demand from our developer community and the rapid adoption of Rust for performance-critical, memory-safe systems, this release enables Rust developers to integrate Aerospike into their applications, all while preserving the consistency, speed, and reliability that define our platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Rust: Strategic alignment with developer needs
&lt;/h2&gt;

&lt;p&gt;Rust is increasingly used across industries such as finance, telecommunications, cloud infrastructure, and embedded systems. It has become the preferred choice for performance-critical systems development. Organizations such as Amazon, Cloudflare, and Discord have adopted Rust to build reliable infrastructure and eliminate classes of memory-related bugs that commonly affect C/C++-based software. &lt;/p&gt;

&lt;p&gt;Its popularity is driven by a combination of performance and reliability characteristics that are a natural fit for Aerospike applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No garbage collection&lt;/strong&gt;: Rust’s lack of a garbage collector helps eliminate latency outliers, a key requirement for real-time systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compile-time memory safety&lt;/strong&gt;: Rust’s memory safety model reduces crash potential by catching common security vulnerabilities at compile time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safe concurrency support&lt;/strong&gt;: Rust prevents data races by enforcing thread safety at compile time, helping high-concurrency applications scale better.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern tooling and developer experience&lt;/strong&gt;: Over 100,000 Rust crates exist today, providing straightforward integration with Kafka, gRPC, observability tools, and more, forming a mature ecosystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Rust client capabilities
&lt;/h2&gt;

&lt;p&gt;Rust Preview highlights include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Execution models&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Async-first&lt;/strong&gt;: Built for non-blocking IO, powered by &lt;a href="https://tokio.rs/" rel="noopener noreferrer"&gt;Tokio&lt;/a&gt; by default, with optional support for &lt;a href="https://async.rs/" rel="noopener noreferrer"&gt;async-std&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sync support&lt;/strong&gt;: Blocking APIs available using a sync sub-crate for flexibility in legacy or mixed environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advanced data operations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Batch protocol&lt;/strong&gt;: Full support for read, write, delete, and UDF operations through the new BatchOperation API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New query/scan support&lt;/strong&gt;: Implements updated query protocols for improved consistency and performance, allowing pagination and limiting the number of returned records&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Policy and expression enhancements&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Replica policies&lt;/strong&gt;: Includes support for Replica, including PreferRack policy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy additions&lt;/strong&gt;: New fields such as allow_inline_ssd, respond_all_keys in BatchPolicy, read_touch_ttl, and QueryDuration in QueryPolicy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limiting&lt;/strong&gt;: Supports records_per_second for scan/query throttling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data model improvements&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Type support&lt;/strong&gt;: Adds support for boolean particle type&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New data constructs&lt;/strong&gt;: Returns types such as Exists, OrderedMap, and UnorderedMap, now supported for &lt;a href="https://aerospike.com/docs/develop/data-types/collections/" rel="noopener noreferrer"&gt;CDT&lt;/a&gt; reads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value conversions&lt;/strong&gt;: Implements TryFromAerospike::Value for type interoperability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infinity and wildcard&lt;/strong&gt;: Supports Infinity, Wildcard, and corresponding expression builders expressions::infinity() and expressions::wildcard()&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Size expressions&lt;/strong&gt;: Adds expressions::record_size() and expressions::memory_size() for granular control&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take a look at the &lt;a href="https://github.com/aerospike/aerospike-client-rust/blob/v2/CHANGELOG.md" rel="noopener noreferrer"&gt;changelog&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;The client has been built from the ground up to integrate easily with today’s Rust frameworks and async runtimes. Support for the Tokio async runtime, standard Rust crates, and idiomatic usage patterns are all part of the design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Release timeline
&lt;/h2&gt;

&lt;p&gt;The client is currently available as a preview release, with support for foundational operations. The &lt;strong&gt;general availability (GA) release is planned for later in 2025&lt;/strong&gt; and will include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full feature parity with other official Aerospike clients (e.g., Go, C#, Java)&lt;/li&gt;
&lt;li&gt;Community feedback-driven improvements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The preview release is available on &lt;a href="https://github.com/aerospike/aerospike-client-rust/tree/v2" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and we encourage developers to experiment, provide feedback, and report issues.&lt;/p&gt;

&lt;p&gt;Designed for the community&lt;br&gt;
Aerospike developed this client because we listened to our developer community. Requests for async support, tighter performance tuning, and alignment with Rust’s ecosystem have been recurring themes in our forums and GitHub discussions. The new client is a direct response to that input.&lt;/p&gt;

&lt;p&gt;By releasing this client under an open license and hosting it on GitHub, we aim to foster ongoing community engagement. Contributions, feature requests, and feedback will help shape the GA version and future enhancements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;

&lt;p&gt;Start working with the &lt;a href="https://github.com/aerospike/aerospike-client-rust/tree/v2" rel="noopener noreferrer"&gt;preview client today&lt;/a&gt; by going to the Installation section of the v2 branch of the Rust client repo.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>rust</category>
      <category>database</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Pi day exercise: Calculating pi with expressions!</title>
      <dc:creator>Piyush Gupta</dc:creator>
      <pubDate>Thu, 14 Mar 2024 13:36:06 +0000</pubDate>
      <link>https://forem.com/aerospike/pi-day-exercise-calculating-pi-with-expressions-25d2</link>
      <guid>https://forem.com/aerospike/pi-day-exercise-calculating-pi-with-expressions-25d2</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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fpiyush-gupta%2Fpi-day-exercise-calculating-pi-with-expressions-1_1710377025176.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fpiyush-gupta%2Fpi-day-exercise-calculating-pi-with-expressions-1_1710377025176.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Monte Carlo method is an effective technique for calculating probabilities.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this fun blog, whose concept was "engineered" by our very own &lt;a href="https://www.linkedin.com/in/jpollack/" rel="noopener noreferrer"&gt;Joshua Pollack&lt;/a&gt;, we demonstrate how to use &lt;a href="https://aerospike.com/docs/server/guide/expressions" rel="noopener noreferrer"&gt;expressions in Aerospike&lt;/a&gt; to calculate the value of Pi using a Monte Carlo technique. &lt;/p&gt;

&lt;p&gt;While the example is fun and rather contrived, it highlights an underlying technique of using expressions in Aerospike to compute incoming data values for thresholds and apply conditional executions to real-time situations such as &lt;a href="https://aerospike.com/solutions/use-cases/fraud-prevention/" rel="noopener noreferrer"&gt;fraud detection&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is Pi?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.piday.org/learn-about-pi/" rel="noopener noreferrer"&gt;Pi&lt;/a&gt; (often represented as the Greek letter &lt;code&gt;π&lt;/code&gt;) is “one of the most well-known mathematical constants [and] is the ratio of a circle’s circumference to its diameter. For any circle, the distance around the edge is a little more than three times the distance across. Typing &lt;code&gt;π&lt;/code&gt; into a calculator and pressing ENTER will yield the result &lt;code&gt;3.141592654&lt;/code&gt;, not because this value is exact, but because a calculator’s display is often limited to 10 digits.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Calculating the value of Pi
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://aws.amazon.com/what-is/monte-carlo-simulation/" rel="noopener noreferrer"&gt;Monte Carlo method&lt;/a&gt; to compute the value of Pi uses the probability of a random point whose &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinates are between &lt;code&gt;-1.0&lt;/code&gt; and &lt;code&gt;1.0&lt;/code&gt; falling within the enclosing square of side &lt;code&gt;2.0&lt;/code&gt; versus within the circle at center &lt;code&gt;(0.0, 0.0)&lt;/code&gt; with radius &lt;code&gt;r = 1.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The probability of being in the circle versus the encompassing square is &lt;code&gt;π*r&lt;sup&gt;2&lt;/sup&gt;/(2r)&lt;sup&gt;2&lt;/sup&gt;&lt;/code&gt;. This article describes this simple technique quite nicely. &lt;/p&gt;

&lt;p&gt;The technique reduces to:&lt;br&gt;&lt;br&gt;
Estimated value of Pi = &lt;code&gt;4 * number of points inside the circle / total number of points&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can apply the ratio to just the top quadrant of the circle and rectangle. &lt;/p&gt;

&lt;p&gt;We can use the Java random number generator to produce &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinates of a point between &lt;code&gt;0.0&lt;/code&gt; and &lt;code&gt;1.0&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;We will do this computation in a single Aerospike record that we initialize as follows:&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;AerospikeClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AerospikeClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;//Initialize our single aggregation record, center of circle &lt;/span&gt;

&lt;span class="nc"&gt;Key&lt;/span&gt; &lt;span class="n"&gt;key1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"points"&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;Bin&lt;/span&gt; &lt;span class="n"&gt;xcoord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&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="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Bin&lt;/span&gt; &lt;span class="n"&gt;ycoord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"y"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Bin&lt;/span&gt; &lt;span class="n"&gt;inCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"inCount"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Bin&lt;/span&gt; &lt;span class="n"&gt;totalCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;WritePolicy&lt;/span&gt; &lt;span class="n"&gt;wPolicy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WritePolicy&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wPolicy&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xcoord&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ycoord&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inCount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;totalCount&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//Check&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&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="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;gen:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;exp:&lt;/span&gt;&lt;span class="mi"&gt;448491015&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;bins:&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;x:&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;y:&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;inCount:&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;count:&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we insert the next random values of the &lt;code&gt;(x,y)&lt;/code&gt; pair, we will use expressions to compute whether the value lies within the circle or outside and in the same write transaction, update the &lt;code&gt;inCount&lt;/code&gt; and the &lt;code&gt;total&lt;/code&gt; count. &lt;/p&gt;

&lt;p&gt;We use another expression-based call to get the estimated value of Pi (expected to be &lt;code&gt;3.14xx&lt;/code&gt;).&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="c1"&gt;//Insert a record using a class based construct&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;insertPoint&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Key&lt;/span&gt; &lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;xval&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;yval&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;bCheck&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Bin&lt;/span&gt; &lt;span class="n"&gt;xcoord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&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="n"&gt;xval&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;Bin&lt;/span&gt; &lt;span class="n"&gt;ycoord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"y"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yval&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;WritePolicy&lt;/span&gt; &lt;span class="n"&gt;wPolicy1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WritePolicy&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nc"&gt;Expression&lt;/span&gt; &lt;span class="n"&gt;inCircleExp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
       &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;le&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
          &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mul&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;floatBin&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;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;floatBin&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;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mul&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;floatBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"y"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;floatBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"y"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
          &lt;span class="o"&gt;),&lt;/span&gt;
          &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;val&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;),&lt;/span&gt;
       &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;floatBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"inCount"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;val&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="o"&gt;)),&lt;/span&gt;
       &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;floatBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"inCount"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
       &lt;span class="o"&gt;));&lt;/span&gt;

    &lt;span class="nc"&gt;Expression&lt;/span&gt; &lt;span class="n"&gt;totalCountExp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;floatBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;val&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt;

    &lt;span class="nc"&gt;Record&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;operate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;wPolicy1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;   
          &lt;span class="nc"&gt;Operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xcoord&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
          &lt;span class="nc"&gt;Operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ycoord&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;                   
          &lt;span class="nc"&gt;ExpOperation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"inCount"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inCircleExp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExpWriteFlags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DEFAULT&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
          &lt;span class="nc"&gt;ExpOperation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;totalCountExp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExpWriteFlags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DEFAULT&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                                  &lt;span class="o"&gt;);&lt;/span&gt;                 
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bCheck&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;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key1&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="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;getPi&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Key&lt;/span&gt; &lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
      &lt;span class="nc"&gt;WritePolicy&lt;/span&gt; &lt;span class="n"&gt;wPolicy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WritePolicy&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
      &lt;span class="nc"&gt;Expression&lt;/span&gt; &lt;span class="n"&gt;piExp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
          &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mul&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;val&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; 
                  &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;div&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;floatBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"inCount"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;floatBin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                 &lt;span class="o"&gt;));&lt;/span&gt;

      &lt;span class="nc"&gt;Record&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;operate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wPolicy&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExpOperation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pi"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;piExp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExpReadFlags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DEFAULT&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="s"&gt;"Pi : "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pi"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's try this code construct:&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="c1"&gt;//Check&lt;/span&gt;
&lt;span class="nc"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;insertPoint&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.71&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.71&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;//Out of circle, in rectangle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&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="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;gen:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;exp:&lt;/span&gt;&lt;span class="mi"&gt;448490510&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;bins:&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;x:&lt;/span&gt;&lt;span class="mf"&gt;0.71&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;y:&lt;/span&gt;&lt;span class="mf"&gt;0.71&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;inCount:&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;count:&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's scale it up and insert 10,000 random points. This takes an imperceptible amount of time on Aerospike.&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="c1"&gt;//Insert random points with x,y between 0.0 and 1.0&lt;/span&gt;

&lt;span class="nc"&gt;Random&lt;/span&gt; &lt;span class="n"&gt;rnd1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Random&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  

&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&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="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++){&lt;/span&gt;
  &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;xval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rnd1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nextDouble&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;yval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rnd1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nextDouble&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;insertPoint&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xval&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yval&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&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;p&gt;And now for our estimate of Pi:&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="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPi&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pi : 3.1424
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Happy Pi Day!&lt;/p&gt;

&lt;p&gt;In the above example, &lt;code&gt;getPi()&lt;/code&gt; is shown here as a separate call. However, it can be made part of the return value in the write api (&lt;code&gt;insertPoint()&lt;/code&gt;).  &lt;/p&gt;

&lt;p&gt;Instead of our pair of &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;, if you had 100s of such parameters that you would want to compute a net score to make a go/nogo decision, the above code constructs can be easily extended. In this example, we had no need to retain the 10,000 random values. However, if the data needs to be retained, consider using one of our collection data types, such as a &lt;code&gt;Map&lt;/code&gt; or a &lt;code&gt;List&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get the most out of your data with Aerospike Expressions
&lt;/h2&gt;

&lt;p&gt;To learn more, watch our &lt;a href="https://aerospike.com/resources/webinars/devchat-aerospike-expressions/" rel="noopener noreferrer"&gt;Optimizing query performance with Aerospike Expressions&lt;/a&gt; webinar with Chief Developer Advocate Tim Faulkes.&lt;/p&gt;

</description>
      <category>pi</category>
      <category>expressions</category>
      <category>aerospike</category>
    </item>
    <item>
      <title>How to retrieve the key in a key-value store</title>
      <dc:creator>Piyush Gupta</dc:creator>
      <pubDate>Wed, 13 Mar 2024 17:54:01 +0000</pubDate>
      <link>https://forem.com/aerospike/how-to-retrieve-the-key-in-a-key-value-store-1e7a</link>
      <guid>https://forem.com/aerospike/how-to-retrieve-the-key-in-a-key-value-store-1e7a</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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fpiyush-gupta%2Fhow-to-retrieve-the-key-in-a-key-value-store-1_1710289769661.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fpiyush-gupta%2Fhow-to-retrieve-the-key-in-a-key-value-store-1_1710289769661.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn how to retrieve user-specified keys in Aerospike using single record reads.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this blog, you’ll learn how to retrieve the user-specified key in Aerospike, a key-value store.&lt;br&gt;&lt;br&gt;
Aerospike is designed from the ground up to support extremely low latency create, read, update, and delete (&lt;a href="https://aerospike.com/resources/tech-videos/crud-ops/" rel="noopener noreferrer"&gt;CRUD&lt;/a&gt;) operations. In Aerospike, applications store data as individual records that are uniformly distributed across all the nodes of the database cluster. A user-specified key is associated with each record along with the application data. Below, we will walk you through the steps necessary to retrieve your user-specified key in a single record read operation.&lt;/p&gt;


&lt;h2&gt;
  
  
  Keys in Aerospike
&lt;/h2&gt;

&lt;p&gt;As mentioned above, Aerospike stores user data in individual records, which are accessible by a user-specified "key." Keys can only be a string, integer, or a byte array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[USER SPECIFIED KEY] → [USER DATA in one or more "bins"]
&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fpiyush-gupta%2FRetreivingKeyBlog_Fig_1_AerospikeKey_1710289926115.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fpiyush-gupta%2FRetreivingKeyBlog_Fig_1_AerospikeKey_1710289926115.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Applications access the data via the &lt;a href="https://aerospike.com/developer/client" rel="noopener noreferrer"&gt;Aerospike client library&lt;/a&gt;, which computes a 20-byte “digest” by hashing the user-supplied key information of set name, user key value, and user key type.&lt;/p&gt;

&lt;p&gt;The client library sends the 20-byte digest as the key of record to the server. So, the record in the server should read:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[20 Byte Digest] → [USER DATA in one or more "bins"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Storing keys in records
&lt;/h2&gt;

&lt;p&gt;What if two keys hash to the same digest value, resulting in a hash collision?&lt;/p&gt;

&lt;p&gt;Aerospike uses the RIPEMD-160 hashing algorithm, which has a statistically near-zero probability of hash collision. By default, Aerospike does not store the user-supplied key with the saved record. However, applications have the option to store the user-specified key along with the record via the &lt;a href="https://aerospike.com/docs/server/guide/policies" rel="noopener noreferrer"&gt;write policy&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[20 Byte Digest ] → [USER DATA in one or more "bins"] + [User Key (string / int / blob)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The approach above ensures that the server verifies the hash against the stored key during CRUD operations. Any subsequent updates where a hash collision is detected, the application will receive a &lt;code&gt;KEY_MISMATCH&lt;/code&gt; error. &lt;/p&gt;

&lt;h3&gt;
  
  
  Key mismatch explained
&lt;/h3&gt;

&lt;p&gt;Consider the case in a namespace &lt;code&gt;test&lt;/code&gt;, where a user-specified key of &lt;code&gt;abc&lt;/code&gt; in set &lt;code&gt;testSet1&lt;/code&gt; generates a particular digest, &lt;code&gt;digest1&lt;/code&gt;. When this record is first created, Aerospike uses &lt;code&gt;digest1&lt;/code&gt; as the internal key of that record but also stores the user-specified key of &lt;code&gt;abc&lt;/code&gt; with the record. &lt;/p&gt;

&lt;p&gt;Hypothetically, in the same namespace &lt;code&gt;test&lt;/code&gt;, consider the user-specified key of &lt;code&gt;xyz&lt;/code&gt; in set &lt;code&gt;testSet2&lt;/code&gt;, which also happens to hash to the same value, &lt;code&gt;digest1&lt;/code&gt;. (This has near zero probability, practically speaking.)&lt;/p&gt;

&lt;p&gt;If the application tries to create or update a record with &lt;code&gt;digest1&lt;/code&gt; and with user-specified key &lt;code&gt;xyz&lt;/code&gt;, Aerospike will access the record stored against &lt;code&gt;digest1&lt;/code&gt; and compare the stored key &lt;code&gt;abc&lt;/code&gt; against the incoming transaction's user-specified key of &lt;code&gt;xyz&lt;/code&gt; and discover that they are different. A &lt;code&gt;KEY_MISMATCH&lt;/code&gt; exception will be thrown in this case.&lt;/p&gt;

&lt;h3&gt;
  
  
  User key stored with the record
&lt;/h3&gt;

&lt;p&gt;The curious may want to know: Is it possible to read this user-specified stored key back in the application? &lt;/p&gt;

&lt;p&gt;For data modeling purposes and for queries (primary or secondary index queries that retrieve qualifying records from the entire namespace), the user stored key can be retrieved back to the client. This is useful since the user may want to then update individual records selectively, as part of their use case. &lt;/p&gt;

&lt;p&gt;However, for single key reads the user key is not returned to the client, as you must have had the key to be able to read the record in the first place. This type of read can be done by passing either the user key and the set name or the digest.&lt;/p&gt;

&lt;p&gt;In certain operational situations, users have asked if it is possible to read back the user stored key on an individual record read. They stored their key with the record and would now like to retrieve it. These are situations where users have the 20-byte digest of a record, but they do not know the user key. The digest was recorded in the server logs. An example of this would be when turning on &lt;a href="https://support.aerospike.com/s/article/How-To-use-rw-client-logging-to-identify-a-hot-digest" rel="noopener noreferrer"&gt;rw-client logging&lt;/a&gt; to identify the digests of "hot-keys," records that are being updated very frequently.&lt;/p&gt;

&lt;p&gt;The read APIs don't provide this functionality upfront via the policies since this is not a typical data modeling need. However, Aerospike does provide &lt;a href="https://aerospike.com/docs/server/guide/expressions" rel="noopener noreferrer"&gt;expressions&lt;/a&gt; that can access the user stored key.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are Aerospike Expressions?
&lt;/h3&gt;

&lt;p&gt;An expression is a strongly typed domain-specific language designed for manipulating and comparing bins and record metadata. There is no “programming language” per se; an expression is built with code. It runs on the nodes in the cluster, not on the client.&lt;/p&gt;

&lt;p&gt;Aerospike supports three types of expressions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Filter expressions (introduced in version 5.2.0)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aerospike.com/products/features/cross-datacenter-replication-xdr/" rel="noopener noreferrer"&gt;Cross Datacenter Replication&lt;/a&gt; filter expressions (introduced in version 5.3.0)&lt;/li&gt;
&lt;li&gt;Operation expressions (introduced in version 5.6.0)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Filter and operation expressions can be specified on a per-call basis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key retrieval code example
&lt;/h2&gt;

&lt;p&gt;Below is an example code snippet demonstrating how to retrieve a key using the Java client.&lt;/p&gt;

&lt;p&gt;Creating the record initially:&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;AerospikeClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AerospikeClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Key&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"testset"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"key1"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;WritePolicy&lt;/span&gt; &lt;span class="n"&gt;wPolicy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WritePolicy&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;wPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;//Store our user key on the server&lt;/span&gt;

&lt;span class="nc"&gt;Bin&lt;/span&gt; &lt;span class="n"&gt;b0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"b00"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wPolicy&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, assume we just have the 20-byte digest and would like to retrieve our key:&lt;/p&gt;

&lt;p&gt;We can use the following key constructor:&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="c1"&gt;// Initialize key from namespace, digest, optional set name, and optional userKey.&lt;/span&gt;
&lt;span class="nc"&gt;Key&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;namespace&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;digest&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;setName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt; &lt;span class="n"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's find the digest of the record we created above, for purposes of this demo.&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="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;recDigest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;recDigest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nc"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;computeDigest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"testset"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"key1"&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;p&gt;Next, create a new key object using the digest-based constructor.&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;Key&lt;/span&gt; &lt;span class="n"&gt;keyByDigest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recDigest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NULL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  About &lt;code&gt;Value.NULL&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The constructor allows specifying the user-specified key in the last argument as a “Value" type object. For example, &lt;code&gt;Value.get("myKey")&lt;/code&gt;. This is provided for the rare case where the application wants to do an update with the key generated using the digest, and the set name is not known but still wants to update with &lt;code&gt;sendKey=true&lt;/code&gt;.  In our case, we don't know the key and are trying to retrieve it in an &lt;code&gt;operate()&lt;/code&gt; call, which is like a write, although we will only perform a read via expressions. Hence, we pass &lt;code&gt;Value.NULL&lt;/code&gt; for the user-specified key and use &lt;code&gt;sendKey=false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We should be able to read the same record using either "key" or "keyDigest." Let's validate.&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;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="s"&gt;"Record: "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&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="s"&gt;"Record via Digest: "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyByDigest&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&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="nl"&gt;Record:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;gen:&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;exp:&lt;/span&gt;&lt;span class="mi"&gt;447740032&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;bins:&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;b00:&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="nc"&gt;Record&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="nl"&gt;Digest:&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;gen:&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;exp:&lt;/span&gt;&lt;span class="mi"&gt;447740032&lt;/span&gt;&lt;span class="o"&gt;),(&lt;/span&gt;&lt;span class="nl"&gt;bins:&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;b00:&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Case 1: key type known
&lt;/h3&gt;

&lt;p&gt;Now, using the digest-based key, let's retrieve the stored key from the server. Since we are specifying the digest and &lt;code&gt;Value.NULL&lt;/code&gt; for the userKey in our &lt;code&gt;recDigest&lt;/code&gt; constructor, we must set the&lt;code&gt;wPolicy.sendKey = false&lt;/code&gt;; to avoid a &lt;code&gt;KEY_MISMATCH&lt;/code&gt; error.&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="n"&gt;wPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;keySend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;Expression&lt;/span&gt; &lt;span class="n"&gt;recKeyExp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;STRING&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="nc"&gt;Record&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;operate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;wPolicy&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyByDigest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;   
          &lt;span class="nc"&gt;ExpOperation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"reckey"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recKeyExp&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExpReadFlags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DEFAULT&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;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="s"&gt;"Record Key: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"reckey"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recall we mentioned that user-specified keys can be of type integer, string, or byte-array. Here, although we don't know our key, we know it is a string type. This is specified using &lt;code&gt;Exp.Type.STRING&lt;/code&gt; when building the expression for the &lt;code&gt;key&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Output:&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;Record&lt;/span&gt; &lt;span class="nl"&gt;Key:&lt;/span&gt; &lt;span class="n"&gt;key1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Case 2: key type unknown
&lt;/h3&gt;

&lt;p&gt;What if we don't know the key type?  We can check for all the three allowable types. Although, in this case, we must use &lt;code&gt;ExpReadFlags.EVAL_NO_FAIL&lt;/code&gt; instead of &lt;code&gt;ExpReadFlags.DEFAULT&lt;/code&gt; so that the failed expressions with type mismatch don't generate an Exception.&lt;/p&gt;

&lt;p&gt;Example code is shown below.&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="n"&gt;wPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;Expression&lt;/span&gt; &lt;span class="n"&gt;recKeyExpStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;STRING&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="nc"&gt;Expression&lt;/span&gt; &lt;span class="n"&gt;recKeyExpInt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INT&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="nc"&gt;Expression&lt;/span&gt; &lt;span class="n"&gt;recKeyExpBlob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BLOB&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

&lt;span class="nc"&gt;Record&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;operate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;wPolicy&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyByDigest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;   
          &lt;span class="nc"&gt;ExpOperation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"reckeyStr"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recKeyExpStr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExpReadFlags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;EVAL_NO_FAIL&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
          &lt;span class="nc"&gt;ExpOperation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"reckeyInt"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recKeyExpInt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExpReadFlags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;EVAL_NO_FAIL&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
          &lt;span class="nc"&gt;ExpOperation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"reckeyBlob"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recKeyExpBlob&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExpReadFlags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;EVAL_NO_FAIL&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;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="s"&gt;"Record Key String: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"reckeyStr"&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="s"&gt;"Record Key Integer: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"reckeyInt"&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="s"&gt;"Record Key BLOB: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"reckeyBlob"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&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;Record&lt;/span&gt; &lt;span class="nc"&gt;Key&lt;/span&gt; &lt;span class="nl"&gt;String:&lt;/span&gt; &lt;span class="n"&gt;key1&lt;/span&gt;
&lt;span class="nc"&gt;Record&lt;/span&gt; &lt;span class="nc"&gt;Key&lt;/span&gt; &lt;span class="nl"&gt;Integer:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="nc"&gt;Record&lt;/span&gt; &lt;span class="nc"&gt;Key&lt;/span&gt; &lt;span class="nl"&gt;BLOB:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Unlock the power of expressions in Aerospike for enhanced data operations
&lt;/h2&gt;

&lt;p&gt;Expressions are a very powerful tool in Aerospike. They can be used as filters for selecting records to return in primary or secondary index queries, as well as compute on a record’s existing data or metadata. It can then return the result of the computation as a read or write it to a new bin. The possibilities are only limited by your creativity! &lt;/p&gt;

&lt;p&gt;To learn more, watch our &lt;a href="https://aerospike.com/resources/webinars/devchat-aerospike-expressions/" rel="noopener noreferrer"&gt;Optimizing query performance with Aerospike Expressions&lt;/a&gt; webinar with Chief Developer Advocate Tim Faulkes.&lt;/p&gt;

</description>
      <category>key</category>
      <category>value</category>
      <category>aerospike</category>
    </item>
    <item>
      <title>Using Aerospike policies (correctly!)</title>
      <dc:creator>Tim F</dc:creator>
      <pubDate>Thu, 29 Feb 2024 23:28:25 +0000</pubDate>
      <link>https://forem.com/aerospike/using-aerospike-policies-correctly-j06</link>
      <guid>https://forem.com/aerospike/using-aerospike-policies-correctly-j06</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TcIUXDEg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developer-hub.s3.us-west-1.amazonaws.com/tim-faulkes/using-aerospike-policies%2520copy_1709244867238.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TcIUXDEg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developer-hub.s3.us-west-1.amazonaws.com/tim-faulkes/using-aerospike-policies%2520copy_1709244867238.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Developers familiar with Aerospike will know that the vast majority of the API calls take a &lt;a href="https://aerospike.com/docs/server/guide/policies.html"&gt;“policy”&lt;/a&gt; as a parameter. This policy is optional but can have a significant impact on the application. There are a number of parameters in policies that can be confusing to &lt;a href="https://aerospike.com/developer/"&gt;developers&lt;/a&gt;, and even creating the policies is frequently done incorrectly. This blog will attempt to clear up some of this confusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are policies?
&lt;/h2&gt;

&lt;p&gt;Each API call in Aerospike typically takes a policy as a parameter. For example, consider a simple get in Java:&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="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"testSet"&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Bin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Tim"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;312&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first parameter here is the policy; in this case, it is an instance of the &lt;code&gt;WritePolicy&lt;/code&gt; class. If &lt;code&gt;null&lt;/code&gt; is specified, then the default policy is used. Policies typically contain fields that fall into one of three categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Networking control&lt;/strong&gt;: How should the API call behave if something goes wrong? For example, if the server cannot be reached, should the call be retried on a different server?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Application behavior&lt;/strong&gt;: Parameters that control how the API call should behave in various application-driven scenarios. For example, Aerospike does an “upsert” operation by default on a &lt;code&gt;put&lt;/code&gt;, selecting to either update or insert the record depending on whether it already exists or not. However, the application might require the record to be inserted only, failing if the record already exists in the database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Filtering&lt;/strong&gt;: Aerospike supports filters on operations, allowing almost all operations to become conditional. For example, an operation can be specified to retrieve a record if the &lt;code&gt;amount&lt;/code&gt; bin in that record is greater than a thousand.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These three categories are all in the same policy object, with the networking control defined on the &lt;code&gt;Policy&lt;/code&gt; class, which is a superclass of other policies, such as &lt;code&gt;WritePolicy&lt;/code&gt;. Note that the &lt;code&gt;Policy&lt;/code&gt; class is used for read operations without a subclass; there is no &lt;code&gt;ReadPolicy&lt;/code&gt; class.&lt;/p&gt;

&lt;h2&gt;
  
  
  Networking control policies
&lt;/h2&gt;

&lt;p&gt;The policy superclass defines a number of parameters related to networking. These are critical to optimizing application behavior but are often poorly understood. Let’s take a look at these and the interaction between them.&lt;/p&gt;

&lt;p&gt;These networking fields are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;connectTimeout&lt;/li&gt;
&lt;li&gt;maxRetries&lt;/li&gt;
&lt;li&gt;replica&lt;/li&gt;
&lt;li&gt;sleepBetweenRetries&lt;/li&gt;
&lt;li&gt;socketTimeout&lt;/li&gt;
&lt;li&gt;timeoutDelay&lt;/li&gt;
&lt;li&gt;totalTimeout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A diagram is helpful in understanding the interaction between these fields:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kLVBFb02--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developer-hub.s3.us-west-1.amazonaws.com/tim-faulkes/using-aerospike-policies-correctly-api-call-sequence_1709244867669.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kLVBFb02--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developer-hub.s3.us-west-1.amazonaws.com/tim-faulkes/using-aerospike-policies-correctly-api-call-sequence_1709244867669.png" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;
Figure 1: API call sequence



&lt;p&gt;The diagram shows a timeline of what happens when an API call is submitted to the Aerospike Client Library (ACL) and can be read from left to right. &lt;/p&gt;

&lt;p&gt;The first thing that happens is the ACL needs a connection to the server which holds the data. If this is a simple get or put, this will be a connection to a single server, but if it’s a complex operation such as a batch or query, multiple servers might be involved. The ACL has connection pools to each server node, so acquiring this connection is typically a matter of borrowing one from the pool, which is almost instantaneous. However, if the pool has no available connections, a new connection must be established, which can take some time. This is especially true if the connection is over TLS as the handshake between the client and server on a TLS connection can be slow. &lt;/p&gt;

&lt;p&gt;This connection establishment process has its own timeout field, &lt;code&gt;connectTimeout&lt;/code&gt;. This field is in milliseconds and includes both the connection establishment as well as user authentication (if any). By default, this is set to zero, which is usually a reasonable default – this uses the lesser of the &lt;code&gt;socketTimeout&lt;/code&gt; and &lt;code&gt;totalTimeout&lt;/code&gt;, or 2,000 milliseconds if both are zero. If the application can tolerate extra time when a connection is established, especially when using TLS, then this can be set to a non-zero value. For example, if you want a large &lt;code&gt;connectTimeout&lt;/code&gt; and a small &lt;code&gt;socketTimeout&lt;/code&gt; to allow for protracted SSL handshakes but fast application responses, setting this value to something like 5,000 milliseconds works well.&lt;/p&gt;

&lt;p&gt;Once a connection has been retrieved, the API call is sent to the server. There are two timeouts compared at this point, the &lt;code&gt;socketTimeout&lt;/code&gt; and the &lt;code&gt;totalTimeout&lt;/code&gt;. Both are in milliseconds, and the &lt;code&gt;socketTimeout&lt;/code&gt; reflects how long it takes to wait for data from this API call before retrying or failing. The &lt;code&gt;totalTimeout&lt;/code&gt; specifies the maximum time the call can take, including retries. If the time remaining in the &lt;code&gt;totalTimeout&lt;/code&gt; is less than the &lt;code&gt;socketTimeout&lt;/code&gt;, then the &lt;code&gt;totalTimeout&lt;/code&gt; is used as the &lt;code&gt;socketTimeout&lt;/code&gt; for the call. &lt;/p&gt;

&lt;p&gt;In Figure 1, the &lt;code&gt;socketTimeout&lt;/code&gt; is less than the &lt;code&gt;totalTimeout&lt;/code&gt;, so the ACL waits until one of the following occurs: &lt;code&gt;socketTimeout&lt;/code&gt; milliseconds have elapsed, the connection returns a timeout, or the call succeeds. If the call was unsuccessful in this period, the ACL checks the &lt;code&gt;maxRetries&lt;/code&gt; setting to see if any retries remain. For reads, this value defaults to two, giving it a total of three tries – the initial attempt plus the two retries. For writes, this value defaults to zero, so no retries are attempted.&lt;/p&gt;

&lt;p&gt;Figure 1 depicts a read with the default two retries, so once the original &lt;code&gt;socketTimeout&lt;/code&gt; expires, the API call does not return to the application. Instead, the ACL waits for &lt;code&gt;sleepBetweenRetries&lt;/code&gt; milliseconds and then submits the call again. &lt;/p&gt;

&lt;p&gt;This second call may or may not go to the same server. This is controlled by the &lt;code&gt;replica&lt;/code&gt; policy setting, which defaults to &lt;code&gt;SEQUENCE&lt;/code&gt;. Sequence means that the first attempt is made to the node containing the master record, but on failure, the retry is made to a replica. This can be very useful in a read-sensitive use case, for example. If the &lt;code&gt;socketTimeout&lt;/code&gt; is set to a short interval (say 20 milliseconds) and there are retries with a replica policy of SEQUENCE if the master node is busy and cannot respond in time or has fallen over. Still, if the cluster has not detected this yet, the retry will go to the replica and may return data within the application’s SLA.&lt;/p&gt;

&lt;p&gt;If this second call again times out after &lt;code&gt;socketTimeout&lt;/code&gt; milliseconds, a second delay of &lt;code&gt;sleepBetweenRetry&lt;/code&gt; milliseconds is performed then the second retry (3rd total attempt) is performed.&lt;/p&gt;

&lt;p&gt;Let’s take a look at where this leaves us in Figure 1:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v9THsB90--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developer-hub.s3.us-west-1.amazonaws.com/tim-faulkes/using-aerospike-policies-correctly-figure-1_1709244868414.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v9THsB90--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developer-hub.s3.us-west-1.amazonaws.com/tim-faulkes/using-aerospike-policies-correctly-figure-1_1709244868414.png" width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ACL is about to start the second retry, but in this case, the remaining time in the &lt;code&gt;totalTimeout&lt;/code&gt; is less than the &lt;code&gt;socketTimeout&lt;/code&gt;. Hence the API call will timeout before the &lt;code&gt;socketTimeout&lt;/code&gt; elapses when the remaining time in the &lt;code&gt;totalTimeout&lt;/code&gt; has elapsed. &lt;/p&gt;

&lt;p&gt;Note that once the &lt;code&gt;totalTimeout&lt;/code&gt; has elapsed, the client API call fails, even if further retries are available. &lt;/p&gt;

&lt;h2&gt;
  
  
  Timeout delay
&lt;/h2&gt;

&lt;p&gt;The only timeout setting not covered in the above is the &lt;code&gt;timeoutDelay&lt;/code&gt; setting. This is not strictly related to the API behavior but rather the system's efficiency. As the above shows, when the ACL submits the call to the server node, and no response is received within &lt;code&gt;socketTimeout&lt;/code&gt; milliseconds, either the call is abandoned, or a retry is performed. But what happens to the connection on which that original request was placed?&lt;/p&gt;

&lt;p&gt;By default, that connection is closed, destroying the connection and not placing it back in the connection pool. This is because it is possible that the server simply did not respond in time, and it might respond some time later. If the connection was reused instead of being closed, this server response might confuse the communication of the reusing call. &lt;/p&gt;

&lt;p&gt;However, as discussed above, connection establishment can be expensive. Closing connections typically means that this connection must be re-established later, which can impact the application. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;timeoutDelay&lt;/code&gt; parameter specifies a time interval in milliseconds for those connections to be kept alive. If the server responds within that timeout, the socket is drained and then returned to the connection pool. If the timeout is exceeded, then the connection is closed. &lt;/p&gt;

&lt;p&gt;Note that there is a cost of using the &lt;code&gt;timeoutDelay&lt;/code&gt; as the ACL must keep track of which connections have timed out. It is useful in situations where timeouts may occur frequently (for example, aggressive read settings) and connection establishment is expensive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default policies
&lt;/h2&gt;

&lt;p&gt;Now that the timeout settings are understood, we can discuss default policies. The ACL defines default values of the various policy attributes, which users can customize to suit their application instead of repeatedly modifying the defaults in the application code. Default policies are set up when the ACL is created and are used when &lt;code&gt;null&lt;/code&gt; is passed to the policy parameter in the API call. Most often, the default policies are customized with the network settings discussed above. &lt;/p&gt;

&lt;p&gt;Here is an example which creates a default &lt;code&gt;writePolicy&lt;/code&gt; with a &lt;code&gt;socketTimeout&lt;/code&gt; of 2,000 milliseconds:&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;WritePolicy&lt;/span&gt; &lt;span class="n"&gt;writePolicyDefault&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WritePolicy&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;writePolicyDefault&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;socketTimeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;ClientPolicy&lt;/span&gt; &lt;span class="n"&gt;clientPolicy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ClientPolicy&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;clientPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;writePolicyDefault&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;writePolicyDefault&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;IAerospikeClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AerospikeClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clientPolicy&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the &lt;code&gt;writePolicyDefault&lt;/code&gt; is set on the &lt;code&gt;ClientPolicy&lt;/code&gt; instance before the ACL is created. When passed to the ACL constructor, a copy of the default policies is made so no changes are possible to the default policies.&lt;/p&gt;

&lt;p&gt;After executing this code, passing &lt;code&gt;null&lt;/code&gt; to a write API call will result in the ACL retrieving and using the defaultWritePolicy. Hence, the following two calls are identical:&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="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"joe"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWritePolicyDefault&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"joe"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating policies
&lt;/h2&gt;

&lt;p&gt;Timeout settings are typically set on default policies and reused multiple times across the application. However, application-level settings are done as needed by the application on a per-call basis. Consider a check-and-set scenario where a record has been read from the database, changes made, and then those changes pushed back to the database, but only if the record has not been changed since it was read:&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;Record&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="nc"&gt;WritePolicy&lt;/span&gt; &lt;span class="n"&gt;writePolicy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWritePolicyDefault&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;writePolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generation&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;writePolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generationPolicy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenerationPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;EXPECT_GEN_EQUAL&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;writePolicy&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"joe"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code attempts to solve the requirements, getting the &lt;code&gt;defaultWritePolicy&lt;/code&gt; from the ACL and then setting the generation and &lt;code&gt;generationPolicy&lt;/code&gt; correctly. However, this code is very dangerous and will create issues in the application. There is just one &lt;code&gt;defaultWritePolicy&lt;/code&gt; on the ACL, and the &lt;code&gt;getWritePolicyDefault()&lt;/code&gt;call will return a reference to that object, not a copy of that object. Hence, setting the generation values on that policy will affect all calls that use that default policy on all threads, almost certainly causing many calls to fail with an exception.&lt;/p&gt;

&lt;p&gt;Another common pattern to solve this problem is:&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;WritePolicy&lt;/span&gt; &lt;span class="n"&gt;writePolicy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WritePolicy&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;writePolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generation&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;writePolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generationPolicy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenerationPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;EXPECT_GEN_EQUAL&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;writePolicy&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"joe"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this code is an improvement on the previous snippet, it too, has a problem. In this case, a unique &lt;code&gt;WritePolicy&lt;/code&gt; instance has been created, preventing issues with this call affecting other calls. However, using new &lt;code&gt;WritePolicy()&lt;/code&gt; does not pick up the settings of the default write policy, so settings changed on this default policy, such as the &lt;code&gt;socketTimeout&lt;/code&gt; will not apply to this new policy.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;correct&lt;/strong&gt; way to create a new policy to override fields is as follows:&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;WritePolicy&lt;/span&gt; &lt;span class="n"&gt;writePolicy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WritePolicy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWritePolicyDefault&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="n"&gt;writePolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generation&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;writePolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generationPolicy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenerationPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;EXPECT_GEN_EQUAL&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;writePolicy&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"joe"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, a new &lt;code&gt;WritePolicy&lt;/code&gt; is created, but it gets a copy of all the settings off the default write policy. This object is local to this API call, so there is no contention with other calls.&lt;/p&gt;

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

&lt;p&gt;Aerospike’s &lt;code&gt;Policy&lt;/code&gt; classes are both powerful and flexible, allowing fine-grained, per-call control over both network and application-level settings. However, it is important to understand what the settings do to correctly control the API call. Network settings are often overlooked during the application development phase and are frequently poorly understood. A thorough understanding of them is critical to developing applications that perform well not just in the happy-day scenario but also in the face of network issues or server failures.&lt;/p&gt;

&lt;p&gt;Developers who are new to Aerospike should understand this simple pattern to create new policies. It will ensure the correct execution of the API without affecting other concurrent calls and unintended surprises.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>policies</category>
    </item>
    <item>
      <title>Unlock Aerospike Cloud: Exploring the power of the Aerospike LINQPad driver</title>
      <dc:creator>Richard Andersen</dc:creator>
      <pubDate>Wed, 28 Feb 2024 02:05:46 +0000</pubDate>
      <link>https://forem.com/aerospike/unlock-aerospike-cloud-exploring-the-power-of-the-aerospike-linqpad-driver-2b2d</link>
      <guid>https://forem.com/aerospike/unlock-aerospike-cloud-exploring-the-power-of-the-aerospike-linqpad-driver-2b2d</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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Funlock-aerospike-cloud-exploring-power-of-linqpad-driver-1_1709081514432.webp" 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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Funlock-aerospike-cloud-exploring-power-of-linqpad-driver-1_1709081514432.webp"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog is part of a continuing series showing how to use the Aerospike LINQPad driver. For other blogs in this series, please see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aerospike.com/developer/blog/aerospike-for-linqpad" rel="noopener noreferrer"&gt;Aerospike for LINQPad&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aerospike.com/developer/blog/how-to-use-auto-values-in-nosql-linqpad-driver" rel="noopener noreferrer"&gt;How to use auto-values in the Aerospike LINQPad driver&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Aerospike LINQPad driver is now able to connect to the Aerospike Cloud, providing all the power of &lt;a href="https://www.linqpad.net/nugetsamples.aspx" rel="noopener noreferrer"&gt;LINQPad&lt;/a&gt; combined with the &lt;a href="https://github.com/aerospike-community/aerospike-linqpad-driver/tree/main/linqpad-samples" rel="noopener noreferrer"&gt;Aerospike LINQPad driver&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This includes a graphical interface, &lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/linq/" rel="noopener noreferrer"&gt;LINQ&lt;/a&gt; support, and enhanced driver features to support the Aerospike Database. Find more information about LINQPad &lt;a href="https://www.linqpad.net/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s look at the new connection dialog and some of the features of the LINQPad driver.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connection dialog
&lt;/h2&gt;

&lt;p&gt;The new connection dialog will now have two tabs. The first tab will be for native, “self-managed”, Aerospike clusters, and the second tab is used to connect to &lt;a href="https://aerospike.com/docs/cloud" rel="noopener noreferrer"&gt;Aerospike Cloud&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Below shows the connection properties:&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Funlock-aerospike-cloud-exploring-the-power-of-the-aerospike-linqpad-driver-connection-dialog_1709081474856.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Funlock-aerospike-cloud-exploring-the-power-of-the-aerospike-linqpad-driver-connection-dialog_1709081474856.png"&gt;&lt;/a&gt;&lt;/p&gt;
Aerospike Cloud connection dialog



&lt;p&gt;A review of each property is below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The host name is provided in the cloud dashboard. The hyperlink will take you to the Aerospike login screen or,  if you are already logged in, to the dashboard.&lt;/li&gt;
&lt;li&gt;The cloud client connection port.&lt;/li&gt;
&lt;li&gt;If a VPC (AWS private link) is defined, this would be the host name displayed on the cloud dashboard. The host name field would be the VPC endpoint.&lt;/li&gt;
&lt;li&gt;The API key is created via the dashboard.&lt;/li&gt;
&lt;li&gt;If the API key and secret were exported from the dashboard to your local machine, this button will allow you to import that API Key CSV file. Properties “API Key” (item 4) and “API Secret” (item 7) are not required.&lt;/li&gt;
&lt;li&gt;If enabled, the built-in LINQPad password manager is used. When enabled, a dropdown will be displayed to select the Password Name you defined in the manager. The Password Manager can be found on the File menu of LINQPad.&lt;/li&gt;
&lt;li&gt;The associated API Key’s secret.&lt;/li&gt;
&lt;li&gt;If checked, it will show the API secret in plain text.&lt;/li&gt;
&lt;li&gt;The associated cloud namespace.&lt;/li&gt;
&lt;li&gt;If provided, a list of set names separated by a comma or space. The set names will be used to populate the sets under the namespace in the LINQPad connection tree (see below image). Also, set and bin “detection” will be performed to obtain the bins and data types. Regardless of whether this field is provided, you can always obtain this information from the “Null Set.” See the “Using Null Set” section below.&lt;/li&gt;
&lt;li&gt;Hyperlinks to additional topics.&lt;/li&gt;
&lt;li&gt;The timeout values that will be used when obtaining the connection or performing an operation. Note that the “Sleep” field is ignored for cloud connections.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below shows the relationship between the “set names” connection property and the LINQPad connection tree:&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Funlock-aerospike-cloud-exploring-the-power-of-the-aerospike-linqpad-driver-connection-tree-set-names_1709081474940.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Funlock-aerospike-cloud-exploring-the-power-of-the-aerospike-linqpad-driver-connection-tree-set-names_1709081474940.png"&gt;&lt;/a&gt;&lt;/p&gt;
Association between the “Set Names” property and the sets populated in the connection tree



&lt;h2&gt;
  
  
  Driver overview
&lt;/h2&gt;

&lt;p&gt;All the features of the Aerospike LINQPad driver are available, including the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Graphical interface with all LINQPad features&lt;/li&gt;
&lt;li&gt;Drag-and-drop of set names&lt;/li&gt;
&lt;li&gt;LINQ&lt;/li&gt;
&lt;li&gt;Serialize and deserialize any C# object via the Object-Mapper (POCO)&lt;/li&gt;
&lt;li&gt;Auto-Values, which provide dynamic data type conversion from Aerospike types to .Net types without testing or casting&lt;/li&gt;
&lt;li&gt;JSON support&lt;/li&gt;
&lt;li&gt;Explore the Aerospike API directly or use the driver’s enhanced API&lt;/li&gt;
&lt;/ul&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Funlock-aerospike-cloud-exploring-the-power-of-the-aerospike-linqpad-driver-2_1709081474438.gif" 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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Funlock-aerospike-cloud-exploring-the-power-of-the-aerospike-linqpad-driver-2_1709081474438.gif"&gt;&lt;/a&gt;&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Funlock-aerospike-cloud-exploring-the-power-of-the-aerospike-linqpad-driver-1_1709081473558.gif" 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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Funlock-aerospike-cloud-exploring-the-power-of-the-aerospike-linqpad-driver-1_1709081473558.gif"&gt;&lt;/a&gt;&lt;/p&gt;
Demonstrates some of the capabilities of LINQPad and the LINQPad driver



&lt;h2&gt;
  
  
  Using the Aerospike null set
&lt;/h2&gt;

&lt;p&gt;If the “Set Names” connection property is not provided, the set and bin names will not be provided in the LINQPad connection tree (see image above).&lt;br&gt;
You can still perform queries and API calls using the driver’s API features. Below is an example of a driver API call to obtain the records for Aerospike set “Artist”:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aerospike_cloud.NullSet.Where(ns =&amp;gt; ns.Aerospike.SetName == "Artist")&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Below is the output:&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Funlock-aerospike-cloud-exploring-the-power-of-the-aerospike-linqpad-driver-extended-api_1709081475084.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Funlock-aerospike-cloud-exploring-the-power-of-the-aerospike-linqpad-driver-extended-api_1709081475084.png"&gt;&lt;/a&gt;&lt;/p&gt;
Result using the driver’s extended API for set “Artist”



&lt;p&gt;You can always extend the “where” clause or interact with the result set.&lt;/p&gt;

&lt;h2&gt;
  
  
  Samples
&lt;/h2&gt;

&lt;p&gt;You can find samples for Aerospike LINQPad Cloud under the &lt;a href="https://github.com/aerospike-community/aerospike-linqpad-driver/tree/main/linqpad-samples/Cloud" rel="noopener noreferrer"&gt;samples folder&lt;/a&gt; or under the “Samples” tab in LINQPad.&lt;/p&gt;

&lt;h2&gt;
  
  
  Review
&lt;/h2&gt;

&lt;p&gt;In this installment of the Aerospike LINQPad driver blog series, we learned how to use LINQPad to connect to Aerospike Cloud. This connection makes exploring your data in the cloud just as easy as other deployment options. Stay tuned for more articles in this series highlighting additional features of the driver.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>linqpad</category>
      <category>cloud</category>
    </item>
    <item>
      <title>How to use the Kubernetes Operator to establish connectivity between clusters</title>
      <dc:creator>Naresh Maharaj</dc:creator>
      <pubDate>Fri, 09 Feb 2024 16:32:21 +0000</pubDate>
      <link>https://forem.com/aerospike/how-to-use-the-kubernetes-operator-to-establish-connectivity-between-clusters-443</link>
      <guid>https://forem.com/aerospike/how-to-use-the-kubernetes-operator-to-establish-connectivity-between-clusters-443</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fnaresh-maharaj%2Fhow-to-use-kubernetes-operator-to-establish-connectivity_1707420652860.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fnaresh-maharaj%2Fhow-to-use-kubernetes-operator-to-establish-connectivity_1707420652860.webp" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Discover how Aerospike's Cross Datacenter Replication feature (XDR) transfers data between clusters effortlessly.&lt;/p&gt;

&lt;p&gt;This post outlines how to establish connectivity between two Aerospike clusters by leveraging Aerospike's &lt;a href="https://aerospike.com/products/features/cross-datacenter-replication-xdr/" rel="noopener noreferrer"&gt;Cross Datacenter Replication&lt;/a&gt; (XDR) feature to seamlessly transmit data from a source cluster to a destination cluster, providing high availability for critical data systems. &lt;/p&gt;

&lt;p&gt;Ensuring network visibility for Aerospike service ports in the remote data center from a source cluster is crucial. However, this can pose challenges, especially in a Kubernetes environment. Fortunately, there is a solution:  deploying a proxy server in front of the private Kubernetes destination cluster. To showcase this solution, we recommend installing the &lt;a href="https://aerospike.com/products/kubernetes-operator/" rel="noopener noreferrer"&gt;Kubernetes Operator&lt;/a&gt; to facilitate the creation and scheduling of the source and destination databases. While the demonstration is on setting up replication in one direction, it's worth noting that Aerospike supports &lt;a href="https://aerospike.com/docs/server/architecture/active-active" rel="noopener noreferrer"&gt;active-active replication&lt;/a&gt;. This is accompanied by a &lt;a href="https://aerospike.com/docs/server/architecture/xdr#bin-convergence-in-mesh-topology" rel="noopener noreferrer"&gt;conflict resolution&lt;/a&gt; mechanism to handle update clashes. This &lt;a href="https://aerospike.com/docs/server/architecture/xdr" rel="noopener noreferrer"&gt;XDR&lt;/a&gt; proxy also supports this feature as well.&lt;/p&gt;

&lt;p&gt;Let's begin the process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmhy58692gtxhxdam7in.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmhy58692gtxhxdam7in.png" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Fig. 1 Aerospike Kubernetes Operator&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The following Kubernetes nodes have been created using EKS. &lt;/p&gt;

&lt;p&gt;First, display the following private and public IP addresses from listing the nodes with the kubectl command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get nodes &lt;span class="nt"&gt;-o&lt;/span&gt; wide

NAME                             STATUS   ROLES    AGE     VERSION                INTERNAL-IP      EXTERNAL-IP      OS-IMAGE         KERNEL-VERSION                 CONTAINER-RUNTIME
ip-192-168-11-132.ec2.internal   Ready    &amp;lt;none&amp;gt;   2m53s   v1.22.15-eks-fb459a0   192.168.11.132   44.201.67.177    Amazon Linux 2   5.4.219-126.411.amzn2.x86_64   docker://20.10.17
ip-192-168-31-131.ec2.internal   Ready    &amp;lt;none&amp;gt;   2m52s   v1.22.15-eks-fb459a0   192.168.31.131   44.192.83.79     Amazon Linux 2   5.4.219-126.411.amzn2.x86_64   docker://20.10.17
ip-192-168-41-140.ec2.internal   Ready    &amp;lt;none&amp;gt;   2m51s   v1.22.15-eks-fb459a0   192.168.41.140   18.208.222.35    Amazon Linux 2   5.4.219-126.411.amzn2.x86_64   docker://20.10.17
ip-192-168-41-63.ec2.internal    Ready    &amp;lt;none&amp;gt;   2m51s   v1.22.15-eks-fb459a0   192.168.41.63    54.173.138.131   Amazon Linux 2   5.4.219-126.411.amzn2.x86_64   docker://20.10.17
ip-192-168-59-220.ec2.internal   Ready    &amp;lt;none&amp;gt;   2m52s   v1.22.15-eks-fb459a0   192.168.59.220   54.227.122.222   Amazon Linux 2   5.4.219-126.411.amzn2.x86_64   docker://20.10.17
ip-192-168-6-124.ec2.internal    Ready    &amp;lt;none&amp;gt;   2m51s   v1.22.15-eks-fb459a0   192.168.6.124    35.174.60.1      Amazon Linux 2   5.4.219-126.411.amzn2.x86_64   docker://20.10.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, get a copy of the Aerospike git repo for the Kubernetes Operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="se"&gt;\ &lt;/span&gt;https://github.com/aerospike/aerospike-kubernetes-operator.git
&lt;span class="nb"&gt;cp &lt;/span&gt;features.conf &lt;span class="se"&gt;\ &lt;/span&gt;aerospike-kubernetes-operator/config/samples/secrets/.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Run the following commands in the order specified. Wait for the CSV “Succeeded phase” to appear after running this line. Initially, it might take between 30 seconds and a minute to show up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get csv &lt;span class="nt"&gt;-n&lt;/span&gt; operators &lt;span class="nt"&gt;-w&lt;/span&gt;

&lt;span class="nb"&gt;cd &lt;/span&gt;aerospike-kubernetes-operator/
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; config/samples/storage/eks_ssd_storage_class.yaml
curl &lt;span class="nt"&gt;-sL&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.22.0/install.sh | bash &lt;span class="nt"&gt;-s&lt;/span&gt; v0.22.0
kubectl create &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
https://operatorhub.io/install/aerospike-kubernetes-operator.yaml
kubectl get csv &lt;span class="nt"&gt;-n&lt;/span&gt; operators &lt;span class="nt"&gt;-w&lt;/span&gt;
cd..
git clone &lt;span class="se"&gt;\ &lt;/span&gt;https://github.com/nareshmaharaj-consultant/kubernetes-anything
&lt;span class="nb"&gt;cd &lt;/span&gt;kubernetes-anything
./createNamespace.sh aerospike
&lt;span class="nb"&gt;cd&lt;/span&gt; ../aerospike-kubernetes-operator/
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike create secret generic aerospike-secret &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--from-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config/samples/secrets
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike create secret generic auth-secret &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--from-literal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'admin123'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Destination Cluster
&lt;/h3&gt;

&lt;p&gt;Use the following YAML configuration file for our destination cluster. Save the file and name it ssd1_xdr_dest_6.1_cluster_cr.yaml:&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="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;asdb.aerospike.com/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AerospikeCluster&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&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;aerocluster-dest-xdr&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aerospike&lt;/span&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aerospike/aerospike-server-enterprise:6.1.0.2&lt;/span&gt;

  &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;filesystemVolumePolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;initMethod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deleteFiles&lt;/span&gt;
      &lt;span class="na"&gt;cascadeDelete&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;blockVolumePolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cascadeDelete&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&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;workdir&lt;/span&gt;
        &lt;span class="na"&gt;aerospike&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/opt/aerospike&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;persistentVolume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;storageClass&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ssd&lt;/span&gt;
            &lt;span class="na"&gt;volumeMode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Filesystem&lt;/span&gt;
            &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1Gi&lt;/span&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;ns&lt;/span&gt;
        &lt;span class="na"&gt;aerospike&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/opt/aerospike/data/&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;persistentVolume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;storageClass&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ssd&lt;/span&gt;
            &lt;span class="na"&gt;volumeMode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Filesystem&lt;/span&gt;
            &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1Gi&lt;/span&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;aerospike-config-secret&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;secretName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aerospike-secret&lt;/span&gt;
        &lt;span class="na"&gt;aerospike&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/etc/aerospike/secret&lt;/span&gt;

  &lt;span class="na"&gt;podSpec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;multiPodPerHost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="na"&gt;aerospikeAccessControl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&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;writer&lt;/span&gt;
        &lt;span class="na"&gt;privileges&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;read-write&lt;/span&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;reader&lt;/span&gt;
        &lt;span class="na"&gt;privileges&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
    &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&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;admin&lt;/span&gt;
        &lt;span class="na"&gt;secretName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;auth-secret&lt;/span&gt;
        &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sys-admin&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;user-admin&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;read-write&lt;/span&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;xdr-writer&lt;/span&gt;
        &lt;span class="na"&gt;secretName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xdr-user-auth-secret&lt;/span&gt;
        &lt;span class="na"&gt;roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;writer&lt;/span&gt;

  &lt;span class="na"&gt;aerospikeConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&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="s"&gt;/etc/aerospike/secret/features.conf&lt;/span&gt;
    &lt;span class="na"&gt;security&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
    &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;service&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;3000&lt;/span&gt;
      &lt;span class="na"&gt;fabric&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;3001&lt;/span&gt;
      &lt;span class="na"&gt;heartbeat&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;3002&lt;/span&gt;
    &lt;span class="na"&gt;namespaces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&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;test&lt;/span&gt;
        &lt;span class="na"&gt;memory-size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;134217728&lt;/span&gt;
        &lt;span class="na"&gt;replication-factor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="na"&gt;storage-engine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;device&lt;/span&gt;
          &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/opt/aerospike/data/test.dat&lt;/span&gt;
          &lt;span class="na"&gt;filesize&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1073741824&lt;/span&gt;
          &lt;span class="na"&gt;data-in-memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create the following Kubernetes resources for our Aerospike destination cluster:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;XDR destination database user login credentials, as a Kubernetes secret&lt;/li&gt;
&lt;li&gt;Destination database cluster using our YAML file named ssd1_xdr_dest_6.1_cluster_cr.yaml
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;secret_auth_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xdr-user-auth-secret
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;password_secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin123
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike create secret generic &lt;span class="nv"&gt;$secret_auth_name&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--from-literal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$password_secret&lt;/span&gt;
kubectl create &lt;span class="nt"&gt;-f&lt;/span&gt; ssd1_xdr_dest_6.1_cluster_cr.yaml
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike get po &lt;span class="nt"&gt;-w&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the database pods up and running successfully.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get po &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike &lt;span class="nt"&gt;-w&lt;/span&gt;

NAME                       READY   STATUS     RESTARTS   AGE
aerocluster-dest-xdr-0-0   0/1     Init:0/1   0          13s
aerocluster-dest-xdr-0-0   0/1     Init:0/1   0          18s
aerocluster-dest-xdr-0-0   0/1     PodInitializing   0          19s
aerocluster-dest-xdr-0-0   1/1     Running           0          24s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  XDR-Proxy
&lt;/h3&gt;

&lt;p&gt;Next, set up the xdr-proxy. Take a brief look at &lt;em&gt;Fig. 1 Aerospike Kubernetes Operator&lt;/em&gt;, and you’ll notice that we are working from the right to the left in that order.&lt;/p&gt;

&lt;h4&gt;
  
  
  Configuration
&lt;/h4&gt;

&lt;p&gt;Create the following xdr-proxy configuration file. Replace the seed address with a fully qualified domain name (FQDN) for the destination database pod(s) you created earlier. Multiple seed addresses may be added (hint: recommended in production).&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;cd&lt;/span&gt; ..
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; xdr-cfg/etc/auth
&lt;span class="nb"&gt;cd &lt;/span&gt;xdr-cfg/etc/

&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;&amp;gt; aerospike-xdr-proxy.yml
# Change the configuration for your use case.
# Naresh Maharaj
# Refer to https://www.aerospike.com/docs/connectors/enterprise/xdr-proxy/configuration/index.html
# for details.

# The connector's listening ports, manage service, TLS, and network interface.
service:
  port: 8901
  # Aerospike Enterprise Server &amp;gt;= 5.0
  manage:
    address: 0.0.0.0
    port: 8902

# The destination aerospike cluster.
aerospike:
  seeds:
    - aerocluster-dest-xdr-0-0.aerospike.svc.cluster.local:
        port: 3000
  credentials:
    username: xdr-writer
    password-file: /etc/aerospike-xdr-proxy/auth/password_DC1.txt
    auth-mode: internal

# The logging config
logging:
  enable-console-logging: true
  file: /var/log/aerospike-xdr-proxy/aerospike-xdr-proxy.log
  levels:
    root: debug
    record-parser: debug
    server: debug
    com.aerospike.connect: debug
  # Ticker log interval in seconds
  ticker-interval: 3600
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="nb"&gt;sudo tee &lt;/span&gt;auth/password_DC1.txt &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
admin123
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ..

kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike create configmap xdr-proxy-cfg &lt;span class="nt"&gt;--from-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;etc/
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike create secret generic xdr-proxy-auth-secret &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--from-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;etc/auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Deployment
&lt;/h4&gt;

&lt;p&gt;Now that you have the xdr-proxy configuration file created, produce the Kubernetes deployment YAML file for the xdr-proxy. The following YAML file is used to deploy the xdr-proxy pods, ideally in the same data center or location where the destination databases will be hosted. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tip&lt;/em&gt;: Remember that your xdr-proxy configuration differs from the Kubernetes xdr-proxy deployment file.&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;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;&amp;gt; xdr-proxy-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: xdr-proxy
  namespace: aerospike
  labels:
    app: xdr-proxy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: xdr-proxy
  template:
    metadata:
      labels:
        app: xdr-proxy
    spec:
      containers:
      - name: xdr-proxy
        image: aerospike/aerospike-xdr-proxy:2.1.0
        volumeMounts:
        - name: xdr-proxy-dir
          mountPath: "/etc/aerospike-xdr-proxy/"
          readOnly: true
        - name: xdr-auth-dir
          mountPath: "/etc/aerospike-xdr-proxy/auth"
          readOnly: true
        ports:
          - name: xdr-proxy-main
            containerPort: 8901
          - name: xdr-proxy-mng
            containerPort: 8902
      volumes:
      - name: xdr-proxy-dir
        configMap:
          name: xdr-proxy-cfg
          optional: false
      - name: xdr-auth-dir
        secret:
          secretName: xdr-proxy-auth-secret
          optional: false
---
apiVersion: v1
kind: Service
metadata:
  name: xdr-proxy
  namespace: aerospike
spec:
  selector:
    app: xdr-proxy
  ports:
  - name: main
    protocol: TCP
    port: 8901
    targetPort: xdr-proxy-main
  - name: manage
    protocol: TCP
    port: 8902
    targetPort: xdr-proxy-mng
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;kubectl create &lt;span class="nt"&gt;-f&lt;/span&gt; xdr-proxy-deployment.yaml
kubectl get po &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike &lt;span class="nt"&gt;-w&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following command shows the current pods are running successfully. So far, so good!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get po &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike &lt;span class="nt"&gt;-w&lt;/span&gt;
NAME                         READY   STATUS    RESTARTS   AGE
aerocluster-dest-xdr-0-0     1/1     Running   0          77m
xdr-proxy-7d9fccd6c8-g5mjt   1/1     Running   0          2m26s
xdr-proxy-7d9fccd6c8-mjxp4   1/1     Running   0          2m26s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Source cluster
&lt;/h4&gt;

&lt;p&gt;Create the Aerospike source cluster using the following configuration. We will insert our sample messages here.&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;cd&lt;/span&gt; ../aerospike-kubernetes-operator/

&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;&amp;gt; ssd1_xdr_src_6.1_cluster_cr.yaml
apiVersion: asdb.aerospike.com/v1beta1
kind: AerospikeCluster
metadata:
  name: aerocluster-source-xdr
  namespace: aerospike

spec:
  size: 1
  image: aerospike/aerospike-server-enterprise:6.1.0.2

  storage:
    filesystemVolumePolicy:
      initMethod: deleteFiles
      cascadeDelete: true
    blockVolumePolicy:
      cascadeDelete: true
    volumes:
      - name: workdir
        aerospike:
          path: /opt/aerospike
        source:
          persistentVolume:
            storageClass: ssd
            volumeMode: Filesystem
            size: 1Gi
      - name: ns
        aerospike:
          path: /opt/aerospike/data/
        source:
          persistentVolume:
            storageClass: ssd
            volumeMode: Filesystem
            size: 1Gi
      - name: aerospike-config-secret
        source:
          secret:
            secretName: aerospike-secret
        aerospike:
          path: /etc/aerospike/secret

  podSpec:
    multiPodPerHost: true

  aerospikeAccessControl:
    roles:
      - name: writer
        privileges:
        - read-write
      - name: reader
        privileges:
        - read
    users:
      - name: admin
        secretName: auth-secret
        roles:
          - sys-admin
          - user-admin
          - read-write

  aerospikeConfig:
    service:
      feature-key-file: /etc/aerospike/secret/features.conf
    security: {}
    network:
      service:
        port: 3000
      fabric:
        port: 3001
      heartbeat:
        port: 3002
    xdr:
      dcs:
        - name: DC2
          connector: true
          node-address-ports:
            - xdr-proxy.aerospike.svc.cluster.local 8901
          namespaces:
            - name: test
    namespaces:
      - name: test
        memory-size: 134217728
        replication-factor: 1
        storage-engine:
          type: device
          files:
            - /opt/aerospike/data/test.dat
          filesize: 1073741824
          data-in-memory: true
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;kubectl create &lt;span class="nt"&gt;-f&lt;/span&gt; ssd1_xdr_src_6.1_cluster_cr.yaml
kubectl get po &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike &lt;span class="nt"&gt;-w&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the source cluster, confirm the XDR component has connected to the xdr-proxy by filtering the Kubernetes log file as shown in the following kubectl command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike logs aerocluster-source-xdr-0-0 &lt;span class="nt"&gt;-c&lt;/span&gt; aerospike-server | &lt;span class="nb"&gt;grep &lt;/span&gt;xdr | &lt;span class="nb"&gt;grep &lt;/span&gt;conn
Dec 08 2022 13:49:21 GMT: INFO &lt;span class="o"&gt;(&lt;/span&gt;xdr&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;dc.c:581&lt;span class="o"&gt;)&lt;/span&gt; DC DC2 connected Oct 10 2022 13:57:53 GMT: INFO &lt;span class="o"&gt;(&lt;/span&gt;xdr&lt;span class="o"&gt;)&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;dc.c:581&lt;span class="o"&gt;)&lt;/span&gt; DC DC2 connected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Simple message test
&lt;/h2&gt;

&lt;p&gt;Add some sample messages to the source database and confirm they are being received in the destination database cluster. Start by getting the source database service address and connect using Aerospike's command line tool -  &lt;a href="https://aerospike.com/docs/tools/aql" rel="noopener noreferrer"&gt;AQL&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get svc &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike

NAME                         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt;             AGE
aerocluster-dest-xdr         ClusterIP   None             &amp;lt;none&amp;gt;        3000/TCP            3h38m
aerocluster-dest-xdr-0-0     NodePort    10.100.226.179   &amp;lt;none&amp;gt;        3000:30168/TCP      3h38m
aerocluster-source-xdr       ClusterIP   None             &amp;lt;none&amp;gt;        3000/TCP            33m
aerocluster-source-xdr-0-0   NodePort    10.100.116.173   &amp;lt;none&amp;gt;        3000:31999/TCP      33m
xdr-proxy                    ClusterIP   10.100.44.96     &amp;lt;none&amp;gt;        8901/TCP,8902/TCP   41m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Insert a source record using the following command in AQL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Never aerospike-tool &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;aerospike/aerospike-tools:latest &lt;span class="nt"&gt;--&lt;/span&gt; aql &lt;span class="nt"&gt;-U&lt;/span&gt; admin &lt;span class="nt"&gt;-P&lt;/span&gt; admin123 &lt;span class="nt"&gt;-h&lt;/span&gt; aerocluster-source-xdr-0-0

insert into test.a1 &lt;span class="o"&gt;(&lt;/span&gt;PK,a,b,c,d&lt;span class="o"&gt;)&lt;/span&gt; values&lt;span class="o"&gt;(&lt;/span&gt;1,&lt;span class="s2"&gt;"A"&lt;/span&gt;,&lt;span class="s2"&gt;"B"&lt;/span&gt;,&lt;span class="s2"&gt;"C"&lt;/span&gt;,&lt;span class="s2"&gt;"D"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
OK, 1 record affected.

aql&amp;gt; &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; from &lt;span class="nb"&gt;test&lt;/span&gt;
+----+-----+-----+-----+-----+
| PK | a   | b   | c   | d   |
+----+-----+-----+-----+-----+
| 1  | &lt;span class="s2"&gt;"A"&lt;/span&gt; | &lt;span class="s2"&gt;"B"&lt;/span&gt; | &lt;span class="s2"&gt;"C"&lt;/span&gt; | &lt;span class="s2"&gt;"D"&lt;/span&gt; |
+----+-----+-----+-----+-----+
1 row &lt;span class="k"&gt;in &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0.023 secs&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, run the following select query in the destination cluster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Never aerospike-tool &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;aerospike/aerospike-tools:latest &lt;span class="nt"&gt;--&lt;/span&gt; aql &lt;span class="nt"&gt;-U&lt;/span&gt; admin &lt;span class="nt"&gt;-P&lt;/span&gt; admin123 &lt;span class="nt"&gt;-h&lt;/span&gt; aerocluster-dest-xdr-0-0

aql&amp;gt; &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; from &lt;span class="nb"&gt;test&lt;/span&gt;
+----+-----+-----+-----+-----+
| PK | a   | b   | c   | d   |
+----+-----+-----+-----+-----+
| 1  | &lt;span class="s2"&gt;"A"&lt;/span&gt; | &lt;span class="s2"&gt;"B"&lt;/span&gt; | &lt;span class="s2"&gt;"C"&lt;/span&gt; | &lt;span class="s2"&gt;"D"&lt;/span&gt; |
+----+-----+-----+-----+-----+
1 row &lt;span class="k"&gt;in &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0.031 secs&lt;span class="o"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Interim summary
&lt;/h2&gt;

&lt;p&gt;At this point, it's confirmed that xdr-proxy is doing exactly what It should do.&lt;/p&gt;

&lt;p&gt;If if you review the log file for the initial two xdr-proxies scheduled, you should see userKey=1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl logs xdr-proxy-7d9fccd6c8-5q7gn &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike | &lt;span class="nb"&gt;grep &lt;/span&gt;record-parser
2022-12-08 14:53:50.607 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;a1, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;120, 48, &lt;span class="nt"&gt;-23&lt;/span&gt;, &lt;span class="nt"&gt;-90&lt;/span&gt;, 110, 126, 84, &lt;span class="nt"&gt;-1&lt;/span&gt;, 114, &lt;span class="nt"&gt;-116&lt;/span&gt;, &lt;span class="nt"&gt;-9&lt;/span&gt;, &lt;span class="nt"&gt;-21&lt;/span&gt;, 28, 75, 126, &lt;span class="nt"&gt;-68&lt;/span&gt;, &lt;span class="nt"&gt;-51&lt;/span&gt;, 83, 31, &lt;span class="nt"&gt;-117&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670511230565, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'eDDppm5+VP9yjPfrHEt+vM1TH4s='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

kubectl logs xdr-proxy-7d9fccd6c8-f5zkt &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
record-parser
&lt;span class="o"&gt;(&lt;/span&gt;none&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Scaling the XDR-Proxies
&lt;/h2&gt;

&lt;p&gt;Go ahead and scale up the xdr-proxy to six pods by editing the file xdr-proxy-deployment.yaml and then apply the changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: xdr-proxy
  namespace: aerospike
  labels:
    app: xdr-proxy
spec:
  replicas: 6
  selector:
    matchLabels:
      app: xdr-proxy
...
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; xdr-proxy-deployment.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can achieve exactly the same by running the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl scale deploy xdr-proxy &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike &lt;span class="nt"&gt;--replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should now have six instances of the xdr-proxies running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get po &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike &lt;span class="nt"&gt;-w&lt;/span&gt;
NAME                         READY   STATUS    RESTARTS   AGE
aerocluster-dest-xdr-0-0     1/1     Running   0          3h50m
aerocluster-source-xdr-0-0   1/1     Running   0          75m
xdr-proxy-7d9fccd6c8-49ttl   1/1     Running   0          7s
xdr-proxy-7d9fccd6c8-5q7gn   1/1     Running   0          83m
xdr-proxy-7d9fccd6c8-c4j7k   1/1     Running   0          7s
xdr-proxy-7d9fccd6c8-f5zkt   1/1     Running   0          83m
xdr-proxy-7d9fccd6c8-lscbg   1/1     Running   0          7s
xdr-proxy-7d9fccd6c8-r56vs   1/1     Running   0          7s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add some sample messages in the source cluster with primary keys 5, 6, and 7. Note that in Aerospike, a primary key serves as a unique identifier for a record within a specific set in a specific namespace. This key is a unique identifier for addressing the record for any operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aql&amp;gt; insert into &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;PK,a,b&lt;span class="o"&gt;)&lt;/span&gt; values &lt;span class="o"&gt;(&lt;/span&gt;5,&lt;span class="s2"&gt;"A"&lt;/span&gt;,&lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
OK, 1 record affected.
aql&amp;gt; insert into &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;PK,a,b&lt;span class="o"&gt;)&lt;/span&gt; values &lt;span class="o"&gt;(&lt;/span&gt;6,&lt;span class="s2"&gt;"A"&lt;/span&gt;,&lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
OK, 1 record affected.
aql&amp;gt; insert into &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;PK,a,b&lt;span class="o"&gt;)&lt;/span&gt; values &lt;span class="o"&gt;(&lt;/span&gt;7,&lt;span class="s2"&gt;"A"&lt;/span&gt;,&lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
OK, 1 record affected.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how userKey=5, userKey=6, and userKey=7 have been shipped across to the newly scaled xdr-proxies. Run the commands below to see the same,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl logs xdr-proxy-7d9fccd6c8-5q7gn &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
record-parser
2022-12-08 14:53:50.607 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;a1, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;120, 48, &lt;span class="nt"&gt;-23&lt;/span&gt;, &lt;span class="nt"&gt;-90&lt;/span&gt;, 110, 126, 84, &lt;span class="nt"&gt;-1&lt;/span&gt;, 114, &lt;span class="nt"&gt;-116&lt;/span&gt;, &lt;span class="nt"&gt;-9&lt;/span&gt;, &lt;span class="nt"&gt;-21&lt;/span&gt;, 28, 75, 126, &lt;span class="nt"&gt;-68&lt;/span&gt;, &lt;span class="nt"&gt;-51&lt;/span&gt;, 83, 31, &lt;span class="nt"&gt;-117&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670511230565, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'eDDppm5+VP9yjPfrHEt+vM1TH4s='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

kubectl logs xdr-proxy-7d9fccd6c8-f5zkt &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
record-parser
&lt;span class="o"&gt;(&lt;/span&gt;none&lt;span class="o"&gt;)&lt;/span&gt;

kubectl logs xdr-proxy-7d9fccd6c8-49ttl &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
record-parser
&lt;span class="o"&gt;(&lt;/span&gt;none&lt;span class="o"&gt;)&lt;/span&gt;

kubectl logs xdr-proxy-7d9fccd6c8-c4j7k &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
record-parser
2022-12-08 15:05:37.511 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="nt"&gt;-88&lt;/span&gt;, 104, 104, &lt;span class="nt"&gt;-114&lt;/span&gt;, 19, &lt;span class="nt"&gt;-44&lt;/span&gt;, &lt;span class="nt"&gt;-19&lt;/span&gt;, 29, &lt;span class="nt"&gt;-15&lt;/span&gt;, 18, 118, 72, &lt;span class="nt"&gt;-117&lt;/span&gt;, &lt;span class="nt"&gt;-106&lt;/span&gt;, &lt;span class="nt"&gt;-28&lt;/span&gt;, 21, &lt;span class="nt"&gt;-48&lt;/span&gt;, 50, 26, 113], &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670511937250, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'qGhojhPU7R3xEnZIi5bkFdAyGnE='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

kubectl logs xdr-proxy-7d9fccd6c8-lscbg &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike | &lt;span class="nb"&gt;grep &lt;/span&gt;record-parser
2022-12-08 15:05:27.548 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;68, 4, &lt;span class="nt"&gt;-94&lt;/span&gt;, &lt;span class="nt"&gt;-44&lt;/span&gt;, &lt;span class="nt"&gt;-75&lt;/span&gt;, 112, &lt;span class="nt"&gt;-102&lt;/span&gt;, 73, &lt;span class="nt"&gt;-120&lt;/span&gt;, 41, &lt;span class="nt"&gt;-101&lt;/span&gt;, &lt;span class="nt"&gt;-120&lt;/span&gt;, 33, &lt;span class="nt"&gt;-111&lt;/span&gt;, 15, &lt;span class="nt"&gt;-114&lt;/span&gt;, &lt;span class="nt"&gt;-85&lt;/span&gt;, 46, &lt;span class="nt"&gt;-2&lt;/span&gt;, 80], &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670511927465, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'RASi1LVwmkmIKZuIIZEPjqsu/lA='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 15:05:32.300 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;33, &lt;span class="nt"&gt;-100&lt;/span&gt;, 127, 120, 17, 45, &lt;span class="nt"&gt;-79&lt;/span&gt;, 115, &lt;span class="nt"&gt;-40&lt;/span&gt;, 53, &lt;span class="nt"&gt;-70&lt;/span&gt;, &lt;span class="nt"&gt;-57&lt;/span&gt;, 120, 73, 20, &lt;span class="nt"&gt;-50&lt;/span&gt;, &lt;span class="nt"&gt;-99&lt;/span&gt;, &lt;span class="nt"&gt;-98&lt;/span&gt;, &lt;span class="nt"&gt;-104&lt;/span&gt;, 85], &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;6, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670511932288, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;6, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'IZx/eBEtsXPYNbrHeEkUzp2emFU='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

kubectl logs xdr-proxy-7d9fccd6c8-r56vs &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike | &lt;span class="nb"&gt;grep &lt;/span&gt;record-parser
&lt;span class="o"&gt;(&lt;/span&gt;none&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, we need to consider one critical factor. When data is actively flowing between source and destination clusters, the existing cached list of xdr-proxy connections from the source cluster will not be refreshed just because you added a bunch of new xdr-proxies. Consequently,  the newly scaled xdr-proxies you have just scheduled will not be utilized immediately.&lt;/p&gt;

&lt;p&gt;To demonstrate this, let's add data to the source cluster using Aerospike's benchmark tool. At the same time, we will scale the xdr-proxies on the destination side and observe the results. &lt;/p&gt;

&lt;h2&gt;
  
  
  Add data to the source cluster
&lt;/h2&gt;

&lt;p&gt;Before you begin, reduce the xdr-proxy server count to one (1) to clarify the observations. In this example, I use my local machine, which has the benchmark tool installed, to send data to the source EC2 instances. To do this, you’ll need to obtain the external IP address of the source cluster’s Kubernetes service. You can download the benchmark tool from &lt;a href="https://aerospike.com/docs/tools/install" rel="noopener noreferrer"&gt;https://aerospike.com/docs/tools/install&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get AerospikeCluster aerocluster-source-xdr &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike  &lt;span class="nt"&gt;-o&lt;/span&gt; yaml

...
pods:
    aerocluster-source-xdr-0-0:
      aerospike:
        accessEndpoints:
        - 192.168.41.63:31999
        alternateAccessEndpoints:
        - 54.173.138.131:31999
        clusterName: aerocluster-source-xdr
        nodeID: 0a0
        tlsAccessEndpoints: &lt;span class="o"&gt;[]&lt;/span&gt;
        tlsAlternateAccessEndpoints: &lt;span class="o"&gt;[]&lt;/span&gt;
        tlsName: &lt;span class="s2"&gt;""&lt;/span&gt;
      aerospikeConfigHash: 4aacb9809beaa01d99a9f00293c9f7dc141845f8
      hostExternalIP: 54.173.138.131
      hostInternalIP: 192.168.41.63
      image: aerospike/aerospike-server-enterprise:6.1.0.2
      initializedVolumes:
      - workdir
      - ns
      networkPolicyHash: acbbfab3668e1fceeed201139d1173f00095667e
      podIP: 192.168.50.203
      podPort: 3000
      podSpecHash: 972dc2a779fe9ab407212b547d54d3a72ecef259
      servicePort: 31999
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may need to add a  firewall rule to allow traffic into the Kubernetes service. Connect the asbenchmark tool to start writing traffic using the public IP address for the NodePort Service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;asbenchmark &lt;span class="nt"&gt;-h&lt;/span&gt; 54.173.138.131:31999 &lt;span class="nt"&gt;-Uadmin&lt;/span&gt; &lt;span class="nt"&gt;-Padmin123&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; 10 &lt;span class="nt"&gt;-servicesAlternate&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; RU,0 &lt;span class="nt"&gt;-o&lt;/span&gt; B256
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scale up the xdr-proxy servers from one to two and check the logs of both proxies to see what messages have been received. In a production environment, you should always disable the unnecessary logging.&lt;/p&gt;

&lt;p&gt;Notice how no data has passed through the new xdr-proxy instance xdr-proxy-7d9fccd6c8-s2tzt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike logs xdr-proxy-7d9fccd6c8-s2tzt | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
record-parser
&lt;span class="o"&gt;(&lt;/span&gt;none&lt;span class="o"&gt;)&lt;/span&gt;

kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; aerospike logs xdr-proxy-7d9fccd6c8-5q7gn | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
record-parser
...
2022-12-08 18:21:36.158 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;51, &lt;span class="nt"&gt;-120&lt;/span&gt;, 114, &lt;span class="nt"&gt;-17&lt;/span&gt;, &lt;span class="nt"&gt;-44&lt;/span&gt;, 72, 123, 125, 50, 92, 3, 110, &lt;span class="nt"&gt;-21&lt;/span&gt;, &lt;span class="nt"&gt;-38&lt;/span&gt;, 74, 25, 42, 35, 117, 72], &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696059, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'M4hy79RIe30yXANu69pKGSojdUg='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.158 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;124, &lt;span class="nt"&gt;-6&lt;/span&gt;, &lt;span class="nt"&gt;-70&lt;/span&gt;, &lt;span class="nt"&gt;-23&lt;/span&gt;, 44, 41, &lt;span class="nt"&gt;-19&lt;/span&gt;, 40, &lt;span class="nt"&gt;-11&lt;/span&gt;, &lt;span class="nt"&gt;-16&lt;/span&gt;, 126, 120, 81, &lt;span class="nt"&gt;-113&lt;/span&gt;, &lt;span class="nt"&gt;-112&lt;/span&gt;, &lt;span class="nt"&gt;-79&lt;/span&gt;, 66, 77, &lt;span class="nt"&gt;-99&lt;/span&gt;, &lt;span class="nt"&gt;-6&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696059, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'fPq66Swp7Sj18H54UY+QsUJNnfo='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.158 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="nt"&gt;-127&lt;/span&gt;, &lt;span class="nt"&gt;-118&lt;/span&gt;, 63, &lt;span class="nt"&gt;-32&lt;/span&gt;, &lt;span class="nt"&gt;-74&lt;/span&gt;, 60, &lt;span class="nt"&gt;-60&lt;/span&gt;, 86, 31, &lt;span class="nt"&gt;-119&lt;/span&gt;, &lt;span class="nt"&gt;-1&lt;/span&gt;, &lt;span class="nt"&gt;-105&lt;/span&gt;, &lt;span class="nt"&gt;-108&lt;/span&gt;, &lt;span class="nt"&gt;-59&lt;/span&gt;, 111, 48, &lt;span class="nt"&gt;-34&lt;/span&gt;, &lt;span class="nt"&gt;-61&lt;/span&gt;, &lt;span class="nt"&gt;-108&lt;/span&gt;, &lt;span class="nt"&gt;-5&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696105, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'gYo/4LY8xFYfif+XlMVvMN7DlPs='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.256 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;99, 1, 80, 2, 76, &lt;span class="nt"&gt;-43&lt;/span&gt;, 125, 77, 47, 8, 6, 35, 49, 117, &lt;span class="nt"&gt;-35&lt;/span&gt;, 54, 120, &lt;span class="nt"&gt;-29&lt;/span&gt;, 118, &lt;span class="nt"&gt;-72&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696178, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'YwFQAkzVfU0vCAYjMXXdNnjjdrg='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.257 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="nt"&gt;-88&lt;/span&gt;, &lt;span class="nt"&gt;-46&lt;/span&gt;, &lt;span class="nt"&gt;-48&lt;/span&gt;, &lt;span class="nt"&gt;-33&lt;/span&gt;, 77, &lt;span class="nt"&gt;-120&lt;/span&gt;, 123, &lt;span class="nt"&gt;-101&lt;/span&gt;, &lt;span class="nt"&gt;-70&lt;/span&gt;, &lt;span class="nt"&gt;-20&lt;/span&gt;, &lt;span class="nt"&gt;-96&lt;/span&gt;, &lt;span class="nt"&gt;-104&lt;/span&gt;, &lt;span class="nt"&gt;-51&lt;/span&gt;, &lt;span class="nt"&gt;-90&lt;/span&gt;, 28, &lt;span class="nt"&gt;-15&lt;/span&gt;, 70, 11, 118, 83], &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696202, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'qNLQ302Ie5u67KCYzaYc8UYLdlM='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.257 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="nt"&gt;-97&lt;/span&gt;, 18, 28, &lt;span class="nt"&gt;-43&lt;/span&gt;, 75, 42, &lt;span class="nt"&gt;-22&lt;/span&gt;, &lt;span class="nt"&gt;-126&lt;/span&gt;, &lt;span class="nt"&gt;-61&lt;/span&gt;, &lt;span class="nt"&gt;-108&lt;/span&gt;, &lt;span class="nt"&gt;-36&lt;/span&gt;, 118, &lt;span class="nt"&gt;-86&lt;/span&gt;, &lt;span class="nt"&gt;-105&lt;/span&gt;, &lt;span class="nt"&gt;-52&lt;/span&gt;, 119, &lt;span class="nt"&gt;-39&lt;/span&gt;, &lt;span class="nt"&gt;-33&lt;/span&gt;, &lt;span class="nt"&gt;-127&lt;/span&gt;, &lt;span class="nt"&gt;-76&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696175, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'nxIc1Usq6oLDlNx2qpfMd9nfgbQ='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.257 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="nt"&gt;-120&lt;/span&gt;, 103, &lt;span class="nt"&gt;-51&lt;/span&gt;, 57, &lt;span class="nt"&gt;-71&lt;/span&gt;, &lt;span class="nt"&gt;-106&lt;/span&gt;, 13, &lt;span class="nt"&gt;-48&lt;/span&gt;, 100, 28, 59, &lt;span class="nt"&gt;-3&lt;/span&gt;, &lt;span class="nt"&gt;-39&lt;/span&gt;, &lt;span class="nt"&gt;-56&lt;/span&gt;, &lt;span class="nt"&gt;-67&lt;/span&gt;, &lt;span class="nt"&gt;-103&lt;/span&gt;, 29, 36, 75, 119], &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696191, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'iGfNObmWDdBkHDv92ci9mR0kS3c='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.257 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="nt"&gt;-47&lt;/span&gt;, 88, &lt;span class="nt"&gt;-13&lt;/span&gt;, 13, &lt;span class="nt"&gt;-35&lt;/span&gt;, 77, 24, 22, &lt;span class="nt"&gt;-40&lt;/span&gt;, &lt;span class="nt"&gt;-61&lt;/span&gt;, &lt;span class="nt"&gt;-118&lt;/span&gt;, &lt;span class="nt"&gt;-115&lt;/span&gt;, 82, 13, 127, &lt;span class="nt"&gt;-125&lt;/span&gt;, 53, 66, &lt;span class="nt"&gt;-22&lt;/span&gt;, &lt;span class="nt"&gt;-8&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696233, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'0VjzDd1NGBbYw4qNUg1/gzVC6vg='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.258 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="nt"&gt;-63&lt;/span&gt;, &lt;span class="nt"&gt;-11&lt;/span&gt;, 93, &lt;span class="nt"&gt;-90&lt;/span&gt;, 47, 29, &lt;span class="nt"&gt;-63&lt;/span&gt;, 36, 12, 53, &lt;span class="nt"&gt;-86&lt;/span&gt;, 84, 57, &lt;span class="nt"&gt;-125&lt;/span&gt;, 16, 43, &lt;span class="nt"&gt;-18&lt;/span&gt;, 93, 56, 9], &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696186, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'wfVdpi8dwSQMNapUOYMQK+5dOAk='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.258 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="nt"&gt;-23&lt;/span&gt;, 101, &lt;span class="nt"&gt;-114&lt;/span&gt;, &lt;span class="nt"&gt;-87&lt;/span&gt;, &lt;span class="nt"&gt;-52&lt;/span&gt;, 107, 36, 113, 101, 33, &lt;span class="nt"&gt;-16&lt;/span&gt;, 82, &lt;span class="nt"&gt;-95&lt;/span&gt;, 97, 34, &lt;span class="nt"&gt;-121&lt;/span&gt;, 82, &lt;span class="nt"&gt;-97&lt;/span&gt;, 40, 59], &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696145, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'6WWOqcxrJHFlIfBSoWEih1KfKDs='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.258 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="nt"&gt;-77&lt;/span&gt;, &lt;span class="nt"&gt;-118&lt;/span&gt;, 49, 4, &lt;span class="nt"&gt;-75&lt;/span&gt;, 123, 81, 2, &lt;span class="nt"&gt;-103&lt;/span&gt;, &lt;span class="nt"&gt;-73&lt;/span&gt;, 42, &lt;span class="nt"&gt;-70&lt;/span&gt;, &lt;span class="nt"&gt;-54&lt;/span&gt;, 95, 98, 23, 73, 66, &lt;span class="nt"&gt;-86&lt;/span&gt;, 7], &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696230, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'s4oxBLV7UQKZtyq6yl9iF0lCqgc='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.258 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;50, &lt;span class="nt"&gt;-38&lt;/span&gt;, &lt;span class="nt"&gt;-31&lt;/span&gt;, &lt;span class="nt"&gt;-54&lt;/span&gt;, &lt;span class="nt"&gt;-122&lt;/span&gt;, &lt;span class="nt"&gt;-113&lt;/span&gt;, &lt;span class="nt"&gt;-38&lt;/span&gt;, 88, 15, 7, 96, 51, &lt;span class="nt"&gt;-92&lt;/span&gt;, &lt;span class="nt"&gt;-25&lt;/span&gt;, 60, &lt;span class="nt"&gt;-104&lt;/span&gt;, 26, 113, &lt;span class="nt"&gt;-117&lt;/span&gt;, &lt;span class="nt"&gt;-82&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696157, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'MtrhyoaP2lgPB2AzpOc8mBpxi64='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.258 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="nt"&gt;-77&lt;/span&gt;, 31, 67, &lt;span class="nt"&gt;-18&lt;/span&gt;, &lt;span class="nt"&gt;-52&lt;/span&gt;, &lt;span class="nt"&gt;-114&lt;/span&gt;, 42, &lt;span class="nt"&gt;-18&lt;/span&gt;, 36, &lt;span class="nt"&gt;-111&lt;/span&gt;, 89, 62, 109, 114, &lt;span class="nt"&gt;-54&lt;/span&gt;, 54, &lt;span class="nt"&gt;-121&lt;/span&gt;, &lt;span class="nt"&gt;-110&lt;/span&gt;, &lt;span class="nt"&gt;-88&lt;/span&gt;, &lt;span class="nt"&gt;-108&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696206, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'sx9D7syOKu4kkVk+bXLKNoeSqJQ='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.258 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;73, 11, 98, &lt;span class="nt"&gt;-50&lt;/span&gt;, 32, 12, 0, &lt;span class="nt"&gt;-50&lt;/span&gt;, 22, &lt;span class="nt"&gt;-101&lt;/span&gt;, &lt;span class="nt"&gt;-108&lt;/span&gt;, 18, 38, 7, &lt;span class="nt"&gt;-65&lt;/span&gt;, 6, &lt;span class="nt"&gt;-58&lt;/span&gt;, 60, &lt;span class="nt"&gt;-6&lt;/span&gt;, &lt;span class="nt"&gt;-33&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696171, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'SQtiziAMAM4Wm5QSJge/BsY8+t8='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
2022-12-08 18:21:36.258 GMT DEBUG record-parser - parsed message fields: &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Key&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;, &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;testset, &lt;span class="nv"&gt;digest&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;109, &lt;span class="nt"&gt;-82&lt;/span&gt;, 24, 53, 35, 89, &lt;span class="nt"&gt;-72&lt;/span&gt;, &lt;span class="nt"&gt;-117&lt;/span&gt;, &lt;span class="nt"&gt;-22&lt;/span&gt;, 79, 119, &lt;span class="nt"&gt;-89&lt;/span&gt;, 56, &lt;span class="nt"&gt;-5&lt;/span&gt;, 0, &lt;span class="nt"&gt;-103&lt;/span&gt;, &lt;span class="nt"&gt;-54&lt;/span&gt;, 51, 25, 126], &lt;span class="nv"&gt;userKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;lastUpdateTimeMs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1670523696146, &lt;span class="nv"&gt;userKeyString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;null, &lt;span class="nv"&gt;digestString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ba4YNSNZuIvqT3enOPsAmcozGX4='&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Achieve dependable resiliency with Aerospike
&lt;/h2&gt;

&lt;p&gt;Aerospike's XDR feature provides a reliable solution for mitigating the risk of cluster unavailability. By asynchronously replicating data between data centers, users can ensure availability. This step-by-step walkthrough demonstrates how to accomplish this seamlessly in a Kubernetes environment using the xdr-proxy. With the Aerospike Kubernetes Operator, you can effortlessly avoid network complications and achieve optimal performance with minimal effort.&lt;/p&gt;

&lt;p&gt;Share your experience! Your feedback is important to us. &lt;a href="https://discord.com/invite/NfC93wJEJU" rel="noopener noreferrer"&gt;Join our Aerospike community&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>k8s</category>
      <category>kubernetes</category>
      <category>xdr</category>
    </item>
    <item>
      <title>Using auto-values in Aerospike LINQPad driver</title>
      <dc:creator>Richard Andersen</dc:creator>
      <pubDate>Thu, 08 Feb 2024 20:03:53 +0000</pubDate>
      <link>https://forem.com/aerospike/using-auto-values-in-aerospike-linqpad-driver-143h</link>
      <guid>https://forem.com/aerospike/using-auto-values-in-aerospike-linqpad-driver-143h</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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Fusing-auto-values-in-aerospike-linqpad-driver-blog_1707410347927.webp" 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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2Fusing-auto-values-in-aerospike-linqpad-driver-blog_1707410347927.webp"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When working with NoSQL databases like Aerospike, which are designed for unstructured data storage, adopting strongly typed languages like C# may introduce programming complexities. These can stem from verifying the presence of "bins" (akin to columns) within a record and bin data types that can change between records.&lt;/p&gt;

&lt;p&gt;Auto-Values (&lt;code&gt;AValue&lt;/code&gt; is the class) simplify the need to check, cast, or convert values between Aerospike data types and .NET data types. They provide a rich set of operations and seamlessly work with any type of data, including collections and JSON. They provide protection against null reference exceptions, invalid cast exceptions, conversion exceptions, etc.&lt;br&gt;
To explore the &lt;a href="https://www.linqpad.net" rel="noopener noreferrer"&gt;LINQPad&lt;/a&gt; or the &lt;a href="https://aerospike.com/developer/blog/aerospike-for-linqpad" rel="noopener noreferrer"&gt;Aerospike LINQPad driver&lt;/a&gt; in more detail, kindly click on the respective links provided.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example set
&lt;/h2&gt;

&lt;p&gt;The following illustrates an Aerospike set where different records have a varied number of bins, and bins in the record set can have varying data types (e.g., bin &lt;code&gt;BinA&lt;/code&gt; can be a &lt;code&gt;double&lt;/code&gt;, &lt;code&gt;long&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, or &lt;code&gt;list&lt;/code&gt; in different records).&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-demo-types-display_1707410345724.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-demo-types-display_1707410345724.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Display of the &lt;code&gt;DemoTypes&lt;/code&gt; set&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Note that the LINQPad connection tree (left side) is expanded, illustrating the bins for the set &lt;code&gt;DemoTypes&lt;/code&gt;. Under the set name, each bin is listed, displaying its associated data type. Take note of the symbols after the data type. A &lt;code&gt;*&lt;/code&gt; indicates this bin has different data types between records. A &lt;code&gt;?&lt;/code&gt; indicates this bin wasn’t present in some of the records within this set. These symbols provide a quick view of the set and expected values. &lt;br&gt;
In the &lt;strong&gt;Results&lt;/strong&gt; pane (bottom-right), bins with &lt;code&gt;null&lt;/code&gt; are not present in that record.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple cast examples
&lt;/h2&gt;

&lt;p&gt;Below are examples that illustrate the difference between using Aerospike data types, C# data types, and Auto-Values.&lt;br&gt;
Let’s begin with an example where  Auto-Values are &lt;strong&gt;not&lt;/strong&gt; used:&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-data-type-casting_1707410345018.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-data-type-casting_1707410345018.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Shows that casting to the proper data type is required&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Notice that there are no results from the query, even though it should have matched one record. The reason it failed is because “456” is an &lt;code&gt;Int32&lt;/code&gt;, and the DB numeric values are &lt;code&gt;Int64&lt;/code&gt;. So, “456” needs to be cast to &lt;code&gt;Int64&lt;/code&gt; (long). Also, we need to check to make sure the bin is present in all records; otherwise, a null exception is thrown. &lt;/p&gt;

&lt;p&gt;Below is an example showing these changes:&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520%2520LINQPad%2520Driver-updated-query-using-required-cast_1707410344508.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520%2520LINQPad%2520Driver-updated-query-using-required-cast_1707410344508.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Updated query using required cast&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s look at the same query using Auto-Values:&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-no-required-testing-or-casting_1707410346940.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-no-required-testing-or-casting_1707410346940.png"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Using Auto-Values doesn’t require testing or casting&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the given example, you do not have to verify the existence of the bin or explicitly cast "456" to a long data type.&lt;br&gt;
Auto-Values take care of not only casting but also converting. Conversion between any of the .NET primitive types to or from any Aerospike data types is seamless. It also handles nullable values, JSON objects, and &lt;a href="https://aerospike.com/developer/tutorials/cdt" rel="noopener noreferrer"&gt;collection data types (CDT)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Auto-Values support all standard operations like &lt;code&gt;==&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, etc. They also support all the equality and comparison operations.&lt;/p&gt;

&lt;p&gt;Below are some additional examples:&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-updated-query-using-required-cast-queries-with-different-auto-value-uses_1707410347730.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-updated-query-using-required-cast-queries-with-different-auto-value-uses_1707410347730.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-different-auto-value-uses_1707410346197.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-different-auto-value-uses_1707410346197.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Queries above show different uses of Auto-Values&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling unsupported data types
&lt;/h2&gt;

&lt;p&gt;Aerospike supports a limited set of &lt;a href="https://aerospike.com/docs/server/guide/data-types/scalar-data-types" rel="noopener noreferrer"&gt;data types&lt;/a&gt;. They include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;String&lt;/li&gt;
&lt;li&gt;Integer (Int64)&lt;/li&gt;
&lt;li&gt;Double&lt;/li&gt;
&lt;li&gt;Boolean&lt;/li&gt;
&lt;li&gt;Blob/Bytes (byte[])&lt;/li&gt;
&lt;li&gt;List&lt;/li&gt;
&lt;li&gt;Map (Directory)&lt;/li&gt;
&lt;li&gt;Geospatial (&lt;a href="https://github.com/GeoJSON-Net/GeoJSON.Net" rel="noopener noreferrer"&gt;GeoJSON.NET&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The driver has extended support by allowing the following .NET data types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DateTime&lt;/code&gt;, &lt;code&gt;DateTimeOffset&lt;/code&gt;, &lt;code&gt;TimeSpan&lt;/code&gt;: These values are mapped to either an Aerospike string or long data types depending on the connection or API configuration. Auto-Values will automatically take care of these conversions to or from the database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;JSON&lt;/code&gt;: These values are mapped to an Aerospike &lt;a href="https://aerospike.com/docs/server/guide/data-types/cdt-map" rel="noopener noreferrer"&gt;&lt;code&gt;Map&lt;/code&gt; data type&lt;/a&gt; where the JSON property name is the key in the Map, and the JSON value is the Map value. JSON arrays are mapped to Aerospike “List.” Nested JSON structures are completely supported, and the driver takes care of all conversions to or from the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below are examples where  .NET DateTimeOffset, DateTime, and TimeSpan instances are used to obtain matching records. The values stored in the Aerospike database are either strings or an Int64 value (number of nanoseconds from Unix Epoch). The driver will manage the conversion between these different types.&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-datetime-datetimeoffset-timespan_1707410345257.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-datetime-datetimeoffset-timespan_1707410345257.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Queries using .NET DateTime, DateTimeOffset, and Timespan&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By the way, you can control how values are converted and displayed through the properties located in the "Display/Conversion Options" section of the connection dialog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conversion
&lt;/h2&gt;

&lt;p&gt;Auto-Values provide a rich set of conversion functions, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Convert&amp;lt;T&amp;gt;&lt;/code&gt; - Will try to convert to the provided .NET data type. If it cannot, an invalid cast exception is thrown.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Is{data type}&lt;/code&gt; – Use to test if the underlying .NET data type is that {date type}. Examples of these functions are: IsList, IsCDT, IsJSON, IsInt16, IsNumeric, IsString, etc.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;To{data type}&lt;/code&gt; – Will try to convert to the .NET {data type}, if possible. Note {data type} can be Dictionary, List, .NET native type, etc. Examples of these functions are: ToList, ToBoolean, ToByte, etc.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TryGetValue&amp;lt;T&amp;gt;&lt;/code&gt; – This will try to match a provided value and convert the value into the provided .NET data type. If not successful, the default value of that data type and/or false is returned, depending on usage. This function can be applied against CDTs or non-CDT values.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TryGetValue&lt;/code&gt; – This will try to match the provided value. If successful, the matched value is returned as an Auto-Value. If not, an empty Auto-Value, false, or null can be returned depending on usage. This function can be applied against CDTs or non-CDT values.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AsEnumerable&lt;/code&gt; – This will convert an Auto-Value into an enumerable object if it is a database CDT. If not a CDT, an empty enumeration is returned. All elements in the CDT are scanned and converted into Auto-Values. This will provide the highest level of protection against invalid casts or null value reference exceptions. This also allows for using the advanced Auto-Value functions outlined in the Collection Data Types section.&lt;/li&gt;
&lt;li&gt;Implicit Casting – Auto-Values know how to implicitly cast from an Aerospike data type to any .NET primary type without explicitly providing the type.
Detailed documentation can be found through  IntelliSense or by reviewing the function’s respective documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Collection data types
&lt;/h2&gt;

&lt;p&gt;Auto-Values can seamlessly be used to find elements within CDTs. These functions are based on standard C# methods. Examples of these operations are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Contains&lt;/code&gt; – Returns true if the matching value is contained in a bin’s value or an element within a CDT. The matching options determine how the matches occur.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FindAll&lt;/code&gt; – Returns a collection of matching Auto-Values. A match can occur as a bin’s value or an element within a CDT. The matching options determine how the matches occur. If no matches are found, an empty enumerable is returned.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TryGetValue&lt;/code&gt; – Returns the first matching value (as an Auto-Value) contained in a bin’s value or an element within a CDT. If the Auto-Value is not found, an Empty Auto-Value is returned.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OfType&amp;lt;T&amp;gt;&lt;/code&gt; - Tries to cast the Auto-Value to the provided .NET type, creating a new collection of those types. If a value cannot be cast, it will be ignored.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cast&amp;lt;T&amp;gt;&lt;/code&gt; -- Will cast the Auto-Value to the provided .NET type. If it cannot be cast, an invalid cast exception will occur.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Convert&amp;lt;T&amp;gt;&lt;/code&gt; - Will try to convert the Auto-Value, resulting in a collection of converted .NET values. If an Auto-Value cannot be converted, it will be ignored.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below are some examples using “Contains” and “FindAll” methods:&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-queries-using-contains-and-findall-methods-_1707410347068.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-queries-using-contains-and-findall-methods-_1707410347068.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Queries using the Contains and FindAll methods&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can find additional examples in the &lt;a href="https://github.com/aerospike-community/aerospike-linqpad-driver/tree/main/linqpad-samples/Cloud" rel="noopener noreferrer"&gt;LINQPad sample folder&lt;/a&gt;.&lt;br&gt;
Below is an example of “drilling” into several different sub-collections using LINQ. This example finds all invoices for a certain song track, resulting in a collection of customers. This example is located in the &lt;a href="https://github.com/aerospike-community/aerospike-linqpad-driver/blob/main/linqpad-samples/Native/CDT-Json-Docs.linq" rel="noopener noreferrer"&gt;CDT-Json-Docs&lt;/a&gt; sample LINQPad script.&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-linq-query_1707410346440.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-linq-query_1707410346440.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;LINQ Query&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Primary key
&lt;/h2&gt;

&lt;p&gt;Auto-Values also extend to primary keys. They have the same features as found in the Bin Auto-Values. There are a few additional features, such as digest values.&lt;br&gt;
If the primary key value is not saved (only the digest is used), matching to a value can still occur using Auto-Values.&lt;br&gt;
Below is an example where the digest is only available; note that the actual value must be used.&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-string-value-database-ingest_1707410347582.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Frichard-andersen%2FUsing%2520Auto-Values%2520in%2520Aerospike%2520LINQPad%2520Driver-string-value-database-ingest_1707410347582.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Query using a string value by means of the database digest&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  LINQPad driver samples
&lt;/h2&gt;

&lt;p&gt;You can find samples for the &lt;a href="https://github.com/aerospike-community/aerospike-linqpad-driver" rel="noopener noreferrer"&gt;Aerospike LINQPad driver&lt;/a&gt; in the &lt;a href="https://github.com/aerospike-community/aerospike-linqpad-driver/tree/main/linqpad-samples/Cloud" rel="noopener noreferrer"&gt;samples folder&lt;/a&gt; or under the “Samples” tab in &lt;a href="https://www.linqpad.net/nugetsamples.aspx" rel="noopener noreferrer"&gt;LINQPad&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>linq</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Using AWS IAM for client authentication</title>
      <dc:creator>Naresh Maharaj</dc:creator>
      <pubDate>Wed, 20 Dec 2023 20:11:36 +0000</pubDate>
      <link>https://forem.com/aerospike/using-aws-iam-for-client-authentication-47nf</link>
      <guid>https://forem.com/aerospike/using-aws-iam-for-client-authentication-47nf</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fnaresh-maharaj%2Fmsk%2Flearn-how-to-use-aws-iam-to-authenticate-clients-aerospike-blog.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fnaresh-maharaj%2Fmsk%2Flearn-how-to-use-aws-iam-to-authenticate-clients-aerospike-blog.webp" alt="heroimg" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this blog post, we detail how to create an Amazon Managed Streaming for Apache Kafka (Amazon MSK) resource using &lt;a href="https://aws.amazon.com/iam/getting-started/" rel="noopener noreferrer"&gt;AWS Identity and Access Management&lt;/a&gt; (AWS IAM) in roles and policies to authenticate user access. In the initial step, we establish an &lt;a href="https://aerospike.com/developer/blog/improving-in-memory-performance-aerospike-database-7" rel="noopener noreferrer"&gt;Aerospike Database&lt;/a&gt; cluster and insert sample messages into the database. Subsequently, we observe in real time how these messages are streamed to Amazon MSK using Aerospike's Kafka Source Connector. &amp;lt;!--truncate--&amp;gt;Below we provide a comprehensive, step-by-step guide for users to successfully implement this process.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  AWS MKS Kafka
&lt;/h2&gt;

&lt;p&gt;In this section, you will set up a simple three-node Kafka cluster. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visit the AWS console and select &lt;strong&gt;MSK service&lt;/strong&gt;. &lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Create a new cluster by selecting &lt;strong&gt;Create Cluster&lt;/strong&gt; → &lt;strong&gt;Quick Create&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Select the provisioned cluster and instance type of kafka.t3.small.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Select the EBS storage type per broker of 10 GB.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: Take note of the VPC, subnets, and security group ID, as you will require these details later in the article.&lt;/p&gt;

&lt;p&gt;The next step is the critical step where you will create the AWS IAM policy and roles. This setup ensures that the Aerospike Database authenticates using AWS IAM to write data to MSK.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;From the AWS Console, select the AWS IAM service.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;To create a new AWS IAM policy, copy the following JSON and paste it in the JSON tab. Replace &lt;code&gt;region:Account-ID&lt;/code&gt; with your own region and AWS account ID.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Save the policy and name it msk-tutorial-policy.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kafka-cluster:Connect",
                "kafka-cluster:AlterCluster",
                "kafka-cluster:DescribeCluster"
            ],
            "Resource": [
                "arn:aws:kafka:region:Account-ID:cluster/MSKTutorialCluster/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "kafka-cluster:*Topic*",
                "kafka-cluster:WriteData",
                "kafka-cluster:ReadData"
            ],
            "Resource": [
                "arn:aws:kafka:region:Account-ID:topic/MSKTutorialCluster/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "kafka-cluster:AlterGroup",
                "kafka-cluster:DescribeGroup"
            ],
            "Resource": [
                "arn:aws:kafka:region:Account-ID:group/MSKTutorialCluster/*"
            ]
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create the IAM role.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Under &lt;strong&gt;Common Use Cases&lt;/strong&gt;, select &lt;strong&gt;EC2&lt;/strong&gt; and then &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Under &lt;strong&gt;Permissions&lt;/strong&gt;, select the policy named &lt;strong&gt;msk-tutorial-policy&lt;/strong&gt; and then &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Give the role a name like &lt;strong&gt;msk-tutorial-role&lt;/strong&gt; and click the &lt;strong&gt;Create Role&lt;/strong&gt; button.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Kafka client machine
&lt;/h2&gt;

&lt;p&gt;Next, create a client machine to install the Kafka tools necessary to access our MSK cluster.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new ec2 instance using type &lt;code&gt;t2.micro&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Use the default AMI: &lt;code&gt;Amazon Linux 2023&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F002nbnvqt0txvcs98iiy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F002nbnvqt0txvcs98iiy.png" alt="image" width="800" height="515"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The AMI may be different depending on your region&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a key-pair if required. I am using an already existing key-pair.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Under &lt;strong&gt;Advanced Options.IAM instance profile&lt;/strong&gt;, select the IAM role created earlier.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Launch the instance!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under instances launched, choose the instance you just created. Click on the ‘Security’ tab and note the security group associated with this instance.&lt;br&gt;
e.g., &lt;code&gt;sg-0914e6271c97ae4c9 (launch-wizard-1)&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Navigate to the &lt;a href="https://console.aws.amazon.com/vpc/" rel="noopener noreferrer"&gt;VPC section&lt;/a&gt; and select &lt;strong&gt;Security Groups&lt;/strong&gt; from the left-hand menu. Locate the security group associated with the MSK cluster, such as &lt;code&gt;sg-e5f51dfb&lt;/code&gt;, and choose &lt;strong&gt;Edit Inbound Rules&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new rule to allow all traffic from the new ec2 instance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmh3x19wme2u6p8gldrf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmh3x19wme2u6p8gldrf.png" alt="image" width="800" height="62"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Kafka topics
&lt;/h2&gt;

&lt;p&gt;After successfully establishing your initial Kafka cluster and Kafka client machine, proceed to conduct testing. Verify the functionality by accessing the MSK cluster, creating a topic, producing and consuming sample messages, and ensuring that everything operates as anticipated.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;From the MSK Cluster, note the Kafka version being used. This examples uses 2.8.1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From the Kafka client machine, install Java 11+.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;java-11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Download Apache Kafka using wget, then extract the archive using tar.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://archive.apache.org/dist/kafka/2.8.1/kafka_2.12-2.8.1.tgz
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; kafka_2.12-2.8.1.tgz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;To use IAM, you will need the MSK IAM Auth jar file. Download the jar to the Kafka libs folder you just extracted.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;kafka_2.12-2.8.1/libs/
wget https://github.com/aws/aws-msk-iam-auth/releases/download/v1.1.1/aws-msk-iam-auth-1.1.1-all.jar
&lt;span class="nb"&gt;cd&lt;/span&gt; ../bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Create a file called client.properties to use when authenticating to MSK. It will define the SASL mechanism to use and reference the Java class file that will handle your IAM callbacks.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;&amp;gt; client.properties
security.protocol=SASL_SSL
sasl.mechanism=AWS_MSK_IAM
sasl.jaas.config=software.amazon.msk.auth.iam.IAMLoginModule required;
sasl.client.callback.handler.class=software.amazon.msk.auth.iam.IAMClientCallbackHandler
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Creating topics
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to the AWS Console and view the MSK Cluster Client Information. There will be three endpoints to choose from, but you only require one.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example choose:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;B-2.msktutorialcluster.450050.c11.kafka.us-east-1.amazonaws.com:9098&lt;/code&gt;&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;From the &lt;code&gt;kafka/bin&lt;/code&gt; folder, run the command to create a topic. Let's call it &lt;code&gt;aerospike-airforce-1&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BootstrapServerString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"b-2.msktutorialcluster.450050.c11.kafka.us-east-1.amazonaws.com:9098"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./kafka-topics.sh &lt;span class="nt"&gt;--create&lt;/span&gt; &lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; &lt;span class="nv"&gt;$BootstrapServerString&lt;/span&gt; &lt;span class="nt"&gt;--command-config&lt;/span&gt; client.properties &lt;span class="nt"&gt;--replication-factor&lt;/span&gt; 3 &lt;span class="nt"&gt;--partitions&lt;/span&gt; 1 &lt;span class="nt"&gt;--topic&lt;/span&gt; aerospike-airforce-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Listing topics
&lt;/h2&gt;

&lt;p&gt;To list the topics, use the following command. Notice our latest topic, called aerospike-airforce-1, just showed up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./kafka-topics.sh &lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; &lt;span class="nv"&gt;$BootstrapServerString&lt;/span&gt; &lt;span class="nt"&gt;--command-config&lt;/span&gt; client.properties &lt;span class="nt"&gt;--list&lt;/span&gt;

MSKTutorialTopic
__amazon_msk_canary
__consumer_offsets
aerospike
aerospike-airforce-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Producer and consumer
&lt;/h2&gt;

&lt;p&gt;I agree that this is more of a Kafka-101 rather than a straightforward Hello-World scenario. Nonetheless, it is essential to test our configuration by sending and receiving messages from the designated Kafka topic before proceeding further.&lt;/p&gt;

&lt;p&gt;Produce some messages by opening a new window and running the following Kafka producer command. Type three or four messages, hitting the 'Return' key after each message&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./kafka-console-producer.sh &lt;span class="nt"&gt;--broker-list&lt;/span&gt; &lt;span class="nv"&gt;$BootstrapServerString&lt;/span&gt; &lt;span class="nt"&gt;--producer&lt;/span&gt;.config client.properties &lt;span class="nt"&gt;--topic&lt;/span&gt; aerospike-airforce-1
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;Instrument Check
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;Pre flight checks confirmed
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;Ready &lt;span class="k"&gt;for &lt;/span&gt;takeoff
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;Full throttle, flaps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're now ready to start a client consumer application. Open a new window and run the consumer. You should now see the same messages you published earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./kafka-console-consumer.sh &lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; &lt;span class="nv"&gt;$BootstrapServerString&lt;/span&gt; &lt;span class="nt"&gt;--consumer&lt;/span&gt;.config client.properties &lt;span class="nt"&gt;--topic&lt;/span&gt; aerospike-airforce-1 &lt;span class="nt"&gt;--from-beginning&lt;/span&gt;
Instrument Check
Pre flight checks confirmed
Ready &lt;span class="k"&gt;for &lt;/span&gt;takeoff
Full throttle, flaps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Database source
&lt;/h2&gt;

&lt;p&gt;Let's review your achievements thus far. You've established a 3-node Kafka cluster in AWS utilizing MSK, incorporating IAM roles and permissions. Additionally, you have successfully created topics and demonstrated the production and consumption of messages using the IAM credentials established during the setup.&lt;/p&gt;

&lt;p&gt;The next phase of your journey involves installing the Aerospike Database, inserting messages, and configuring a simple XDR component. XDR is a Cross Datacenter Replication tool and is crucial for transmitting data from the Aerospike Database to the Aerospike Kafka Source Connector allowing us to subsequently forward messages to Amazon MSK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the Aerospike Database
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Start by creating a new ec2 instance. For this demo, you can use Linux Centos 8&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Rocky 8 AMI: ami-043ceee68871e0bb5 ( us-east-1 )&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr4iw9ejogzrfi3crskt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr4iw9ejogzrfi3crskt.png" alt="image" width="448" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select the instance type as &lt;code&gt;t2.medium&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdylf351ft9ivfjbzamed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdylf351ft9ivfjbzamed.png" alt="image" width="764" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add the extra volume for the Aerospike data storage layer. EBS volume is all that is required for now.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhm22ywwvlg4g798t99x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhm22ywwvlg4g798t99x.png" alt="image" width="768" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Launch the instance and connect to the host using ssh. If you have an Aerospike license feature file, upload it to the instance.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Install the Aerospike Database server
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Run the following to install the Aerospike Database Server.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"6.1.0.2"&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;java python3 openssl-devel wget git gcc maven bind-utils sysstat nc &lt;span class="nt"&gt;-y&lt;/span&gt;
wget &lt;span class="nt"&gt;-O&lt;/span&gt; aerospike-tools.tgz &lt;span class="s1"&gt;'https://www.aerospike.com/download/tools/latest/artifact/el8'&lt;/span&gt;
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xvf&lt;/span&gt; aerospike-tools.tgz
&lt;span class="nb"&gt;cd &lt;/span&gt;aerospike-tools_&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./dep-check
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./asinstall
wget &lt;span class="nt"&gt;-O&lt;/span&gt; aerospike.tgz https://enterprise.aerospike.com/enterprise/download/server/&lt;span class="nv"&gt;$VER&lt;/span&gt;/artifact/el8
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xvf&lt;/span&gt; aerospike.tgz
&lt;span class="nb"&gt;cd &lt;/span&gt;aerospike-server-enterprise-&lt;span class="nv"&gt;$VER&lt;/span&gt;&lt;span class="nt"&gt;-el8&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./asinstall
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/log/aerospike/
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;aerospike
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Confirm the storage disk for Aerospike.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsblk
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  10G  0 disk
└─xvda1 202:1    0  10G  0 part /
xvdb    202:16   0  10G  0 disk   &amp;lt;&amp;lt;&lt;span class="nt"&gt;-----------------&lt;/span&gt; This one!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;When its data is available, replace the Aerospike configuration file under /etc/aerospike/aerospike.conf with the configuration file listed below, also replacing the following lines:

&lt;ul&gt;
&lt;li&gt;Under &lt;code&gt;heartbeat.address&lt;/code&gt; add in your internal 172.x.x.x address&lt;/li&gt;
&lt;li&gt;For &lt;code&gt;xdr.dc.node-address-port&lt;/code&gt; enter the {kafka-client-machine-address}:8080&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Aerospike Database configuration file for use with &lt;code&gt;systemd&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;service {
  # paxos-single-replica-limit 1 # Number of nodes where the replica count is automatically
  proto-fd-max 15000
  service-threads 10
  feature-key-file /etc/aerospike/features.conf
  node-id A1
  cluster-name CLA
}

logging {
  file /var/log/aerospike/aerospike.log {
    context any info
  }
}

# public and private addresses
network {
  service {
    address any
    port 3000
  }

  heartbeat {
    mode mesh
    address 172.31.94.201
    port 3002 # Heartbeat port for this node.
    interval 150 # controls how often to send a heartbeat packet
    timeout 10 # number of intervals after which a node is considered to be missing
  }

  fabric {
    port 3001
  }

  info {
    port 3003
  }
}

namespace test {
  replication-factor 2
  memory-size 40G
  default-ttl 0
  index-type shmem
  high-water-disk-pct 50
  high-water-memory-pct 60
  stop-writes-pct 90
  nsup-period 0

  storage-engine device {
    device /dev/xvdb
    data-in-memory false
    write-block-size 128K
    min-avail-pct 5
  }
}

xdr {
  # Change notification XDR block that round-robins between two connector nodes
  dc aerospike-kafka-source {
    connector true
    node-address-port 172.31.58.190 8080
    namespace test {
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Start the Aerospike service
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Copy the license feature file to the aerospike configuration directory.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo cp &lt;/span&gt;features.conf /etc/aerospike/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start the Aerospike server and check the logs to ensure there are no errors.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start aerospike
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status aerospike
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Aerospike Kafka Source Connector
&lt;/h2&gt;

&lt;p&gt;The seamless flow of data from Aerospike Database Enterprise Edition to Apache Kafka hinges on the utilization of the Aerospike Kafka source (outbound) connector. This connector subscribes to change notifications. Upon receiving these notifications, the connector converts them into messages, which are dispatched to Kafka topics. Going back to the ec2 instance you created earlier with our Kafka client configured, go ahead and &lt;a href="https://docs.aerospike.com/connect/kafka/from-asdb/installing#installing-on-linux" rel="noopener noreferrer"&gt;install&lt;/a&gt; the &lt;a href="https://aerospike.com/resources/solution-brief/kafka-connector-data-streams/" rel="noopener noreferrer"&gt;Aerospike Kafka Source Connector&lt;/a&gt;. This is your outbound connector to send data from the Aerospike to MSK.&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;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;java &lt;span class="c"&gt;#( install 11+ JDK )&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://enterprise.aerospike.com/artifacts/enterprise/aerospike-kafka-outbound/5.0.1/aerospike-kafka-outbound-5.0.1-1.noarch.rpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;rpm &lt;span class="nt"&gt;-i&lt;/span&gt; aerospike-kafka-outbound-5.0.0-1.noarch.rpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure the outbound connector
&lt;/h2&gt;

&lt;p&gt;The terms “outbound” and “source connector” are used interchangeably in this article.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Locate the following file on the Kafka client box: &lt;code&gt;/etc/aerospike-kafka-outbound/aerospike-kafka-outbound.yml&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replace the broker address for one of the node addresses in the MSK Kafka cluster &lt;code&gt;producer-props.bootstrap.servers&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then add the following contents to the file with the changes that have been outlined.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Change the configuration for your use case.
#
# Refer to https://www.aerospike.com/docs/connectors/enterprise/kafka/outbound/configuration/index.html
# for details.

# The connector's listening ports, TLS, and network interface.
service:
  port: 8080

# Format of the Kafka destination message.
format:
  mode: flat-json
  metadata-key: metadata

# Aerospike record routing to a Kafka destination.
routing:
  mode: static
  destination: aerospike

# Kafka producer initialization properties.
producer-props:
  bootstrap.servers:
    - b-3.msktutorialcluster.450050.c11.kafka.us-east-1.amazonaws.com:9098
  ssl.truststore.location: /etc/aerospike-kafka-outbound/kafka.client.truststore.jks
  ssl.truststore.password: changeit
  security.protocol: SASL_SSL
  sasl.mechanism: AWS_MSK_IAM
  sasl.jaas.config: software.amazon.msk.auth.iam.IAMLoginModule required awsProfileName=default;
  sasl.client.callback.handler.class: software.amazon.msk.auth.iam.IAMClientCallbackHandler

# The logging properties.
logging:
  file: /var/log/aerospike-kafka-outbound/aerospike-kafka-outbound.log
  enable-console-logging: true
  levels:
    root: debug
    record-parser: debug
    server: debug
    com.aerospike.connect: debug
  ticker-interval: 3600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create the CA certificate trust store for use in the Kafka Outbound Connector config. You can see the SSL trust store location referenced in the file above as &lt;code&gt;ssl.truststore.location&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; /usr/lib/jvm/java-11-amazon-corretto/lib/security/cacerts /etc/aerospike-kafka-outbound/kafka.client.truststore.jks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;755 /etc/aerospike-kafka-outbound/kafka.client.truststore.jks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Finally,  make the AWS IAM Kafka Auth Jar file available to the Aerospike Outbound Kafka Connector. This is the same jar file that you downloaded and added to the kafka/libs folder.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo cp &lt;/span&gt;kafka_2.12-2.8.1/libs/aws-msk-iam-auth-1.1.1-all.jar /opt/aerospike-kafka-outbound/lib/aws-msk-iam-auth-1.1.1-all.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start the service.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;aerospike-kafka-outbound
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start aerospike-kafka-outbound
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Send data from Aerospike to Kafka
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open a separate window so you can list all messages on the Aerospike Kafka topic. Start by adding one of the private endpoint bootstrap servers as an environment variable for ease of use.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BootstrapServerString&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"b-3.msktutorialcluster.450050.c11.kafka.us-east-1.amazonaws.com:9098"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run the consumer client as follows:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./kafka-console-consumer.sh &lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; &lt;span class="nv"&gt;$BootstrapServerString&lt;/span&gt; &lt;span class="nt"&gt;--consumer&lt;/span&gt;.config client.properties &lt;span class="nt"&gt;--topic&lt;/span&gt; aerospike &lt;span class="nt"&gt;--from-beginning&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;In a new window, start &lt;a href="https://aerospike.com/docs/tools/aql" rel="noopener noreferrer"&gt;AQL&lt;/a&gt;, the Aerospike command line client which connects to your Aerospike Database.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;aql&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;U&lt;/span&gt; &lt;span class="n"&gt;auser&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Insert some data
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&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;pk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"Your winning lottery ticket awaits you"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Check to see if the message appears in the Kafka consumer window
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"metadata":{"namespace":"test","userKey":400,"digest":"W7eGav2hKfOU00xx7mnOPYa2uCo=","msg":"write","gen":1,"lut":1681488437767,"exp":0},"a":"Your winning lottery ticket awaits you"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You've just discovered how straightforward it is to transmit data from Aerospike to AWS MSK Kafka while ensuring client authentication through AWS IAM permissions! From establishing an Aerospike Database from scratch to configuring the AWS MSK Kafka cluster and employing the Aerospike Outbound Kafka Connector, you've effortlessly constructed a real-time streaming data pipeline. Congratulations on this accomplishment!&lt;/p&gt;

&lt;p&gt;Share your experience! Your feedback is important to us. &lt;a href="https://discord.com/invite/NfC93wJEJU" rel="noopener noreferrer"&gt;Join our Aerospike community&lt;/a&gt;! &lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>iam</category>
      <category>kafka</category>
      <category>java</category>
    </item>
    <item>
      <title>A developer’s introduction to graph databases</title>
      <dc:creator>Alex Infanzon</dc:creator>
      <pubDate>Thu, 30 Nov 2023 02:31:18 +0000</pubDate>
      <link>https://forem.com/aerospike/a-developers-introduction-to-graph-databases-clb</link>
      <guid>https://forem.com/aerospike/a-developers-introduction-to-graph-databases-clb</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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fdevelopers-introduction-to-graph-databases-aerospike-blog.webp" 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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fdevelopers-introduction-to-graph-databases-aerospike-blog.webp" alt="heroimg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Get ready to deploy a real-world dataset on Aerospike Graph and execute queries in just a few minutes.&lt;/p&gt;

&lt;p&gt;Ready to dive into new realms of graph technology and discover fascinating insights with each click? Whether you're a curious beginner or a seasoned graph explorer searching for fresh perspectives, this blog is meant for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aerospike Graph at a glance
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://aerospike.com/products/graph-database/" rel="noopener noreferrer"&gt;Aerospike Graph&lt;/a&gt; leverages Apache TinkerPop, an open-source graph computing framework, and Gremlin, a graph traversal language. In other words, Gremlin is a query language, like SQL, for traversing and manipulating graph-structured data. Using Gremlin, you can explore specific graph traversal sequences known as traversals. Our post, &lt;a href="https://aerospike.com/blog/business/graph-data-visualization-with-gv/" rel="noopener noreferrer"&gt;Aerospike and gdotv partnership delivers rich graph data visualization&lt;/a&gt; goes further into the capabilities at your disposal when using a Gremlin IDE.&lt;/p&gt;

&lt;p&gt;Aerospike Graph is built on top of the &lt;a href="https://aerospike.com/products/database/" rel="noopener noreferrer"&gt;Aerospike Database&lt;/a&gt;, a high-performance, scalable, and reliable database engine. Aerospike Graph can build and operate large-scale graph applications across many use cases, including customer 360 and &lt;a href="https://aerospike.com/solutions/use-cases/fraud-prevention/" rel="noopener noreferrer"&gt;fraud prevention&lt;/a&gt;, among others.&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-aerospike-architecture.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-aerospike-architecture.png" alt="aerospike architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with graph data
&lt;/h2&gt;

&lt;p&gt;In this example, we examine various queries that explore a graph which contains a model of the worldwide air route network. The air-routes graph schema (see figure below) models a transportation network for air routes. It represents airports, countries, and continents as vertices and flight routes (i.e., routes) and continents or countries (i.e., the airport's location) as edges between the vertices. Each vertex (e.g., airport) has properties such as an airport code, name, location (latitude and longitude), and time zone. Similarly, edges (routes) can have properties such as distance between airports.&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-airport-continent-country.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-airport-continent-country.png" alt="airport continent country"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The schema includes the following elements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Airport vertex: Represents an airport in the transportation network. It has properties such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;code&lt;/code&gt;: The unique code assigned to the airport.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: The name of the airport.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;location&lt;/code&gt;: The geographical coordinates of the airport (latitude and longitude).
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;timezone&lt;/code&gt;: The time zone of the airport.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Route edge: Represents a flight route between two airports. It has properties such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;airline&lt;/code&gt;: The name of the airline operating the flight.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;distance&lt;/code&gt;: The distance between the airports.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Additionally, the schema could include other optional properties or additional vertex and edge types to represent more complex relationships, such as intermediate stops or connecting flights. The specific implementation of the graph schema may vary depending on the use case and your requirements. The remainder of the blog describes the software prerequisites, the Docker images you need, how to connect and load the data, and how to execute some queries.&lt;/p&gt;

&lt;p&gt;Why Docker containers? If you are a developer working on multiple machines, each time you switch a machine, you need to set up and configure the database separately. &lt;/p&gt;

&lt;p&gt;Using Aerospike Database and Aerospike Graph inside a Docker container, you can quickly spin up a sandbox environment and focus on actual development rather than infrastructure setup. The same is true for the production environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Software prerequisites
&lt;/h2&gt;

&lt;p&gt;As usual, there are a few prerequisites that need to be taken care of before you begin. Following is a list of the software used to run this JupyterLab Notebook.&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Frequired-software.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Frequired-software.png" alt="required software"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next section provides the steps to download the Docker images and launch the Graph Service and Database containers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Download Aerospike software
&lt;/h3&gt;

&lt;p&gt;Once you have Docker installed, the simplest way to get up and running is to pull the Aerospike images from the Docker hub repository. In a terminal window, execute the following pull commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull aerospike/aerospike-serverdocker
docker pull aerospike/aerospike-graph-servicedocker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll also need a trial license key for the Aerospike Graph Service. Get started by &lt;a href="https://aerospike.com/get-started-aerospike-graph/https://aerospike.com/get-started-aerospike-graph/" rel="noopener noreferrer"&gt;downloading a free trial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you would like detailed steps on how to start the containers, take a look at the &lt;a href="https://docs.aerospike.com/graph/docker/getting_started" rel="noopener noreferrer"&gt;Aerospike Graph Using Docker&lt;/a&gt; documentation. However, the steps below should be enough to get you started.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Set an environment variable with the license key (aka, Feature Key).&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FEATKEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; /&amp;lt;YOUR_PATH&amp;gt;/&amp;lt;YOUR_FEATURE_KEY.conf&amp;gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FEATKEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; /Users/Shared/setup/as_featurekey.conf&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Launch the database container.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"FEATURES=&lt;/span&gt;&lt;span class="nv"&gt;$FEATKEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"FEATURE_KEY_FILE=env-b64:FEATURES"&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; as_database &lt;span class="nt"&gt;-p&lt;/span&gt; 3000-3002:3000-3002 aerospike/aerospike-server-enterprise
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Launch the graph service.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p8182&lt;/span&gt;:8182 &lt;span class="nt"&gt;--name&lt;/span&gt; as_graph &lt;span class="nt"&gt;-v&lt;/span&gt; &amp;lt;PATH_TO_YOUR_SHARED_DIR&amp;gt;:/opt/aerospike/etc/sampledata &lt;span class="nt"&gt;-e&lt;/span&gt; aerospike.client.namespace&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; aerospike.client.host&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"172.17.0.2:3000"&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; aerospike.graph.index.vertex.label.enabled&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true &lt;/span&gt;aerospike/aerospike-graph-service
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p8182&lt;/span&gt;:8182 &lt;span class="nt"&gt;--name&lt;/span&gt; as_graph &lt;span class="nt"&gt;-v&lt;/span&gt; /Users/Shared/data/docker-bulk-load:/opt/aerospike/etc/sampledata &lt;span class="nt"&gt;-e&lt;/span&gt; aerospike.client.namespace&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; aerospike.client.host&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"172.17.0.2:3000"&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; aerospike.graph.index.vertex.label.enabled&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true &lt;/span&gt;aerospike/aerospike-graph-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; The &lt;code&gt;-v&lt;/code&gt; option allows you to bind a directory in your host operating system to a directory inside the Docker container. Make sure the &lt;strong&gt;air-routes-latest.graphml&lt;/strong&gt; has been copied to the shared directory &lt;code&gt;&amp;lt;PATH_TO_YOUR_SHARED_DIR&amp;gt;&lt;/code&gt; in the command above.  You can download the &lt;strong&gt;air-routes-latest.graphml&lt;/strong&gt; file form &lt;a href="https://github.com/krlawrence/graph/blob/master/sample-data/air-routes-latest.graphml" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Importing Python modules
&lt;/h3&gt;

&lt;p&gt;Execute the following cell to import the packages you need. You might need to install them first using the &lt;code&gt;pip&lt;/code&gt; command.&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;importlib.metadata&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pandas.plotting&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;ipywidgets&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;interact&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;IPython.display&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Markdown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HTML&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;IPython.display&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;display_markdown&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;gremlin_python.process.traversal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;IO&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;gremlin_python.process.anonymous_traversal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;traversal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;gremlin_python.driver.driver_remote_connection&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DriverRemoteConnection&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;gremlin_python.process.graph_traversal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GraphTraversalSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;__&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;gremlin_python.process.traversal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Barrier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Bindings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Cardinality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Operator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Pop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WithOptions&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;nest_asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;networkx&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ipycytoscape&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;jugri&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;

&lt;span class="n"&gt;nest_asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Connect to the graph service and load the air-route data
&lt;/h2&gt;

&lt;p&gt;To traverse the vertices and edges in the graph, you must spawn a traversal object:&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;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;traversal&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;withRemote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DriverRemoteConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ws://0.0.0.0:8182/gremlin&lt;/span&gt;&lt;span class="sh"&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;g&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above Gremlin query represents a simple pattern for creating a traversal object using a remote connection. Here is the breakdown of each part:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;g&lt;/code&gt;: This variable represents a reference to the traversal object. It allows you to build and execute queries on the graph database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;traversal()&lt;/code&gt;: This function creates a new traversal object. It is the entry point for executing queries in Gremlin.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;withRemote(DriverRemoteConnection('ws://0.0.0.0:8182/gremlin','g'))&lt;/code&gt;: This command configures the traversal object to use a remote connection to communicate with the Aerospike database. The DriverRemoteConnection class is used to establish the connection.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ws://0.0.0.0:8182/gremlin&lt;/code&gt;: This parameter specifies the WebSocket endpoint URL of the server hosting the graph database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;g&lt;/code&gt;: This parameter represents the specific traversal source on the server.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;By executing this query, you can perform various graph database operations using the 'g' traversal object linked to the specified remote connection.&lt;/p&gt;

&lt;p&gt;The next step is to populate the graph. The air-routes data should already be in the Aerospike Graph Service container. The file name is &lt;strong&gt;air-routes-latest.graphml&lt;/strong&gt; and should be in the &lt;code&gt;/opt/aerospike/etc/sampledata&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;The file is in GraphML format. GraphML is an XML-based file format for graphs shown in the table below. On the left column, there is one entry (a record) for each one of the vertices in the graph schema, namely continent, airport, and county. The column on the right shows the format for edges.&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-vertices-edges-chart.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-vertices-edges-chart.png" alt="vertices edges chart"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Populate the graph (vertices and edges)
&lt;/h3&gt;

&lt;p&gt;The following cell executes two statements. The first one &lt;code&gt;drops&lt;/code&gt; all data in the graph. The second one loads the data using the &lt;code&gt;io()&lt;/code&gt; step. The &lt;code&gt;evaluationTimeout&lt;/code&gt; parameter prevents the loading operation from timing out when running for extended periods. In the following example, the timeout is set to 5 minutes in milliseconds (even though it takes a couple of seconds to load the air-routes data). You can adjust it as necessary.&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;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evaluationTimeout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;\
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;io&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/opt/aerospike/etc/sampledata/air-routes-latest.graphml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;\
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graphml&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;\
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;\
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the data is loaded you can get a count of vertices and edges. To get a count of the total number of vertices loaded, execute the following statement:&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;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupCount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;g.V()&lt;/code&gt;: This step retrieves all the vertices in the graph.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.label()&lt;/code&gt;: This step extracts the label of each vertex.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.groupCount()&lt;/code&gt;: This step counts the occurrences of each unique label and creates a map with the label as the key and the count as a value.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.toList()&lt;/code&gt;: This step converts the map into a list, which can be returned as the final result of the Gremlin query.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: I am using Pandas data frames to capture the output of the queries and display the result either in tabular form or as a matplotlib chart.&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;v_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;groupCount&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;   &lt;span class="c1"&gt;# .T to Transpose the dataframe
&lt;/span&gt;&lt;span class="n"&gt;v_cnt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;v_cnt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&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;vertex name&lt;/span&gt;&lt;span class="sh"&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;count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get the number of edges loaded, replace the &lt;code&gt;g.V()&lt;/code&gt; step for &lt;code&gt;g.E()&lt;/code&gt;.&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;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;E&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupCount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;e_cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;E&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;groupCount&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;   &lt;span class="c1"&gt;# .T to Transpose the dataframe
&lt;/span&gt;&lt;span class="n"&gt;e_cnt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;e_cnt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&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;edge name&lt;/span&gt;&lt;span class="sh"&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;count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cell below uses &lt;strong&gt;matplotlib&lt;/strong&gt; to display the counts as a bar chart.&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="nf"&gt;display_markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;## Total Number of Vertices: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v_cnt&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;; Total Number of Edges: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e_cnt&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subplots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nrows&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ncols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;ax1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v_cnt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,).&lt;/span&gt;&lt;span class="n"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Vertex Counts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vertex name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;red&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ax1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vertices Count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ax1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar_label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ax1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;ax2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e_cnt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,).&lt;/span&gt;&lt;span class="n"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;axes&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;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Edge Counts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;edge name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;green&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ax2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;edges Count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ax2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar_label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ax2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After executing the above code you will get a count of vertices and edges in the graph.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Total number of vertices: 3749; Total number of edges: 57645&lt;/strong&gt;&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-airport-vertex-and-edges-counts.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-airport-vertex-and-edges-counts.png" alt="vertex edges count"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Traverse the graph data
&lt;/h2&gt;

&lt;p&gt;The last section of this blog presents some examples of Gremlin traversals that take advantage of the speed of the Aerospike Database.&lt;/p&gt;

&lt;p&gt;If you are new to Gremlin, this document, &lt;a href="https://www.kelvinlawrence.net/book/PracticalGremlin.html" rel="noopener noreferrer"&gt;PRACTICAL GREMLIN: An Apache TinkerPop Tutorial&lt;/a&gt;, is a great place to start. I've added comments to make the queries easy to understand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Query 1: Retrieve all columns for the airport with code 'AUS' (Austin)
&lt;/h3&gt;

&lt;p&gt;The first query looks at all the data in the graph and filters vertices that have the 'AUS' airport code.&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;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&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;AUS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;valueMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;g.V()&lt;/code&gt;: The vertex set of all the vertices in the graph.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.has('code','AUS')&lt;/code&gt;: Filtered by vertices with code = 'AUS'.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.valueMap()&lt;/code&gt;: Projects the result as a key value map of all the vertex properties.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.next()&lt;/code&gt;: Returns the final result set of the query.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&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;AUS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;valueMap&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()))&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-austin-bergstrom-airport.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-austin-bergstrom-airport.png" alt="autin bergstrom"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Query 2: Display a pie chart of the ten top countries with the greatest number of airports
&lt;/h3&gt;

&lt;p&gt;The next query demonstrates a count aggregation. It filters all the vertices labeled 'airport' and counts the number of airports by country.&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;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;airport&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupCount&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.hasLabel('airport')&lt;/code&gt;: Create a vertex set of all the vertices with the vertex label equal to 'airport'.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.groupCount().by('country')&lt;/code&gt;: Group and count all occurrences of airports by country.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;hasLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;airport&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;groupCount&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&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;Airports&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&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;index&lt;/span&gt;&lt;span class="sh"&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;Country&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;srt_temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Airports&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;not_top_ten&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srt_temp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;
&lt;span class="n"&gt;not_top_ten_sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;srt_temp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;not_top_ten&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;srt_top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;srt_temp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;new_record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Country&lt;/span&gt;&lt;span class="sh"&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;Other&lt;/span&gt;&lt;span class="sh"&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;Airports&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;not_top_ten&lt;/span&gt;&lt;span class="p"&gt;}])&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;srt_top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_record&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ignore_index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Airports&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;ax1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subplot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;121&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aspect&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;equal&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pie&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Airports&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ax1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autopct&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%1.1f%%&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="n"&gt;startangle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shadow&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Country&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;legend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fontsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ax2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subplot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;122&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;off&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tbl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ax2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;center&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;auto_set_font_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_fontsize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-top-10-countries-with-most-airports.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-top-10-countries-with-most-airports.png" alt="top 10 countries with most airports"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Query 3: Show possible routes from London to San Jose with one stop
&lt;/h3&gt;

&lt;p&gt;This query limits the number of vertices returned using the &lt;code&gt;limit()&lt;/code&gt; step.&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;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;airport&lt;/span&gt;&lt;span class="sh"&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;code&lt;/span&gt;&lt;span class="sh"&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;LHR&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;out&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;out&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&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;SJC&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.has('airport','code','LHR')&lt;/code&gt;: Filters the vertices by those with the property 'airport' and 'code' value equal to 'LHR' (London Heathrow Airport).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.out().out()&lt;/code&gt;: Traverses two steps out from the previous filtered vertices. This means it retrieves vertices that are connected by edges going out two times from the 'LHR' vertex. These vertices represent flights departing from London Heathrow Airport, possibly making a stopover at another airport.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.has('code','SJC')&lt;/code&gt;: Filters the vertices retrieved in the previous step by those with the property 'code' equal to 'SJC' (San Jose International Airport).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.limit(15)&lt;/code&gt;: Limits the result to only return a maximum of 15 vertices.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.path().by('code')&lt;/code&gt;: Retrieves the paths taken to reach the filtered vertices represented by the 'code' property of each vertex. This means it returns the flight routes from London Heathrow Airport to San Jose International Airport.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;style&amp;gt;.container { width:100% !important; }&amp;lt;/style&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;airport&lt;/span&gt;&lt;span class="sh"&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;code&lt;/span&gt;&lt;span class="sh"&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;LHR&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;out&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;out&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&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;SJC&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Path&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;legs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&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;Source_Airport&lt;/span&gt;&lt;span class="sh"&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;Dest_Airport&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;str&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iterrows&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path\[(.*), (.*), (.*)\]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&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;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;df1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Source_Airport&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&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;Airport&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;df2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Dest_Airport&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&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;Airport&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;vertices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;df1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;df2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;vertices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vertices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Airport&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&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;Airport&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;vertices_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;v&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;label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;vertices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Airport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;span class="n"&gt;NX_graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DiGraph&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;NX_graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_nodes_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vertices_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;NX_graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edges_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Display the first 5 rows only in tabular form
&lt;/span&gt;&lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw_networkx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NX_graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;font_color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#FFF&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node_color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#b20b00&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spring_layout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NX_graph&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;with_labels&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-airport-chart.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-airport-chart.png" alt="aiport chart"&gt;&lt;/a&gt;&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-airport-vertexes.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-airport-vertexes.png" alt="airport vetexes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Query 4: Return a map where the keys are the continent codes and the values are the number of airports in that continent
&lt;/h3&gt;

&lt;p&gt;In this next query, use a child traversal that spawns anonymously from &lt;code&gt;__&lt;/code&gt;. Usually, the function that gets this traversal will connect it to the previous traversal, as depicted in the following:&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;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;continent&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;out&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.hasLabel('continent')&lt;/code&gt;: This filters the vertices to only include those with the label 'continent'.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.group()&lt;/code&gt;: This function groups the filtered vertices.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.by('code')&lt;/code&gt;: This specifies that the grouping key will be 'code' property of the vertices.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.by(__.out().count())&lt;/code&gt;: This specifies that the value for each group will be the count of outgoing edges from each vertex.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;hasLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;continent&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;out&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;fig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;pie1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subplots&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;pie1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; \
        &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; \
        &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;autopct&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%1.1f%%&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;\
        &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;shadow&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt; \
        &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;startangle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt; \
        &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;explode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;pie1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;equal&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-continent-codes.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%2Fdeveloper-hub.s3.us-west-1.amazonaws.com%2Fdev-guide-graph%2Fa-developers-introduction-to-graph-databases-continent-codes.png" alt="continent codes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Query 5: Find the number of international and domestic flights with one stop from SFO
&lt;/h3&gt;

&lt;p&gt;The following query introduces four more steps. Namely, Project: “fold and unfold.”&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;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&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;SFO&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;out&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;out&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dedup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fold&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;International Flights From SFO&lt;/span&gt;&lt;span class="sh"&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;Domestic Flights From SFO&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unfold&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unfold&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&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;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.dedup()&lt;/code&gt;: Use the dedup step to remove duplicates from a result.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.fold()&lt;/code&gt;: Gathers all elements in the stream to that point and reduces them to a List.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.unfold()&lt;/code&gt;: Does the opposite, taking a List and unrolling it to its individual items and placing each back in the stream.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.project()&lt;/code&gt;: Similar to SQL project, that is, which properties we want to pick for display.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;display_markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt; ### &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;V&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&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;SFO&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;out&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;out&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;dedup&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;fold&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;International Flights From SFO&lt;/span&gt;&lt;span class="sh"&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;Domestic Flights From SFO&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unfold&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unfold&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&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;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;{'International Flights From SFO': 1904, 'Domestic Flights From SFO': 455}&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Start exploring the world of graph
&lt;/h2&gt;

&lt;p&gt;In this blog, I have shared a high-level view of the different layers of the Aerospike Graph Service and how those layers interoperate from the application layer to the database layer. I have also looked at the advantage of using the &lt;strong&gt;python_gremlin&lt;/strong&gt; library to execute queries against the Aerospike database, which helps simplify the application development.&lt;/p&gt;

&lt;p&gt;Aerospike Graph leverages open-source components, including the TinkerPop graph engine and the Gremlin graph query language. The current release initially addresses OLTP workloads, such as fraud detection and identity authentication, with OLAP functionality in the future. You can use it with many different programming languages; Python and Java are just two examples. Choose the language that works best for you.&lt;/p&gt;

&lt;p&gt;I suggest you try it out. Get the most out of your data with an &lt;a href="https://aerospike.com/get-started-aerospike-graph/" rel="noopener noreferrer"&gt;Aerospike Graph 60-day free trial&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>graph</category>
      <category>intro</category>
      <category>gremlin</category>
    </item>
    <item>
      <title>In-memory database improvements with Database 7</title>
      <dc:creator>Ronen Botzer</dc:creator>
      <pubDate>Wed, 15 Nov 2023 07:50:18 +0000</pubDate>
      <link>https://forem.com/aerospike/in-memory-database-improvements-with-database-7-3bdf</link>
      <guid>https://forem.com/aerospike/in-memory-database-improvements-with-database-7-3bdf</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eFgI79NP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developer-hub.s3.us-west-1.amazonaws.com/78458717/improving-in-memory-performance-aerospike-database-7_1700028415335.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eFgI79NP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developer-hub.s3.us-west-1.amazonaws.com/78458717/improving-in-memory-performance-aerospike-database-7_1700028415335.webp" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Welcome to Aerospike Database 7, and the initial server 7.0 release that sets the foundation for big developer API additions in server 7.1 and beyond. Server 7.0 also overhauls in-memory namespace in significant ways.&lt;/p&gt;

&lt;p&gt;Aerospike releases have always been a continuum, with preceding minor releases providing prerequisite work upon which the next major release stands. For example, server 5.6 added a data structure for set indexes later used for secondary indexes (SI). Server 5.7 overhauled secondary index garbage collection and cut down SI memory consumption by 60%. Aerospike Database 6 was built on these essential improvements. Similarly, server 6.4 removed support for &lt;a href="https://docs.aerospike.com/reference/configuration#single-bin"&gt;&lt;code&gt;single-bin&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://docs.aerospike.com/reference/configuration#data-in-index"&gt;&lt;code&gt;data-in-index&lt;/code&gt;&lt;/a&gt; namespaces, freeing up primary index (PI) space needed for upcoming server 7.1 features.&lt;/p&gt;

&lt;p&gt;Though major server releases have distinct themes, work on specific subsystems doesn’t end when our main focus shifts. Just as server versions 6.1 and 6.4 delivered significant throughput improvements to &lt;a href="https://aerospike.com/products/features/cross-datacenter-replication-xdr/"&gt;cross-datacenter replication&lt;/a&gt; (XDR) following the XDR rewrite theme of Aerospike Database 5, secondary index improvements will continue in Aerospike Database 7 releases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unified storage format revolutionizes in-memory namespaces
&lt;/h2&gt;

&lt;p&gt;After previously using the same storage format for &lt;a href="https://docs.aerospike.com/server/operations/configure/namespace/storage"&gt;namespaces that persist data&lt;/a&gt; on SSD or Intel Optane™ Persistent Memory (PMem), an overhaul of in-memory namespaces in server 7.0 consolidates all three storage engines to the same efficient flat format. This results in multiple operational benefits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Faster restarts for in-memory namespaces
&lt;/h3&gt;

&lt;p&gt;In Aerospike Enterprise Edition (EE) and Standard Edition (SE), the new storage-engine memory places its data in shared memory (shmem) rather than volatile process memory. This means that in-memory namespaces can now &lt;a href="https://docs.aerospike.com/server/operations/manage/aerospike/fast_start"&gt;fast restart&lt;/a&gt; (AKA warmstart) after clean shutdowns. &lt;/p&gt;

&lt;p&gt;An in-memory namespace without persistence shares the fast restart capability mentioned above. More interestingly, cold restarts, during which Aerospike daemon (asd) rebuilds its indexes, run much faster, as record data is read from shared-memory, rather than a storage device. &lt;/p&gt;

&lt;p&gt;An in-memory namespace with storage-backed persistence benefits from faster cold restarts when certain configuration parameters are adjusted (for example, &lt;a href="https://docs.aerospike.com/server/reference/configuration#partition-tree-sprigs"&gt;&lt;code&gt;partition-tree-sprigs&lt;/code&gt;&lt;/a&gt;). Only after a crash will Aerospike read from storage-backed persistence to repopulate record data into memory, along with rebuilding the indexes.&lt;/p&gt;

&lt;p&gt;Adding to its existing capability of backing up index shmem segments to disk, the Aerospike Shared Memory Tool (&lt;a href="https://docs.aerospike.com/tools/asmt"&gt;ASMT&lt;/a&gt;) can now be used after Aerospike shuts down to back up in-memory namespace data ahead of restarting the host machine.&lt;/p&gt;

&lt;p&gt;To summarize, in-memory namespaces without storage-backed persistence don’t lose their data on restarts of asd, and all in-memory namespaces benefit from faster restarts (both warmstart and faster coldstart).&lt;/p&gt;

&lt;h3&gt;
  
  
  Compression for in-memory namespaces
&lt;/h3&gt;

&lt;p&gt;Now you can configure an in-memory namespace to use storage compression, such as ZStandard (zstd), LZ4, or Snappy. Customers already using storage compression in the persistence layer of an in-memory namespace (or data on SSD or PMem) will achieve the same compression ratio for their data, regardless of the storage engine, at the same CPU cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stability and performance improvements for in-memory namespaces
&lt;/h3&gt;

&lt;p&gt;As in-memory and on-device storage use the exact same storage format in server 7.0, an in-memory namespace is mirrored to its persistence layer. This means that its write-block defragmentation happens much faster in memory and no longer requires device reads. The same continuous write-block defrag mechanism eliminates heap fragmentation encountered in the former JEMalloc-based in-memory storage. Similarly, tomb raiding of durable-delete tombstones happens fully in memory and requires no device reads. This removes back-pressure generated by the persistence layer’s devices on in-memory namespace operations.&lt;/p&gt;

&lt;p&gt;The unified format's single-pointer and contiguous record storage improve performance in two other ways. First, reading the entire record costs a single memory access, as opposed to the older scattered bins approach requiring multiple independent reads from RAM. Second, since write-blocks are mirrored to the persistence layer, write operations save the CPU previously consumed by separate serialization to a second storage format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Capacity planning for in-memory namespaces
&lt;/h3&gt;

&lt;p&gt;The first thing to note about in-memory namespaces with storage-backed persistence in server 7.0 is that the persistence layer is exactly the same as the in-memory storage; the two are mirrors of each other, which has a capacity planning implication. For previous versions, we had recommended that persistent storage be a multiple of &lt;a href="https://docs.aerospike.com/server/reference/configuration#memory-size"&gt;&lt;code&gt;memory-size&lt;/code&gt;&lt;/a&gt; (the max memory allocation for the namespace), typically 4x. Starting with server 7.0, persistent storage needs to be at a 1:1 ratio to the memory you wish to dedicate to your in-memory namespace.&lt;/p&gt;

&lt;p&gt;The second thing to be aware of is that in-memory data storage is static, and gets pre-allocated in server 7.0 rather than progressively growing and bound by the (now obsolete) &lt;code&gt;memory-size&lt;/code&gt; configuration parameter.&lt;/p&gt;

&lt;p&gt;Capacity planning for indexes has not changed. In server 7.0, indexes continue to start small and grow in increments defined by the configuration parameters &lt;a href="https://docs.aerospike.com/server/reference/configuration#index-stage-size"&gt;&lt;code&gt;index-stage-size&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://docs.aerospike.com/server/reference/configuration#sindex-stage-size"&gt;&lt;code&gt;sindex-stage-size&lt;/code&gt;&lt;/a&gt;. &lt;a href="https://docs.aerospike.com/server/operations/plan/capacity#calculating-set-index-storage"&gt;Set indexes&lt;/a&gt; grow in 4KiB increments after an initial pre-allocation. After upgrading a cluster node, the namespace indexes consume the same amount of memory as before, out of the system memory not pre-allocated for namespace data storage.&lt;/p&gt;

&lt;p&gt;We no longer have diverging capacity planning formulas for data in-memory versus data on persistent storage. All storage-engine configurations use the same storage format and a single formula in the &lt;a href="https://docs.aerospike.com/server/operations/plan/capacity"&gt;capacity planning guide&lt;/a&gt;. Treating capacity planning of in-memory data storage the same as you would data storage on an SSD is helpful. In both cases, you are aiming to size pre-allocated storage.&lt;/p&gt;

&lt;p&gt;The memory consumed by your indexes (and room for them to grow), plus the pre-allocated namespace data storage, should fit within your host machine’s RAM and within the previously declared memory-size. Read the &lt;a href="https://docs.aerospike.com/server/operations/upgrade/special_upgrades/70_upgrade"&gt;special upgrade instructions for Server 7.0&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caveats
&lt;/h3&gt;

&lt;p&gt;Support for single-bin namespaces was removed in server 6.4. Aerospike users without single-bin namespaces in their cluster may upgrade to server 7.0 through a regular rolling upgrade. Otherwise, please consult the &lt;a href="https://docs.aerospike.com/server/operations/upgrade/special_upgrades/64_upgrade"&gt;special upgrade instructions for Server 6.4&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Due to the unified storage format, a &lt;a href="https://docs.aerospike.com/server/reference/configuration#write-block-size"&gt;&lt;code&gt;write-block-size&lt;/code&gt;&lt;/a&gt; limit of 8MiB applies to in-memory namespaces (with or without persistence). Aerospike users who depend on the former 128MiB record size limit of in-memory without persistence will need to break up their records. Customers may choose to delay upgrading till server 7.1, which will enable an easier transition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration and monitoring
&lt;/h2&gt;

&lt;p&gt;The newly released &lt;a href="https://aerospike.com/download/#aerospike-monitoring-stack"&gt;Aerospike Observability Stack 3.0&lt;/a&gt; and &lt;a href="https://aerospike.com/download/#aerospike-tools"&gt;Tools 10.0&lt;/a&gt; support metrics and configuration for both Aerospike 6 and Aerospike 7 and are designed to ease your transition to server 7.0. If you are not familiar with &lt;a href="https://aerospike.com/products/observability-management/"&gt;Aerospike Observability and Management&lt;/a&gt; (O&amp;amp;M), we have a short video, &lt;a href="https://aerospike.com/blog/architect/manage-what-matters-aerospike-observability-stack/"&gt;blog&lt;/a&gt;, and webinar available on our site.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration parameter and metric changes in detail
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.aerospike.com/server/operations/configure/namespace"&gt;Namespace configuration&lt;/a&gt;, regardless of &lt;a href="https://docs.aerospike.com/server/operations/configure/namespace/storage"&gt;storage engine&lt;/a&gt; choice, is simpler in server 7.0.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aerospike.com/server/operations/configure/namespace/retention"&gt;Stop-writes and eviction thresholds&lt;/a&gt; are controlled by the storage-engine configuration parameters &lt;a href="https://docs.aerospike.com/server/reference/configuration#stop-writes-used-pct"&gt;&lt;code&gt;stop-writes-used-pct&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://docs.aerospike.com/server/reference/configuration#stop-writes-avail-pct"&gt;&lt;code&gt;stop-writes-avail-pct&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://docs.aerospike.com/server/reference/configuration#evict-used-pct"&gt;&lt;code&gt;evict-used-pct&lt;/code&gt;&lt;/a&gt;, which are relative to the namespace data storage size. There are also a pair of thresholds relative to the system memory - &lt;a href="https://docs.aerospike.com/server/reference/configuration#stop-writes-sys-memory-pct"&gt;&lt;code&gt;stop-writes-sys-memory-pct&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://docs.aerospike.com/server/reference/configuration#evict-sys-memory-pct"&gt;&lt;code&gt;evict-sys-memory-pct&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Data storage metrics have been simplified to &lt;code&gt;data_used_bytes&lt;/code&gt;, &lt;code&gt;data_total_bytes&lt;/code&gt;, &lt;code&gt;data_used_pct&lt;/code&gt;, and &lt;code&gt;data_avail_pct&lt;/code&gt; for all storage engine types.&lt;/p&gt;

&lt;p&gt;Index metrics are also simpler. Set indexes have &lt;code&gt;set_index_used_bytes&lt;/code&gt;. Primary and secondary indexes have &lt;code&gt;index_used_bytes&lt;/code&gt; and &lt;code&gt;sindex_used_bytes&lt;/code&gt;, whether they’re stored in shared memory, PMem, or an SSD. If they’re in persistent storage, they also have &lt;code&gt;index_mounts_used_pct&lt;/code&gt; and &lt;code&gt;sindex_mounts_used_pct&lt;/code&gt; relative to the mounts_budget. &lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-tenancy
&lt;/h2&gt;

&lt;p&gt;Many Aerospike customers deploy their database clusters as a multi-tenant service, with distinct users separated by &lt;a href="https://docs.aerospike.com/server/architecture/data-model"&gt;sets&lt;/a&gt; within a namespace. Multi-tenancy leans on Aerospike enterprise features, such as scoped role-based access control (&lt;a href="https://docs.aerospike.com/server/operations/configure/security/access-control"&gt;RBAC&lt;/a&gt;), &lt;a href="https://docs.aerospike.com/server/guide/security/rate_quotas"&gt;rate quotas&lt;/a&gt;, and &lt;a href="https://docs.aerospike.com/server/operations/manage/sets#capping-the-size-of-a-set"&gt;set quotas&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Server 7.0 makes multi-tenant deployment easier with several new features.The limit of 64K unique bin names per-namespace was removed. Operators no longer need to advise developers to restrict how many bin names their applications write into the namespace. As a result, the &lt;code&gt;bins&lt;/code&gt; info command and  the &lt;code&gt;available_bin_names&lt;/code&gt; namespace statistic, were removed.&lt;/p&gt;

&lt;p&gt;The limit on unique set names per namespaces was raised from 1023 to 4095, allowing for set-level segregation of more tenants on the same Aerospike cluster.&lt;/p&gt;

&lt;p&gt;Finally, an operator can now assign a unique set-level &lt;code&gt;default-ttl&lt;/code&gt; as an override of the namespace &lt;code&gt;default-ttl&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  New developer API features
&lt;/h2&gt;

&lt;p&gt;Server 7.0 adds the capability to &lt;a href="https://docs.aerospike.com/server/guide/query"&gt;index and query&lt;/a&gt; bytes data (BLOBs).&lt;/p&gt;

&lt;p&gt;Application developers may now choose to persist key-ordered Map indexes, trading off extra storage for improved performance. The new MapPolicy option can be applied when creating a new Map bin or with the Map set_type operation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MapPolicy(MapOrder order, int flags, boolean persistIndex)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Persisting Map indexes should only be used by an application once all the nodes in the Aerospike cluster have been upgraded to version &amp;gt;= 7.0.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dropping support for old OS versions
&lt;/h2&gt;

&lt;p&gt;Server 6.4 added support for Amazon Linux 2023 and Debian 12. As I &lt;a href="https://developer.aerospike.com/blog/aerospike-database-64-improved-query-and-data-distribution"&gt;previously warned&lt;/a&gt;, server 7.0 removes support and el7 builds for Red Hat Enterprise Linux 7 and its variants, including CentOS 7, Amazon Linux 2, and Oracle Linux 7. Similarly, server 7.0 will not be available on Debian 10.&lt;/p&gt;

&lt;p&gt;Aerospike engineering takes performance seriously, and Aerospike users choose to build mission-critical applications on our database because it has the best cost-performance in its field. Performance is hindered by running new Aerospike server versions on ancient lower-performing OS kernels, such as the 3.10 Linux kernel packaged with RHEL 7. In a recent announcement, the Linux kernel team declared they will no longer offer six years of LTS support. This announcement validated our perspective on the stability and performance cost of running Aerospike on old kernels.&lt;/p&gt;

&lt;p&gt;Both Debian 10 and RHEL 7 reach their end of life (EOL) in June 2024 ( 5 and 10 years from their initial release, respectively ). Each new major and minor Aerospike server version gets two years of bug fixes and security vulnerability support. Going forward, new server versions will not be offered on OS distro versions scheduled to expire during this support period. Subsequent patch releases (hotfixes) will continue to be built and tested on the same OS distro versions as when they were first released.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try Aerospike 7.0
&lt;/h2&gt;

&lt;p&gt;Persistence, fast restart capability, and built-in compression all make the new Aerospike in-memory namespaces appealing for in-memory database use cases.&lt;/p&gt;

&lt;p&gt;Consult the &lt;a href="https://docs.aerospike.com/reference/platform-support"&gt;platform compatibility&lt;/a&gt; page and the &lt;a href="https://developer.aerospike.com/client/client_matrix#minimum-usable-client-versions"&gt;minimum usable client versions&lt;/a&gt; table. For more details, read the &lt;a href="https://docs.aerospike.com/reference/release_notes/server/7.0-server-release-notes"&gt;Server 7.0 release notes&lt;/a&gt;. You can &lt;a href="https://aerospike.com/download/"&gt;download&lt;/a&gt; Aerospike EE and run in a single-node evaluation; you can get started with a 60-day multi-node trial at our &lt;a href="https://aerospike.com/lp/try-now/"&gt;Try Now&lt;/a&gt; page.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>inmemory</category>
      <category>speed</category>
    </item>
  </channel>
</rss>
