<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Saurabh Verma on Medium]]></title>
        <description><![CDATA[Stories by Saurabh Verma on Medium]]></description>
        <link>https://medium.com/@saurabhdec1988?source=rss-d3b5e35d17ea------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*QdRvBJqB48Qja7r_bXQg1w.jpeg</url>
            <title>Stories by Saurabh Verma on Medium</title>
            <link>https://medium.com/@saurabhdec1988?source=rss-d3b5e35d17ea------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 04:26:21 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@saurabhdec1988/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Distributed Transactions Atomicity : 2PC commit & Raft-based 2PC]]></title>
            <link>https://medium.com/@saurabhdec1988/distributed-transactions-atomicity-2pc-commit-raft-based-2pc-69139ab702b6?source=rss-d3b5e35d17ea------2</link>
            <guid isPermaLink="false">https://medium.com/p/69139ab702b6</guid>
            <category><![CDATA[consensus-algorithm]]></category>
            <category><![CDATA[transactions]]></category>
            <category><![CDATA[distributed-systems]]></category>
            <dc:creator><![CDATA[Saurabh Verma]]></dc:creator>
            <pubDate>Tue, 04 Jun 2024 20:35:30 GMT</pubDate>
            <atom:updated>2024-06-05T06:01:19.177Z</atom:updated>
            <content:encoded><![CDATA[<h3>Distributed Transactions Atomicity : 2PC commit &amp; Raft-based 2PC</h3><p>This article compares the approaches to achieve <strong>Atomicity (</strong>from ACID) aspect in a distributed transaction</p><h4><strong>Introduction</strong></h4><p>Distributed databases typically divide their tables into partitions spread across different servers which get accessed by many clients. In these databases, client transactions often span the different servers as the transactions may need to read from various partitions.<strong><em> A distributed transaction is a database transaction which spans multiple servers.</em></strong></p><h4>Characteristics of a Correct Transaction</h4><p>A correct transaction satisfies the <a href="https://en.wikipedia.org/wiki/ACID">ACID</a> properties, briefly mentioned below</p><p><strong>Atomicity: </strong>Guarantee that the transaction is treated as a “single unit”, which either succeeds or fails</p><p><strong>Consistency: </strong>Guarantee that the transaction completion ensures no database / domain invariant is broken</p><p><strong>Isolation</strong>: Guarantee that there are no race conditions in face of concurrent transactions</p><p><strong>Durability: </strong>Guarantee that a committed transaction is committed even in case of system failure (eg. machine restart, disk corruption, etc.)</p><h4>Atomicity in Distributed Transactions</h4><p>The atomicity aspect is more difficult to guarantee in distributed transactions since it involves more number of participant servers. With multiple servers involved, the transaction can fail on some of the servers. The database must maintain atomicity in this case as well which would be aborting the transaction and rolling back the state on the remaining servers.</p><h4>Transaction Commit Process Model</h4><ol><li>The transaction commit process models the <strong>Atomicity </strong>problem as decision-making problem involving multiple processes called <strong>Resource Managers (RM)</strong></li><li>The fundamental problem is that the RMs must eventually agree on whether the transaction is committed or aborted</li><li>Goal of the Transaction Commit Process with a given set of RMs in <em>Working</em> State<br>a. Make all the RMs agree on either <strong><em>Committed</em> or <em>Aborted</em> state<br></strong>b. Once an RM reaches <em>Committed</em> state, it cannot go to <em>Aborted</em> state and vice versa<br>c. If an RM is in <em>Committed</em> state, no other RM can be in <em>Aborted</em> state and vice versa</li><li>Below is the state diagram for an RM</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/777/1*o5sBEsjsH1blSkwhXH4oVg.png" /><figcaption>State Diagram for Resource Manager</figcaption></figure><h4>The Two-Phase Commit (2PC) protocol</h4><p><strong>Two-Phase commit (2PC) protocol </strong>is an implementation of the Transaction Commit Process which uses a <strong>Transaction Manager (TM) </strong>to coordinate the decision making process across <strong>RMs</strong></p><p>The 2PC introduces below states for the TM<br>- initialized<br>- preparing<br>- committed<br>- aborted</p><p>Below sequence diagram captures the message flow for 2PC</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/803/1*vZHLPLHe51oqkZiExiI9Jw.png" /><figcaption>Message flow for 2PC in the scenario where RM1 is the first RM to enter <em>Prepared State</em></figcaption></figure><p>and described below</p><ol><li>2PC starts when an RM enters <em>Prepared </em>state and sends a <em>Prepared </em>message to the TM</li><li>The TM enters the <em>Preparing </em>state and sends a <em>Prepare </em>message to every other RM</li><li>Upon receiving the <em>Prepare </em>message, the RMs get into the <em>Prepared </em>state and send a <em>Prepared </em>message to the TM</li><li>When TM receives <em>Prepared</em> message from all the RMs, it enters the <em>Committed </em>state and sends a <em>Commit </em>message to each RM</li><li>The RMs enter the <em>Committed </em>state on receiving the <em>Commit</em> message from the TM</li></ol><h4>Fault Tolerance</h4><ol><li>Each participant (TM and RMs) store their state on durable storage before sending the message to any other participant</li><li>This adds fault tolerance in the event of participants going down and coming back up</li></ol><h4>The Problem in 2PC</h4><ol><li>2PC is a <strong>blocking commit protocol </strong>— in face of TM failure, the entire transaction commit blocks until the TM is repaired</li><li>Consider the scenario where all the RMs have replied back with <em>Prepared </em>message to the TM and the TM fails <br>a. RMs do not have a way to know if the TM committed or aborted the transaction<br>b. RMs keep waiting for the message from TM while possibly holding locks on respective servers</li></ol><h4>Augmenting 2PC with Raft</h4><p>The <a href="https://en.wikipedia.org/wiki/Raft_(algorithm)">Raft</a> algorithm is a distributed consensus algorithm that improves the availability of the system by introducing replicas and keeps the replicas strongly consistent. Raft understands only the <em>leader and followers concept.</em></p><p>The blocking nature of 2PC is due to a single TM, and if we can make the TM highly available, we will be able to make transaction commit process non-blocking in face of TM failures.</p><p>We can achieve HA for TM and the RMs using Raft as below</p><ol><li>Convert TM and RMs into raft groups. Each raft group has an <em>odd number </em>of instances</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/755/1*5MmGu1OgeXgedyvdnTNykw.png" /><figcaption>The TM and RMs converted to Raft groups with 3 replicas each</figcaption></figure><p>2. A TM raft group with <em>2f+1 </em>nodes can withstand <em>f </em>failures</p><p>3. The TM leader (chosen via Raft leader election) coordinates the Transaction Commit Process across the RM raft groups via message passing as mentioned in the “The Two-Phase Commit (2PC) protocol” section above</p><p>4. Each RM is also a raft group and decides on one of <em>can_commit </em>and <em>must_abort </em>value for each transaction</p><p>The message flow for Raft-based 2PC looks as below</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tiUrznpeM44m2G_Pr5LwCw.png" /><figcaption>Message flow for Raft-based 2PC</figcaption></figure><h4>Conclusion</h4><p>In this article, I summarized the 2PC and how Raft can be used to workaround the blocking nature of 2PC in face of failures. In the next articles, I would drill down upon the aspects of Dynamic RM registration</p><h4>References</h4><ol><li>Consensus on Transaction Commit — <a href="https://dl.acm.org/doi/10.1145/1132863.1132867">https://dl.acm.org/doi/10.1145/1132863.1132867</a></li><li><a href="https://timilearning.com/posts/mit-6.824/lecture-12-distributed-transactions/">https://timilearning.com/posts/mit-6.824/lecture-12-distributed-transactions/</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=69139ab702b6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Leveraging the Stargate Document API for Time Series Data in Cassandra]]></title>
            <link>https://medium.com/@saurabhdec1988/leveraging-the-stargate-document-api-for-time-series-data-in-cassandra-94795d8225b3?source=rss-d3b5e35d17ea------2</link>
            <guid isPermaLink="false">https://medium.com/p/94795d8225b3</guid>
            <category><![CDATA[timeseries]]></category>
            <category><![CDATA[stargate]]></category>
            <category><![CDATA[real-time-analytics]]></category>
            <category><![CDATA[cassandra]]></category>
            <category><![CDATA[datastax]]></category>
            <dc:creator><![CDATA[Saurabh Verma]]></dc:creator>
            <pubDate>Tue, 04 Jun 2024 13:55:44 GMT</pubDate>
            <atom:updated>2024-06-04T13:55:44.756Z</atom:updated>
            <content:encoded><![CDATA[<p><em>In this blog, you’ll learn how to use the Stargate Document API for Apache Cassandra® and build a simple TimeSeries DB for weather monitoring on top of the DataStax Astra DB. The demo focuses on the data model, data extraction, storage, and retrieval queries for the Weather monitoring app</em>.</p><h3>Introduction</h3><p><a href="https://dtsx.io/3XHGwlN">Stargate</a> for Apache Cassandra is a data API gateway deployed between the client applications and a database. The Stargate Document API modifies and queries data stored as unstructured JSON documents in collections, which gives the application developers native JSON support without having to give up any of the reliability and scalability goodness of Cassandra.</p><p>This Stargate Document API lets most Cassandra distributions (Cassandra 3.11, Cassandra 4.0, K8ssandra.io, DataStax Enterprise 6.8) work with JSON through a REST API. This <a href="https://dtsx.io/3in0zpy">deep dive</a> details how Stargate Document API stores the JSON as C* column family data within Cassandra.</p><h3>Time Series Data with the Cassandra Database</h3><p>Cassandra’s data model works well with data in a sequence. That data can be variable in size, and Cassandra handles large amounts of data excellently.</p><p>Cassandra uses <a href="https://www.youtube.com/watch?v=I6jB0nM9SKU">Log Structured Merge Trees</a> (LSM-Trees) to store its data, not B-Trees. The LSM tree data structure is perfect for high write volumes, turning updates and deletes into new writes. With the wrong data model, reads are often an order of magnitude slower than writes, which is exactly the opposite of B-Trees. Thus, Cassandra’s underlying storage mechanism is highly compatible with Time Series Data.</p><p>When writing data to Cassandra, data is sorted and written sequentially to disk. When retrieving data by row key and then by range, you get a fast and efficient access pattern due to minimal disk seeks. Time series data is an excellent fit for this type of pattern. For these examples, we’ll use a weather station that creates temperature data every minute. You’ll see how using the row key and sequence can be a powerful data modeling tool.</p><h3>Building a Weather Monitoring App with Cassandra and Stargate</h3><p>Let’s consider the data retrieval needs of a weather monitoring app built to consume data produced by the weather station. This application would provide reports such as those in the table below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oZsj3aZdnG4XFRES" /></figure><p>Cassandra is well suited for supporting these types of reports, especially when the format of the underlying weather data is relatively static over time. However, let’s consider the case where the contents of weather reports can vary.</p><h3>What Purpose Does the Stargate Document API Serve?</h3><p>The data provided by weather.com has a considerable amount of location, time, and weather attributes. New attributes can be <em>added or removed</em> from the <a href="https://www.weatherapi.com/">WeatherAPI.com</a> response at any time. This example focuses on temperature-related characteristics for the locations, but can add additional attributes easily<em>.</em> Let’s start by querying for <em>hierarchical attributes</em> like:</p><ul><li>location (country -&gt; region -&gt; city)</li><li>time granularity (monthly -&gt; weekly -&gt; daily)</li></ul><p>This requires that the data storage format allows us to do at least two things:</p><ol><li>Accept any provided attributes at write time, and impose schema at read time.</li><li>Store and query the data at hierarchical levels and not force us to flatten it before storing it in the data store.</li></ol><p>Given these requirements, a Document-oriented approach with JSON formatted data would be suitable for this use case, which is where the Stargate Document API comes into play. The Document API allows the application to store arbitrary JSON documents in a collection, while under the hood, still leveraging the efficiencies Cassandra provides for reading and writing time series data.</p><h3>Weather Application Architecture</h3><p>Let’s look in more detail at a sample weather application.</p><h3>API Specification</h3><p>The application is a Next.js app located <a href="https://github.com/DataStax-Examples/weatherapp">here</a> in Github. Below are the API endpoints exposed by this application and a sample query for each endpoint.</p><ol><li><strong>/cities</strong> → POST endpoint to add a new city to the application for weather monitoring.</li></ol><pre>curl --location --request POST &#39;localhost:3000/api/cities&#39; \<br>--header &#39;Content-Type: application/json&#39; \<br>--data-raw &#39;{<br>   &quot;name&quot;: &quot;Austin&quot;<br>}&#39;</pre><p>2. <strong>/fetcher</strong> → POST endpoint that triggers async pull of weather data for a given city and a date.</p><pre>curl --location --request POST &#39;localhost:3000/api/fetcher&#39; \<br>--header &#39;Content-Type: application/json&#39; \<br>--data-raw &#39;{<br>    &quot;city&quot;: &quot;Seattle&quot;,<br>    &quot;numDays&quot;: 7,<br>    &quot;forecastDate&quot;: &quot;2022-10-01&quot;<br>}&#39;</pre><p>3. <strong>/report1</strong> → POST endpoint fetching the weekly temperature report by day for a given location (<a href="https://medium.com/building-the-open-data-stack/leveraging-the-stargate-document-api-for-time-series-data-in-cassandra-870b732c1bcd#e777">Report 1</a>).</p><pre>curl --location --request POST &#39;localhost:3000/api/report1&#39; \<br>--header &#39;Content-Type: application/json&#39; \<br>--data-raw &#39;{<br>    &quot;city&quot;: &quot;London&quot;,<br>    &quot;date&quot;: &quot;2022-11-01&quot;<br>}&#39;</pre><p>4. <strong>/report2 </strong>→ POST endpoint fetching the weekly temperature comparison for 2 given locations and a given week (<a href="https://medium.com/building-the-open-data-stack/leveraging-the-stargate-document-api-for-time-series-data-in-cassandra-870b732c1bcd#e777">Report 2</a>).</p><pre>curl --location --request POST &#39;localhost:3000/api/report2&#39; \<br>--header &#39;Content-Type: application/json&#39; \<br>--data-raw &#39;{<br>    &quot;city1&quot;: &quot;London&quot;,<br>    &quot;city2&quot;: &quot;Seattle&quot;,<br>    &quot;date&quot;: &quot;2022-11-01&quot;<br>}&#39;</pre><h3>Application Components</h3><p>The figure below shows the components that make up our weather application and how it receives and stores data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Be7ocB-mC5hKq7wy" /></figure><p>Figure 1: High-level data flow of the weather application</p><p>Let’s look at each of the numbered components below in more detail so you can run this example yourself.</p><h3>(1) Data Source</h3><p>The data source is <a href="https://www.weatherapi.com/">WeatherAPI.com</a> which provides JSON APIs for <a href="https://www.weatherapi.com/api-explorer.aspx#history">historical</a> and <a href="https://www.weatherapi.com/api-explorer.aspx#forecast">forecast</a> weather data for specified locations.</p><h3>WeatherAPI.com API Keys and Authentication</h3><p>In order to be able to access the weather data using the history API, you need to sign up at <a href="https://www.weatherapi.com/">WeatherAPI.com</a> and get an API Key, as shown below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*mcqJmrfTNSizGFWi" /></figure><p>Figure 2: Weather API API key</p><p>To view the request and the response format from the history API, open the <a href="https://www.weatherapi.com/api-explorer.aspx#forecast">API Explorer tool</a> from Weather API and input your API Key as below. To request historical data, you must input the API Key for each API call.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*63kDL5fXIxZF-TzX" /></figure><p>Figure 3: Weather API interactive API explorer</p><p>Here’s an example response from the forecast API for <em>London on 2022–11–09</em>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*kevxdWemgoDiv_zN" /></figure><p>Figure 4: An example of Weather API JSON forecast response</p><h3>(2) Application Configuration</h3><p>The application configuration is stored in files <em>.env.*</em> in the root folder and named according to the patterns described in the following table.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*DckB_pGAdb2mcS_u" /></figure><p>The table below describes the application configuration parameters.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*UfD7ZRcrxq88_7CE.png" /></figure><p>*Instructions on how to generate an application token <a href="https://dtsx.io/3VmeB9t">here</a>.</p><p>To configure your instance of the application, you’ll populate the values shown in the <em>.env.local </em>file.</p><pre>ASTRA_DB_ID=&lt;ASTRA_DB_ID&gt;<br>ASTRA_DB_REGION=&lt;ASTRA_DB_REGION&gt;<br>ASTRA_DB_APPLICATION_TOKEN=&lt;ASTRA_DB_APPLICATION_TOKEN&gt;<br>ASTRA_DB_KEYSPACE=&lt;ASTRA_DB_KEYSPACE&gt;<br>WEATHER_API_KEY=&lt;WEATHER_API_KEY&gt;</pre><h3>(3) Weather Data Extractor (/fetch API)</h3><p>Source / raw data nearly always needs some transformation when applied to a new use case. This application is no exception. The queries mentioned <a href="https://medium.com/building-the-open-data-stack/leveraging-the-stargate-document-api-for-time-series-data-in-cassandra-870b732c1bcd#e777">here</a> are often fetching the data at weekly granularity, whereas the data made available by the weather.com API is at a daily level.</p><p>The <a href="https://medium.com/building-the-open-data-stack/leveraging-the-stargate-document-api-for-time-series-data-in-cassandra-870b732c1bcd#09fb">/fetch</a> API can solve this, by fetching the data from the weatherapi.com API. Then, it converts day-level data as a member in the weekly granularity document for the particular city in Apache Cassandra as shown below.</p><p>The <a href="https://medium.com/building-the-open-data-stack/leveraging-the-stargate-document-api-for-time-series-data-in-cassandra-870b732c1bcd#09fb">/fetch</a> API uses the <a href="https://dtsx.io/3VxOMD2">Stargate Document API Collections</a> to store the weather data. Additionally, the <a href="https://medium.com/building-the-open-data-stack/leveraging-the-stargate-document-api-for-time-series-data-in-cassandra-870b732c1bcd#09fb">/fetch</a> API stores the weekly weather document with the key as <em>&lt;cityName_weekNumber&gt;</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*yzd7TSRHuN2YA-dO" /></figure><p>Figure 5: An example of JSON response stored in Stargate Collection</p><p>The document stored in C* via the Stargate Document API has the key as<em> &lt;city_weekNumber&gt;</em> seen below for city Boston and week 26:</p><pre>{<br>  &quot;documentId&quot;: &quot;Boston_26&quot;,   ←— documentKey aka primary key<br>  &quot;data&quot;: {<br>    &quot;city&quot;: &quot;Boston&quot;,<br>    &quot;week&quot;: 26,<br>    &quot;forecast&quot;: [<br>      {<br>        &quot;date&quot;: &quot;2022-10-24&quot;,<br>        &quot;date_epoch&quot;: 1666569600,<br>        &quot;stats&quot;: {<br>          &quot;day&quot;: {<br>            &quot;mintemp_f&quot;: 50,<br>            &quot;maxtemp_f&quot;: 68,<br>            &quot;humidity&quot;: 85<br>          }<br>        }<br>      }<br>    ]<br>  }<br>}</pre><p>This makes weekly querying for city a point lookup using the documentKey.</p><h3>(4) TimeSeries Queries (/report1, /report2 APIs)</h3><p>Now let’s examine the querying capabilities of the Stargate Document API via a set of TimeSeries queries for each report from <a href="https://medium.com/building-the-open-data-stack/leveraging-the-stargate-document-api-for-time-series-data-in-cassandra-870b732c1bcd#e777">here</a>. Want to try the queries yourself? They are available as a <a href="https://www.postman.com/datastax/workspace/stargate-cassandra/collection/24325908-23927518-65bd-4797-911b-e872931bb735">Postman collection</a> on the DataStax Teamspace on the Postman API Network.</p><h3>Report 1: Weekly temperature report by day for a given location and a given week</h3><p>Report 1 is a <em>point query using the primary key</em> on the data model from the developers’ point of view and exposed as <a href="https://medium.com/building-the-open-data-stack/leveraging-the-stargate-document-api-for-time-series-data-in-cassandra-870b732c1bcd#4899">/report1</a> API endpoint. For example, you could use the following query to query daily min and max temperatures for Boston for week 26.</p><pre>curl --location --request POST &#39;localhost:3000/api/report1&#39; \<br>--header &#39;Content-Type: application/json&#39; \<br>--data-raw &#39;{<br>    &quot;city&quot;: &quot;Seattle&quot;,<br>    &quot;date&quot;: &quot;2022-11-01&quot;<br>}&#39;</pre><p>The response to this query will look something like this:</p><pre>{<br>    &quot;forecast&quot;: [<br>        {<br>            &quot;date&quot;: &quot;2022-10-30&quot;,<br>            &quot;stats&quot;: {<br>                &quot;day&quot;: {<br>                    &quot;maxtemp_f&quot;: 53.2,<br>                    &quot;mintemp_f&quot;: 47.8<br>                }<br>            }<br>        },<br>        {<br>            &quot;date&quot;: &quot;2022-10-31&quot;,<br>            &quot;stats&quot;: {<br>                &quot;day&quot;: {<br>                    &quot;maxtemp_f&quot;: 55.2,<br>                    &quot;mintemp_f&quot;: 45.7<br>                }<br>            }<br>        },...<br>    ]<br>}</pre><p>The resulting plot in the app looks like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*MV084A7Pp8FLMK3O" /></figure><p>Figure 6: A graph showing a weekly temperature report</p><h3>Report 2: Weekly temperature comparison for two given locations and a given week</h3><p>Report 2 is a <em>bulk get with filters </em>example and exposed as <a href="https://medium.com/building-the-open-data-stack/leveraging-the-stargate-document-api-for-time-series-data-in-cassandra-870b732c1bcd#f214">/report2</a> API endpoint. For example, you could use the following query to get a weekly temperature comparison for Boston and Seattle for week 26.</p><pre>curl --location --request POST &#39;localhost:3000/api/report2&#39; \<br>--header &#39;Content-Type: application/json&#39; \<br>--data-raw &#39;{<br>    &quot;city1&quot;: &quot;London&quot;,<br>    &quot;city2&quot;: &quot;Seattle&quot;,<br>    &quot;date&quot;: &quot;2022-11-01&quot;<br>}&#39;</pre><p>The response to this query will look something like this:</p><pre>{<br>    &quot;forecast&quot;: [<br>        {<br>            &quot;date&quot;: &quot;2022-10-30&quot;,<br>            &quot;stats&quot;: {<br>            &quot;city1&quot;:<br>            {<br>                &quot;city&quot;: &quot;London&quot;,<br>                &quot;day&quot;: {<br>                    &quot;maxtemp_f&quot;: 53.2,<br>                    &quot;mintemp_f&quot;: 47.8<br>                }},<br>            &quot;city2&quot;:<br>            {<br>                &quot;city&quot;: &quot;Seattle&quot;,<br>                &quot;day&quot;: {<br>                    &quot;maxtemp_f&quot;: 43.1,<br>                    &quot;mintemp_f&quot;: 37.8<br>                }}<br>            }<br>        },<br>        {<br>            &quot;date&quot;: &quot;2022-10-31&quot;,<br>            &quot;stats&quot;: {<br>            &quot;city1&quot;:<br>            {<br>                &quot;city&quot;: &quot;London&quot;,<br>                &quot;day&quot;: {<br>                    &quot;maxtemp_f&quot;: 52.2,<br>                    &quot;mintemp_f&quot;: 45.8<br>                }},<br>            &quot;city2&quot;:<br>            {<br>                &quot;city&quot;: &quot;Seattle&quot;,<br>                &quot;day&quot;: {<br>                    &quot;maxtemp_f&quot;: 47.1,<br>                    &quot;mintemp_f&quot;: 39.8<br>                }}<br>            }<br>        },...<br>    ]<br>}</pre><h3>Report 3: Min and max temperatures for a location and a week</h3><p>Report 3 is an example of an <em>aggregation query </em>since you have to compute the min and max across the week. What we have stored is the min and max per day. As of today, aggregations are not supported by the <a href="https://dtsx.io/3F8G4Wq">Stargate Document API</a> and thus the onus lies on the client to do any aggregations. For example, to get the weekly min and max temperatures for Boston for week 26, the client would execute <a href="https://medium.com/building-the-open-data-stack/leveraging-the-stargate-document-api-for-time-series-data-in-cassandra-870b732c1bcd#4899">/report1</a> via the Document API to get the temperature values for the week and then compute the min and max locally.</p><h3>Time Series Related Improvements for the Stargate Document API</h3><p>Based on the analysis above, we can see several possible ways in which extending the Document API could support additional functionality and take on some of the work currently performed by the application:</p><ul><li>Support for aggregation querying functions on the returned documents.</li><li>Namespace and Collection level metadata. For example, the number of documents in a collection, the number of rows, or a list of distinct keys. This data could be useful for computing page sizes or deciding whether to retrieve data synchronously or asynchronously at runtime.</li><li>Server-side sorting on a specific field.</li><li>Precomputed key level aggregates — average, median, min/max, etc. during ingestion of the documents to Stargate.</li></ul><h3>Conclusion</h3><p>Time series is one of the compelling data models for Cassandra. It’s a natural fit for the big table data model and scales well under various variations. There are lots of machine-generated data these days, so there’s no shortage of use cases similar to the examples above. For those users, the problem of storing data at machine-generating speeds and still keeping it organized in a useful manner is no longer a challenge.</p><p>The Stargate Document API transforms Apache Cassandra into a Document DB, a full-fledged native JSON data service over Cassandra. With no upfront schema definition or data modeling, developers can handle unstructured, <a href="https://dtsx.io/3VxOMD2">semi-structured, and structured</a> JSON while leveraging Cassandra’s write speed, reliability, and scalability guarantees for a production-ready data store.</p><p>The Document API provides a wide range of write and query operators — for equality, range queries, array contains, server-side array push/pop. Additionally, the developers can also query at all the nested levels without local computations.</p><p><strong>Try this out on the Astra DB free plan in the </strong><a href="https://astra.datastax.com/sample-app-gallery/"><strong>sample app gallery</strong></a><strong>, or locally as a </strong><a href="https://github.com/DataStax-Examples/weatherapp"><strong>Node JS app</strong></a><strong>.</strong></p><p><em>Follow the </em><a href="https://dtsx.io/3ON2QGs"><em>DataStax Tech Blog</em></a><em> for more developer stories. Check our </em><a href="https://dtsx.io/3ON30h2"><em>YouTube</em></a><em> channel for tutorials and DataStax Developers on </em><a href="https://dtsx.io/3VeQc5C"><em>Twitter</em></a><em> for the latest news about our developer community.</em></p><h3>Resources</h3><ol><li><a href="https://dtsx.io/3OI9NZC">Data Modeling by Example: Time Series Data Model</a></li><li><a href="https://dtsx.io/3ikcC6X">Advanced Time Series Data Modelling</a></li><li><a href="https://thelastpickle.com/blog/2017/08/02/time-series-data-modeling-massive-scale.html">Time Series Modeling at Massive Scale</a></li><li><a href="https://dtsx.io/3iqN3Bq">DateTieredCompactionStrategy (DTCS)</a></li><li><a href="https://dtsx.io/3OHJZNj">On Demand Webinar: Time Series Data Management at Scale with Apache Cassandra™</a></li><li><a href="https://dtsx.io/3OKhWwt">Apache Cassandra and Timeseries: BFF’s?</a></li><li><a href="https://dtsx.io/3Vf7jnP">Join Stargate Discord</a></li><li><a href="https://dtsx.io/3VgZePH">Stargate Twitter</a></li><li><a href="https://dtsx.io/3ubpSNO">Stargate Github discussions</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=94795d8225b3" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>