{"id":55540,"date":"2026-09-24T14:39:51","date_gmt":"2026-09-24T21:39:51","guid":{"rendered":"https:\/\/www.griddb.net\/?p=55540"},"modified":"2026-09-30T14:44:27","modified_gmt":"2026-09-30T21:44:27","slug":"building-a-real-time-griddb-dashboard-for-factory-floor-monitoring","status":"publish","type":"post","link":"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/","title":{"rendered":"Building a Real-Time GridDB Dashboard for Factory Floor Monitoring"},"content":{"rendered":"<p>\nModern factory floors continuously generate streams of sensor data, including temperature, humidity, vibration and how much they are producing. On their own, each reading might not seem important. When you collect this data from many machines over a long time it is the best way for a factory to find problems early and avoid shutting down for a long time.\n<\/p>\n<p>\nThe main challenge is that this data is time-series: it is timestamped, arrives quickly, and is usually written once. Using a general-purpose relational table can work when there is not much data, but as you add more sensors and keep data longer, problems appear. Indexes get too large, range queries slow down, and deleting old data becomes difficult.\n<\/p>\n<p>\nThis post walks through a complete solution: a Java application that simulates readings from three factory sensors, stores them in <a href=\"https:\/\/www.griddb.net\/en\/\">GridDB<\/a>&#8216;s native <code>TimeSeries<\/code> containers, and serves a live web dashboard that displays rolling averages and threshold alerts in real time.\n<\/p>\n<p><a href=\"https:\/\/www.griddb.net\/en\/\">GridDB<\/a> is an open-source distributed NoSQL database purpose-built for IoT and time-series workloads. Its <code>TimeSeries<\/code> containers are optimized for exactly the shape of problem a sensor fleet like this one produces: high write throughput paired with efficient temporal queries.<\/p>\n<p>\n&#8212;\n<\/p>\n<h2 id=\"what-youll-learn\">What you&#8217;ll learn<\/h2>\n<p>\nBy the end of this tutorial, you&#8217;ll be able to:\n<\/p>\n<ul>\n<li>Set up a complete GridDB + Java environment using Docker Compose, with no local installation required<\/li>\n<li>Ingest time-series sensor data using GridDB&#8217;s <code>TimeSeries<\/code> containers and the <code>append()<\/code> method<\/li>\n<li>Query and analyze data with built-in aggregations (<code>AVG<\/code>, <code>MIN<\/code>, <code>MAX<\/code>) and TQL, GridDB&#8217;s SQL-like query language<\/li>\n<li>Visualize live data with a dashboard featuring sparklines, range gauges, and an alert log<\/li>\n<li>Deploy a pipeline that works on Windows, Mac, and Linux without host-networking issues<\/li>\n<\/ul>\n<p>\n&#8212;\n<\/p>\n<h2 id=\"prerequisites\">Prerequisites<\/h2>\n<ul>\n<li><strong>Docker<\/strong> and <strong>Docker Compose<\/strong> (Docker Desktop, with the WSL2 backend enabled if you&#8217;re on Windows)<\/li>\n<li><strong>Java 17<\/strong> and <strong>Maven<\/strong> \u2014 only needed if you want to build or modify the Java app outside of Docker; the provided <code>Dockerfile<\/code> handles both automatically if you&#8217;re just running the demo<\/li>\n<li><strong>Git<\/strong>, to clone the project repository<\/li>\n<li>No local GridDB installation is required \u2014 it runs entirely inside the Docker Compose stack<\/li>\n<\/ul>\n<p>\n&#8212;\n<\/p>\n<h2 id=\"project-structure\">Project structure<\/h2>\n<div class=\"clipboard\">\n<pre><code class=\"language-plaintext\">griddb-dashboard-demo\/\r\n\u251c\u2500\u2500 docker-compose.yml\r\n\u2514\u2500\u2500 app\/\r\n    \u251c\u2500\u2500 Dockerfile\r\n    \u251c\u2500\u2500 pom.xml\r\n    \u2514\u2500\u2500 src\/main\/\r\n        \u251c\u2500\u2500 java\/com\/example\/griddb\/\r\n        \u2502   \u251c\u2500\u2500 Main.java\r\n        \u2502   \u251c\u2500\u2500 GridDbConnection.java\r\n        \u2502   \u251c\u2500\u2500 SensorReading.java\r\n        \u2502   \u251c\u2500\u2500 SensorIngestor.java\r\n        \u2502   \u2514\u2500\u2500 DashboardServer.java\r\n        \u2514\u2500\u2500 resources\/\r\n            \u2514\u2500\u2500 dashboard.html<\/code><\/pre>\n<\/div>\n<p><code>docker-compose.yml<\/code> at the root wires the GridDB server and the Java app together on a shared Docker network. Everything under <code>app\/<\/code> is the Java side: the <code>Dockerfile<\/code> builds it, <code>pom.xml<\/code> declares the GridDB client dependency, and <code>dashboard.html<\/code> is the front end served directly by the Java app&#8217;s embedded HTTP server.<\/p>\n<p>\n&#8212;\n<\/p>\n<h2 id=\"why-a-time-series-database-here\">Why a time-series database here<\/h2>\n<p>\nGridDB is built around two container types: <code>Collection<\/code>, for general keyed data, and <code>TimeSeries<\/code>, which uses the row&#8217;s timestamp as its key and is optimized for exactly this append-heavy, time-ordered access pattern. For a monitoring use case, that means two things fall out almost for free:\n<\/p>\n<ul>\n<li><strong>Efficient aggregation over time windows.<\/strong> Asking &#8220;what was the average temperature for sensor 3 over the last 24 hours&#8221; is a single built-in aggregation call, not a hand-rolled <code>GROUP BY<\/code> over a timestamp column.<\/li>\n<li><strong>Natural isolation per device.<\/strong> Each sensor gets its own <code>TimeSeries<\/code> container, so a burst of writes from one noisy machine doesn&#8217;t contend with reads against another.<\/li>\n<\/ul>\n<p>\nIt is worth comparing this approach with a traditional relational database design. A common starting point for many IoT projects is to store all sensor readings in a single relational table containing columns such as <code>device_id<\/code>, <code>timestamp<\/code>, and the measured values, with indexes added to support time-range queries. While this approach works well for small-scale deployments, it becomes increasingly difficult to maintain as the number of devices, data ingestion rate, and retention period grow.\n<\/p>\n<p>\nAs sensor data grows, traditional relational databases become increasingly difficult to manage. Every new reading requires index updates, time-range queries must search ever-larger tables, and removing historical data often requires costly delete operations or custom partitioning strategies.\n<\/p>\n<p><a href=\"https:\/\/www.griddb.net\/en\/\">GridDB<\/a> is designed to address these challenges. Its native TimeSeries containers optimize sequential writes and time-based queries, while built-in row expiration automatically removes outdated data based on configurable retention policies. This reduces database maintenance and simplifies application development, making GridDB well suited for large-scale Industrial IoT and real-time monitoring applications.<\/p>\n<h3 id=\"griddb-compared-with-postgresql-and-influxdb\">GridDB Compared with PostgreSQL and InfluxDB<\/h3>\n<table class=\"markdown-table\" style=\"border-collapse: collapse; width: 100%; margin: 1em 0;\">\n<thead>\n<tr>\n<th style=\"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; text-align: left;\">Feature<\/th>\n<th style=\"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; text-align: left;\">GridDB<\/th>\n<th style=\"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; text-align: left;\">PostgreSQL<\/th>\n<th style=\"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; text-align: left;\">InfluxDB<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><strong>Native Time-Series Support<\/strong><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Yes<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Partial (via extensions such as TimescaleDB)<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Yes<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><strong>Horizontal Scaling<\/strong><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Yes<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Primarily vertical (distributed extensions available)<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Yes<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><strong>Query Language<\/strong><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">TQL (SQL-like)<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">SQL<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">InfluxQL \/ Flux<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><strong>Designed for Time-Series &#038; IoT<\/strong><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Yes<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">General-purpose database<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Yes<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><strong>ACID Transactions<\/strong><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Yes<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Yes<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Limited*<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><strong>Official Java Support<\/strong><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Official Java Client<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">JDBC<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Official Java Client<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><strong>Docker Support<\/strong><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Yes<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Yes<\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Yes<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\n> <strong>\\<\/strong>* InfluxDB provides durability and consistency for time-series workloads but does not implement full ACID transactional semantics across multiple records in the same way as traditional relational databases such as PostgreSQL.<br \/>\n&#8212;\n<\/p>\n<h2 id=\"architecture\">Architecture<\/h2>\n<p>\nThe system has four main components:\n<\/p>\n<p><a href=\"\/wp-content\/uploads\/2026\/09\/architecture-scaled.png\"><img fetchpriority=\"high\" decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/09\/architecture-scaled.png\" alt=\"\" width=\"2560\" height=\"660\" class=\"aligncenter size-full wp-image-55541\" srcset=\"\/wp-content\/uploads\/2026\/09\/architecture-scaled.png 2560w, \/wp-content\/uploads\/2026\/09\/architecture-300x77.png 300w, \/wp-content\/uploads\/2026\/09\/architecture-1024x264.png 1024w, \/wp-content\/uploads\/2026\/09\/architecture-768x198.png 768w, \/wp-content\/uploads\/2026\/09\/architecture-1536x396.png 1536w, \/wp-content\/uploads\/2026\/09\/architecture-2048x528.png 2048w, \/wp-content\/uploads\/2026\/09\/architecture-600x155.png 600w\" sizes=\"(max-width: 2560px) 100vw, 2560px\" \/><\/a><\/p>\n<ol>\n<li><strong>GridDB server<\/strong> \u2014 running in Docker, one container from the standard GridDB image.<\/li>\n<li><strong>A Java ingestion process<\/strong> \u2014 seeds historical data, then keeps appending a new reading every few seconds per simulated device.<\/li>\n<li><strong>An embedded HTTP API<\/strong> \u2014 built on the JDK&#8217;s built-in <code>com.sun.net.httpserver<\/code>, so there&#8217;s no extra web framework to configure. It exposes <code>\/api\/stats<\/code>, <code>\/api\/alerts<\/code>, and <code>\/api\/history<\/code>.<\/li>\n<li><strong>A dashboard page<\/strong> \u2014 polls those endpoints and renders a fleet summary strip, per-device panels with live sparkline trend lines and range gauges, and an alarm log.<\/li>\n<\/ol>\n<p>\nEverything ships in one <code>docker-compose.yml<\/code>, so <code>docker compose up --build<\/code> gets a full GridDB cluster and the Java app talking to each other on a bridge network.\n<\/p>\n<p>\nThe complete source \u2014 the <code>Dockerfile<\/code>, <code>docker-compose.yml<\/code>, and all Java classes \u2014 is on GitHub: <strong><a href=\"https:\/\/github.com\/dagmawit-sudo-cloud\/griddb-dashboard-demo\">dagmawit-sudo-cloud\/griddb-dashboard-demo<\/a><\/strong>.\n<\/p>\n<p>\nClone it now to follow along and run each step as you read.\n<\/p>\n<h3 id=\"data-flow-end-to-end\">Data flow, end to end<\/h3>\n<p><a href=\"\/wp-content\/uploads\/2026\/09\/dataflow-scaled.png\"><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/09\/dataflow-scaled.png\" alt=\"\" width=\"2131\" height=\"2560\" class=\"aligncenter size-full wp-image-55543\" srcset=\"\/wp-content\/uploads\/2026\/09\/dataflow-scaled.png 2131w, \/wp-content\/uploads\/2026\/09\/dataflow-250x300.png 250w, \/wp-content\/uploads\/2026\/09\/dataflow-852x1024.png 852w, \/wp-content\/uploads\/2026\/09\/dataflow-768x923.png 768w, \/wp-content\/uploads\/2026\/09\/dataflow-1279x1536.png 1279w, \/wp-content\/uploads\/2026\/09\/dataflow-1705x2048.png 1705w, \/wp-content\/uploads\/2026\/09\/dataflow-600x721.png 600w\" sizes=\"(max-width: 2131px) 100vw, 2131px\" \/><\/a><\/p>\n<p>\n&#8212;\n<\/p>\n<h2 id=\"why-docker\">Why Docker<\/h2>\n<p>\nDocker packages both GridDB and the Java application into isolated containers, so the exact same setup runs the same way regardless of whether it&#8217;s on your laptop, a teammate&#8217;s machine, or a CI pipeline \u2014 no &#8220;works on my machine&#8221; gap between installing GridDB natively and getting the Java client to find it.\n<\/p>\n<p>\nIt also sidesteps a real platform-specific headache: Docker Desktop on Windows and Mac doesn&#8217;t support host networking the way Linux does, so a Compose setup using a proper bridge network (as this one does) is the version that actually works cross-platform, rather than one that only works if you happen to be on Linux.\n<\/p>\n<p>\n&#8212;\n<\/p>\n<h2 id=\"modeling-a-sensor-reading\">Modeling a sensor reading<\/h2>\n<p>\nThe Java side talks to GridDB through its official Java Client API \u2014 the same supported <code>gridstore<\/code> library GridDB documents for production use, not a community wrapper or a raw protocol implementation. Every device writes rows shaped like this:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">public class SensorReading {\r\n    @RowKey Date timestamp;\r\n    String deviceId;\r\n    double temperature;\r\n    double humidity;\r\n    boolean alertTriggered;\r\n}<\/code><\/pre>\n<\/div>\n<p>\nThe <code>@RowKey<\/code> annotation on <code>timestamp<\/code> is what tells GridDB this class belongs in a <code>TimeSeries<\/code> container rather than a plain <code>Collection<\/code>. <code>alertTriggered<\/code> is computed at write time rather than derived later \u2014 efficient to compute once, and it lets the alerts endpoint run a simple boolean filter instead of recomputing a threshold check on every poll.\n<\/p>\n<h3 id=\"connecting-with-retry\">Connecting, with retry<\/h3>\n<p>\nDocker Compose starts containers in parallel, so the Java app frequently comes up before GridDB is actually ready to accept connections. The connection helper handles that with a bounded retry loop instead of failing hard on the first attempt:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">Properties props = new Properties();\r\nprops.setProperty(&quot;notificationMember&quot;, notificationMember);\r\nprops.setProperty(&quot;clusterName&quot;, clusterName);\r\nprops.setProperty(&quot;user&quot;, user);\r\nprops.setProperty(&quot;password&quot;, password);\r\n\r\nfor (int attempt = 1; attempt &lt;= maxAttempts; attempt++) {\r\n    try {\r\n        GridStore store = GridStoreFactory.getInstance().getGridStore(props);\r\n        System.out.println(&quot;Connected to GridDB at &quot; + notificationMember);\r\n        return store;\r\n    } catch (GSException e) {\r\n        System.out.println(&quot;Attempt &quot; + attempt + &quot;\/&quot; + maxAttempts +\r\n                &quot;: GridDB not ready yet (&quot; + e.getMessage() + &quot;), retrying in 5s...&quot;);\r\n        Thread.sleep(5000);\r\n    }\r\n}<\/code><\/pre>\n<\/div>\n<p>\nAll four connection properties \u2014 notification member, cluster name, user, password \u2014 are read from environment variables set in <code>docker-compose.yml<\/code>, which keeps the same image usable across dev and staging without a rebuild.\n<\/p>\n<p>\n> <strong>Tip:<\/strong> GridDB&#8217;s cluster takes 30\u201360 seconds to form after container startup. The retry loop ensures your application connects reliably even if it starts before the database is ready.\n<\/p>\n<h3 id=\"packaging-the-java-app\">Packaging the Java app<\/h3>\n<p>\nThe Java side builds as a two-stage Docker image, so the final container doesn&#8217;t carry a Maven install around at runtime:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-dockerfile\">FROM maven:3.9-eclipse-temurin-17 AS build\r\nWORKDIR \/build\r\nCOPY pom.xml .\r\nCOPY src .\/src\r\nRUN mvn -q clean package -DskipTests\r\n\r\nFROM eclipse-temurin:17-jre\r\nWORKDIR \/app\r\nCOPY --from=build \/build\/target\/app.jar app.jar\r\nEXPOSE 8080\r\nCMD [&quot;java&quot;, &quot;-jar&quot;, &quot;app.jar&quot;]<\/code><\/pre>\n<\/div>\n<p>\nThe build stage compiles the fat jar with Maven; the runtime stage starts from a bare JRE image and copies only the finished artifact across. The net effect is a noticeably smaller image and a faster <code>docker compose up<\/code> on the second run, since Docker&#8217;s layer cache skips the Maven download step entirely as long as <code>pom.xml<\/code> hasn&#8217;t changed.\n<\/p>\n<p><code>docker-compose.yml<\/code> wires this image up to the GridDB container on a dedicated bridge network and passes in the connection properties as environment variables, so the two containers can find each other by service name (<code>griddb-server:10001<\/code>) without any manual network configuration.<\/p>\n<p>\n&#8212;\n<\/p>\n<h2 id=\"generating-and-appending-data\">Generating and appending data<\/h2>\n<p>\nThe application supports two ingestion workflows: an initial historical data load to populate the dashboard and a continuous streaming process that appends new sensor readings as they are generated.\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">public static void ingest(GridStore store, String deviceId, int readingCount, double baseTemp) throws GSException {\r\n    TimeSeries&lt;SensorReading&gt; ts = store.putTimeSeries(deviceId, SensorReading.class);\r\n    for (int i = 0; i &lt; readingCount; i++) {\r\n        ts.append(buildReading(deviceId, baseTemp, new Random()));\r\n    }\r\n}<\/code><\/pre>\n<\/div>\n<p><code>append()<\/code> is the right call for time-series writes specifically \u2014 it assumes rows arrive in increasing timestamp order and skips the row-key lookup a generic <code>put()<\/code> would do, which matters once you&#8217;re writing thousands of readings a minute across many devices. The continuous variant runs the same <code>append()<\/code> call on a daemon thread every three seconds per device.<\/p>\n<p>\n&#8212;\n<\/p>\n<h2 id=\"querying-aggregates-and-alerts\">Querying: aggregates and alerts<\/h2>\n<p>\nThe stats endpoint leans on GridDB&#8217;s built-in aggregation functions rather than pulling raw rows into Java and averaging them by hand:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">Date now = TimestampUtils.current();\r\nDate oneDayAgo = TimestampUtils.add(now, -24, TimeUnit.HOUR);\r\n\r\ndouble avg = ts.aggregate(oneDayAgo, now, &quot;temperature&quot;, Aggregation.AVERAGE).getDouble();\r\ndouble min = ts.aggregate(oneDayAgo, now, &quot;temperature&quot;, Aggregation.MINIMUM).getDouble();\r\ndouble max = ts.aggregate(oneDayAgo, now, &quot;temperature&quot;, Aggregation.MAXIMUM).getDouble();<\/code><\/pre>\n<\/div>\n<p>\nThe alerts endpoint uses GridDB&#8217;s TQL query language instead, since it&#8217;s a row filter rather than an aggregate:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">Query&lt;SensorReading&gt; query = ts.query(&quot;WHERE alertTriggered&quot;, SensorReading.class);\r\nRowSet&lt;SensorReading&gt; rows = query.fetch();<\/code><\/pre>\n<\/div>\n<p>\n> <strong>TQL pitfall:<\/strong> For boolean fields, TQL allows conditions to be written directly as <code>WHERE alertTriggered<\/code>, which is the form used throughout this example.\n<\/p>\n<p>\nBoth endpoints return hand-built JSON strings over the JDK&#8217;s embedded <code>HttpServer<\/code>. That&#8217;s a deliberate simplification for a demo of this size \u2014 swap in your JSON library and framework of choice once the endpoint list grows past two.\n<\/p>\n<h3 id=\"api-endpoints\">API endpoints<\/h3>\n<table class=\"markdown-table\" style=\"border-collapse: collapse; width: 100%; margin: 1em 0;\">\n<thead>\n<tr>\n<th style=\"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; text-align: left;\">Method &#038; route<\/th>\n<th style=\"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; text-align: left;\">Purpose<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>GET \/api\/health<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Basic liveness check<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>GET \/api\/stats<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">Per-device avg\/min\/max\/reading count over the configured window<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>GET \/api\/alerts<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">The most recent threshold-breaching readings across all devices<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>GET \/api\/history?device=<id><\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">The last 40 readings for one device, oldest first \u2014 powers the sparkline trend line<\/td>\n<\/tr>\n<tr>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\"><code>GET \/<\/code><\/td>\n<td style=\"border: 1px solid #ddd; padding: 8px; text-align: left;\">The dashboard HTML page itself<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\n&#8212;\n<\/p>\n<h2 id=\"the-dashboard\">The dashboard<\/h2>\n<p>\nThe dashboard is implemented as a lightweight, static HTML page served directly by the Java application&#8217;s embedded HTTP server. The interface is designed to resemble an industrial control-room dashboard, providing operators with a clear, real-time view of factory conditions.\n<\/p>\n<p>\nEvery five seconds, the dashboard requests the latest data from the REST API and updates the display with three key monitoring components:\n<\/p>\n<ul>\n<li><strong>A fleet summary<\/strong> displays an overview of the monitored environment, including the number of active devices, the fleet-wide average temperature, and the current number of active alerts.<\/li>\n<li><strong>Device Monitoring panels<\/strong> present a dedicated panel for each sensor, featuring a status indicator, the latest sensor reading, a sparkline showing recent temperature trends, and a min\/max range gauge with a configurable alert threshold.<\/li>\n<li><strong>An alarm log<\/strong> displays the most recent threshold breaches and presents a clear empty state when no alerts have been triggered.<\/li>\n<\/ul>\n<p>\nThat five-second polling interval is a knob worth tuning in your own setup tighter for a control-room display, looser if you&#8217;re polling over a slow network link.\n<\/p>\n<p><a href=\"\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png\"><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png\" alt=\"\" width=\"1348\" height=\"633\" class=\"aligncenter size-full wp-image-55542\" srcset=\"\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png 1348w, \/wp-content\/uploads\/2026\/09\/dashboard-screenshot-300x141.png 300w, \/wp-content\/uploads\/2026\/09\/dashboard-screenshot-1024x481.png 1024w, \/wp-content\/uploads\/2026\/09\/dashboard-screenshot-768x361.png 768w, \/wp-content\/uploads\/2026\/09\/dashboard-screenshot-600x282.png 600w\" sizes=\"(max-width: 1348px) 100vw, 1348px\" \/><\/a><\/p>\n<p>\nA close-up of a single device panel, showing the sparkline trend line and the min\/max range gauge with the alert threshold marker.\n<\/p>\n<p><a href=\"\/wp-content\/uploads\/2026\/09\/device-panel-closeup.png\"><img loading=\"lazy\" decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/09\/device-panel-closeup.png\" alt=\"\" width=\"575\" height=\"358\" class=\"aligncenter size-full wp-image-55544\" srcset=\"\/wp-content\/uploads\/2026\/09\/device-panel-closeup.png 575w, \/wp-content\/uploads\/2026\/09\/device-panel-closeup-300x187.png 300w\" sizes=\"(max-width: 575px) 100vw, 575px\" \/><\/a><\/p>\n<p>\n&#8212;\n<\/p>\n<h2 id=\"running-it\">Running it<\/h2>\n<div class=\"clipboard\">\n<pre><code class=\"language-plaintext\">docker compose up --build<\/code><\/pre>\n<\/div>\n<p>\nThen open <code>http:\/\/localhost:8080<\/code>. Within a few seconds the device panels populate with live readings and trend lines, and if the simulated readings cross the alert threshold (27.5\u00b0C in this example), rows start appearing in the alarm log.\n<\/p>\n<p>\nTerminal output of <code>docker compose up --build<\/code> completing successfully, showing GridDB&#8217;s cluster starting and the Java app connecting.\n<\/p>\n<p><a href=\"\/wp-content\/uploads\/2026\/09\/docker-compose-terminal.png\"><img loading=\"lazy\" decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/09\/docker-compose-terminal.png\" alt=\"\" width=\"1025\" height=\"309\" class=\"aligncenter size-full wp-image-55545\" srcset=\"\/wp-content\/uploads\/2026\/09\/docker-compose-terminal.png 1025w, \/wp-content\/uploads\/2026\/09\/docker-compose-terminal-300x90.png 300w, \/wp-content\/uploads\/2026\/09\/docker-compose-terminal-768x232.png 768w, \/wp-content\/uploads\/2026\/09\/docker-compose-terminal-600x181.png 600w\" sizes=\"(max-width: 1025px) 100vw, 1025px\" \/><\/a><\/p>\n<p><code>docker ps<\/code> showing both containers \u2014 <code>griddb-server<\/code> and <code>griddb-java-app<\/code> \u2014 up and running on the shared bridge network.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2026\/09\/docker-containers-running.png\"><img loading=\"lazy\" decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/09\/docker-containers-running.png\" alt=\"\" width=\"1024\" height=\"134\" class=\"aligncenter size-full wp-image-55546\" srcset=\"\/wp-content\/uploads\/2026\/09\/docker-containers-running.png 1024w, \/wp-content\/uploads\/2026\/09\/docker-containers-running-300x39.png 300w, \/wp-content\/uploads\/2026\/09\/docker-containers-running-768x101.png 768w, \/wp-content\/uploads\/2026\/09\/docker-containers-running-600x79.png 600w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<h3 id=\"checking-the-api-directly\">Checking the API directly<\/h3>\n<p>\nIt&#8217;s worth hitting the endpoints on their own before trusting the dashboard, both to confirm the data looks right and as a sanity check while you&#8217;re adapting this to your own sensors:\n<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ curl http:\/\/localhost:8080\/api\/stats\r\n# [{&quot;deviceId&quot;:&quot;factory_floor_sensor_01&quot;,&quot;avg&quot;:26.84,&quot;min&quot;:24.02,&quot;max&quot;:31.97,&quot;count&quot;:118}, ...]\r\n\r\n$ curl http:\/\/localhost:8080\/api\/alerts\r\n# [{&quot;deviceId&quot;:&quot;factory_floor_sensor_01&quot;,&quot;timestamp&quot;:&quot;2026-07-01T14:22:09.441Z&quot;,&quot;temperature&quot;:29.13}, ...]<\/code><\/pre>\n<\/div>\n<p>\nBecause both routes set <code>Access-Control-Allow-Origin: *<\/code>, they&#8217;re also easy to point a separate front end or a tool like Grafana&#8217;s JSON API plugin at, if the bundled dashboard ends up being a placeholder for something more elaborate.\n<\/p>\n<p>\n&#8212;\n<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>\nGridDB&#8217;s native time-series support, high write throughput, and straightforward Docker integration make it a strong fit for factory monitoring: <code>TimeSeries<\/code> containers handle the append-heavy, time-ordered access pattern that sensor data naturally produces, without the index maintenance and partitioning work a general-purpose relational table would require at the same scale.\n<\/p>\n<p>\nThe full source for this project \u2014 the five Java classes, <code>Dockerfile<\/code>, and <code>docker-compose.yml<\/code> \u2014 is available on GitHub: <strong><a href=\"https:\/\/github.com\/dagmawit-sudo-cloud\/griddb-dashboard-demo\">dagmawit-sudo-cloud\/griddb-dashboard-demo<\/a><\/strong>.\n<\/p>\n<h2 id=\"references\">References<\/h2>\n<ol>\n<li>GridDB Java API Reference \u2013 https:\/\/www.griddb.net\/en\/resources\/griddb-java-api-reference\/<\/li>\n<li>GridDB GitHub Repository \u2013 https:\/\/github.com\/griddb\/griddb<\/li>\n<li>Docker Documentation \u2013 https:\/\/docs.docker.com\/<\/li>\n<li>Chart.js Documentation &#8211; https:\/\/www.chartjs.org\/docs\/latest\/<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Modern factory floors continuously generate streams of sensor data, including temperature, humidity, vibration and how much they are producing. On their own, each reading might not seem important. When you collect this data from many machines over a long time it is the best way for a factory to find problems early and avoid shutting [&hellip;]<\/p>\n","protected":false},"author":41,"featured_media":55542,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-55540","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Building a Real-Time GridDB Dashboard for Factory Floor Monitoring | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"Modern factory floors continuously generate streams of sensor data, including temperature, humidity, vibration and how much they are producing. On their\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building a Real-Time GridDB Dashboard for Factory Floor Monitoring | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"Modern factory floors continuously generate streams of sensor data, including temperature, humidity, vibration and how much they are producing. On their\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/\" \/>\n<meta property=\"og:site_name\" content=\"GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/griddbcommunity\/\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-24T21:39:51+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-30T21:44:27+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.griddb.net\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1348\" \/>\n\t<meta property=\"og:image:height\" content=\"633\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"griddb-admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:site\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"griddb-admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/\"},\"author\":{\"name\":\"griddb-admin\",\"@id\":\"https:\/\/www.griddb.net\/ja\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\"},\"headline\":\"Building a Real-Time GridDB Dashboard for Factory Floor Monitoring\",\"datePublished\":\"2026-09-24T21:39:51+00:00\",\"dateModified\":\"2026-09-30T21:44:27+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/\"},\"wordCount\":2014,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.griddb.net\/ja\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/\",\"url\":\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/\",\"name\":\"Building a Real-Time GridDB Dashboard for Factory Floor Monitoring | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\/\/www.griddb.net\/ja\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png\",\"datePublished\":\"2026-09-24T21:39:51+00:00\",\"dateModified\":\"2026-09-30T21:44:27+00:00\",\"description\":\"Modern factory floors continuously generate streams of sensor data, including temperature, humidity, vibration and how much they are producing. On their\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/#primaryimage\",\"url\":\"\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png\",\"contentUrl\":\"\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png\",\"width\":1348,\"height\":633},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.griddb.net\/ja\/#website\",\"url\":\"https:\/\/www.griddb.net\/ja\/\",\"name\":\"GridDB: Open Source Time Series Database for IoT\",\"description\":\"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL\",\"publisher\":{\"@id\":\"https:\/\/www.griddb.net\/ja\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.griddb.net\/ja\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.griddb.net\/ja\/#organization\",\"name\":\"Fixstars\",\"url\":\"https:\/\/www.griddb.net\/ja\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.griddb.net\/ja\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/griddb-linux-griddb-linux-clone-gnbah8a6f2fwd5eb.westus-01.azurewebsites.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"contentUrl\":\"https:\/\/griddb-linux-griddb-linux-clone-gnbah8a6f2fwd5eb.westus-01.azurewebsites.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"width\":200,\"height\":83,\"caption\":\"Fixstars\"},\"image\":{\"@id\":\"https:\/\/www.griddb.net\/ja\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/griddbcommunity\/\",\"https:\/\/x.com\/GridDBCommunity\",\"https:\/\/www.linkedin.com\/company\/griddb-by-toshiba\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.griddb.net\/ja\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\",\"name\":\"griddb-admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.griddb.net\/ja\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"caption\":\"griddb-admin\"},\"url\":\"https:\/\/www.griddb.net\/en\/author\/griddb-admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Building a Real-Time GridDB Dashboard for Factory Floor Monitoring | GridDB: Open Source Time Series Database for IoT","description":"Modern factory floors continuously generate streams of sensor data, including temperature, humidity, vibration and how much they are producing. On their","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/","og_locale":"en_US","og_type":"article","og_title":"Building a Real-Time GridDB Dashboard for Factory Floor Monitoring | GridDB: Open Source Time Series Database for IoT","og_description":"Modern factory floors continuously generate streams of sensor data, including temperature, humidity, vibration and how much they are producing. On their","og_url":"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2026-09-24T21:39:51+00:00","article_modified_time":"2026-09-30T21:44:27+00:00","og_image":[{"width":1348,"height":633,"url":"https:\/\/www.griddb.net\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png","type":"image\/png"}],"author":"griddb-admin","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"griddb-admin","Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/#article","isPartOf":{"@id":"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/"},"author":{"name":"griddb-admin","@id":"https:\/\/www.griddb.net\/ja\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233"},"headline":"Building a Real-Time GridDB Dashboard for Factory Floor Monitoring","datePublished":"2026-09-24T21:39:51+00:00","dateModified":"2026-09-30T21:44:27+00:00","mainEntityOfPage":{"@id":"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/"},"wordCount":2014,"commentCount":0,"publisher":{"@id":"https:\/\/www.griddb.net\/ja\/#organization"},"image":{"@id":"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/","url":"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/","name":"Building a Real-Time GridDB Dashboard for Factory Floor Monitoring | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/www.griddb.net\/ja\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/#primaryimage"},"image":{"@id":"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png","datePublished":"2026-09-24T21:39:51+00:00","dateModified":"2026-09-30T21:44:27+00:00","description":"Modern factory floors continuously generate streams of sensor data, including temperature, humidity, vibration and how much they are producing. On their","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.griddb.net\/en\/blog\/building-a-real-time-griddb-dashboard-for-factory-floor-monitoring\/#primaryimage","url":"\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png","contentUrl":"\/wp-content\/uploads\/2026\/09\/dashboard-screenshot.png","width":1348,"height":633},{"@type":"WebSite","@id":"https:\/\/www.griddb.net\/ja\/#website","url":"https:\/\/www.griddb.net\/ja\/","name":"GridDB: Open Source Time Series Database for IoT","description":"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL","publisher":{"@id":"https:\/\/www.griddb.net\/ja\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.griddb.net\/ja\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.griddb.net\/ja\/#organization","name":"Fixstars","url":"https:\/\/www.griddb.net\/ja\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.griddb.net\/ja\/#\/schema\/logo\/image\/","url":"https:\/\/griddb-linux-griddb-linux-clone-gnbah8a6f2fwd5eb.westus-01.azurewebsites.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","contentUrl":"https:\/\/griddb-linux-griddb-linux-clone-gnbah8a6f2fwd5eb.westus-01.azurewebsites.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","width":200,"height":83,"caption":"Fixstars"},"image":{"@id":"https:\/\/www.griddb.net\/ja\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/griddbcommunity\/","https:\/\/x.com\/GridDBCommunity","https:\/\/www.linkedin.com\/company\/griddb-by-toshiba"]},{"@type":"Person","@id":"https:\/\/www.griddb.net\/ja\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233","name":"griddb-admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.griddb.net\/ja\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","caption":"griddb-admin"},"url":"https:\/\/www.griddb.net\/en\/author\/griddb-admin\/"}]}},"_links":{"self":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/55540","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/comments?post=55540"}],"version-history":[{"count":3,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/55540\/revisions"}],"predecessor-version":[{"id":55549,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/55540\/revisions\/55549"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media\/55542"}],"wp:attachment":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media?parent=55540"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/categories?post=55540"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/tags?post=55540"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}