{"id":52180,"date":"2025-07-09T00:00:00","date_gmt":"2025-07-09T07:00:00","guid":{"rendered":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/"},"modified":"2025-07-09T00:00:00","modified_gmt":"2025-07-09T07:00:00","slug":"griddb-for-environmental-monitoring-in-smart-cities","status":"publish","type":"post","link":"https:\/\/griddb.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/","title":{"rendered":"GridDB for Environmental Monitoring in Smart Cities"},"content":{"rendered":"<h2><strong>Introduction<\/strong><\/h2>\n<p>Smart cities are transforming urban landscapes by leveraging technology to improve efficiency and sustainability. A key component of smart cities is environmental monitoring, which involves the collection, aggregation, and analysis of real-time data to address challenges like air pollution, traffic congestion, and resource management. By leveraging innovative database technologies, smart cities can unlock actionable insights that drive sustainability and improve urban living standards.<\/p>\n<p>This article delves into how GridDB, a high-performance database tailored for time-series and IoT data, supports environmental monitoring in smart cities. Using real-time data streams like pollen levels, illness risk metrics, and air quality indices, we showcase how GridDB effectively manages large data volumes with speed and precision, empowering informed decision-making for a smarter, more sustainable urban future.<\/p>\n<h4>Understanding the Use Case<\/h4>\n<p>To demonstrate a practical application, we integrate environmental data from <strong><a href=\"https:\/\/www.getambee.com\/\">Ambee<\/a><\/strong>, a trusted provider of real-time environmental information. Using GridDB\u2019s robust capabilities, we aggregate and analyze this data, uncovering patterns and insights that can guide policymakers and stakeholders in enhancing urban sustainability.<\/p>\n<p>In this article, we focus on three specific datasets crucial for smart city management:<\/p>\n<ol>\n<li>\n<p><strong>Pollen Data<\/strong>: This dataset tracks allergen levels to predict periods of heightened allergy risks, enabling authorities to issue timely health advisories.<\/p>\n<\/li>\n<li>\n<p><strong>Illness Risk Data<\/strong>: By analyzing environmental conditions, this dataset assesses the probability of disease outbreaks, aiding public health planning.<\/p>\n<\/li>\n<li>\n<p><strong>Air Quality Data<\/strong>: Monitoring pollutants such as PM2.5, PM10, and NO2 ensures compliance with health standards and helps mitigate pollution\u2019s impact on urban life.<\/p>\n<\/li>\n<\/ol>\n<p>Together, these datasets, sourced from <a href=\"https:\/\/www.getambee.com\/\">Ambee<\/a>, serve as the basis for our study, highlighting the potential of GridDB for real-time environmental monitoring and data-driven decision-making.<\/p>\n<h4>Setting Up GridDB Cluster and Spring Boot Integration: For Environmental Monitoring<\/h4>\n<p>The first step is to set up a GridDB cluster and integrate it with our Spring Boot application as follows.<\/p>\n<ul>\n<li>\n<p><strong>Setting up GridDB Cluster<\/strong><\/p>\n<p>GridDB provides flexible options to meet different requirements. For development, a single-node cluster on our local machine may be sufficient. However, in production, distributed clusters across multiple machines are typically preferred for improved fault tolerance and scalability. For detailed guidance on setting up clusters based on our deployment strategy, refer to the GridDB documentation.<\/p>\n<p>To set up a GridDB cluster, follow the steps mentioned <a href=\"https:\/\/docs.griddb.net\/gettingstarted\/using-apt\/#install-with-apt-get\">here<\/a>.<\/p>\n<\/li>\n<li>\n<p><strong>Setting up Spring Boot Application<\/strong><\/p>\n<p>Once our GridDB cluster is operational, the next step is connecting it to ourSpring Boot application. The GridDB Java Client API provides the necessary tools to establish this connection. To simplify the process, you can include the <code>griddb-spring-boot-starter<\/code> library as a dependency in our project, which offers pre-configured beans for a streamlined connection setup.\u00a0\u00a0\u00a0<\/p>\n<\/li>\n<li>\n<p><strong>Setting Up API Access<\/strong><\/p>\n<p>To begin, visit <a href=\"https:\/\/www.getambee.com\/\">www.getambee.com<\/a> and create an account. After registering, you&#8217;ll be provided with an API key, which is required for authentication when making requests to their endpoints. This key grants access to various environmental data services offered by the platform. \u00a0<\/p>\n<h4>Pricing Plans<\/h4>\n<p><a href=\"https:\/\/www.getambee.com\/\">Ambee <\/a>offers flexible pricing plans to suit different needs:<\/p>\n<ul>\n<li><strong>Free Tier<\/strong>: Ideal for developers or small-scale projects, with limited API calls per month.<\/li>\n<li><strong>Paid Plans<\/strong>: Designed for larger-scale applications, these plans provide higher API limits and additional features.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong>Project Structure<\/strong><\/p>\n<p>Here&#8217;s a suggested project structure for this application:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">\u2514\u2500\u2500\u2500my-griddb-app\n    \u2502   pom.xml\n    \u2502   \n    \u251c\u2500\u2500\u2500src\n    \u2502   \u251c\u2500\u2500\u2500main\n    \u2502   \u2502   \u251c\u2500\u2500\u2500java\n    \u2502   \u2502   \u2502   \u2514\u2500\u2500\u2500mycode\n    \u2502   \u2502   \u2502       \u2502   MySpringBootApplication.java\n    \u2502   \u2502   \u2502       \u2502   \n    \u2502   \u2502   \u2502       \u251c\u2500\u2500\u2500config\n    \u2502   \u2502   \u2502       \u2502       GridDBConfig.java\n    \u2502   \u2502   \u2502       \u2502       \n    \u2502   \u2502   \u2502       \u251c\u2500\u2500\u2500controller\n    \u2502   \u2502   \u2502       \u2502       ChartController.java\n    \u2502   \u2502   \u2502       \u2502       \n    \u2502   \u2502   \u2502       \u251c\u2500\u2500\u2500dto\n    \u2502   \u2502   \u2502       \u2502       AirQualityDTO.java\n    \u2502   \u2502   \u2502       \u2502       IllnessRiskDTO.java\n    \u2502   \u2502   \u2502       \u2502       PollenDataDTO.java\n    \u2502   \u2502   \u2502       \u2502       \n    \u2502   \u2502   \u2502       \u2514\u2500\u2500\u2500service\n    \u2502   \u2502   \u2502               ChartService.java\n    \u2502   \u2502   \u2502               MetricsCollectionService.java\n    \u2502   \u2502   \u2502               RestTemplateConfig.java\n    \u2502   \u2502   \u2502\n    \u2502   \u2502   \u2514\u2500\u2500\u2500resources\n    \u2502   \u2502       \u2502   application.properties\n    \u2502   \u2502       \u2502   \n    \u2502   \u2502       \u2514\u2500\u2500\u2500templates\n    \u2502   \u2502               charts.html\n    \u2502   \u2502\n    \u2502   \u2514\u2500\u2500\u2500test\n    \u2502       \u2514\u2500\u2500\u2500java\n    \u2502           \u2514\u2500\u2500\u2500com\n    \u2502               \u2514\u2500\u2500\u2500example\n    \u2502                       AppTest.java<\/code><\/pre>\n<\/div>\n<p>This structure separates controllers, models, repositories, services, and the application entry point into distinct layers, enhancing modularity and maintainability.<\/p>\n<p><strong>Add GridDB Dependency<\/strong><\/p>\n<p>To enable interaction with GridDB in our Spring Boot project, we must include the GridDB Java Client API dependency. This can be accomplished by adding the appropriate configuration to the project build file, such as <code>pom.xml<\/code> for Maven or the equivalent file for Gradle.<\/p>\n<p>Here&#8217;s an example of how to configure the dependency in the<code>pom.xml<\/code> file:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-bash\">&lt;project \n  xmlns_xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n  xsi_schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/maven-v4_0_0.xsd\"&gt;\n  &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n  &lt;groupId&gt;com.example&lt;\/groupId&gt;\n  &lt;artifactId&gt;my-griddb-app&lt;\/artifactId&gt;\n  &lt;version&gt;1.0-SNAPSHOT&lt;\/version&gt;\n  &lt;name&gt;my-griddb-app&lt;\/name&gt;\n  &lt;url&gt;http:\/\/maven.apache.org&lt;\/url&gt;\n\n  &lt;parent&gt;\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-boot-starter-parent&lt;\/artifactId&gt;\n    &lt;version&gt;3.2.4&lt;\/version&gt;\n    &lt;relativePath \/&gt; &lt;!-- lookup parent from repository --&gt;\n  &lt;\/parent&gt;\n\n  &lt;properties&gt;\n    &lt;maven.compiler.source&gt;17&lt;\/maven.compiler.source&gt;\n    &lt;maven.compiler.target&gt;17&lt;\/maven.compiler.target&gt;\n  &lt;\/properties&gt;\n\n  &lt;dependencies&gt;\n    &lt;dependency&gt;\n      &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n      &lt;artifactId&gt;spring-boot-starter-actuator&lt;\/artifactId&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n      &lt;groupId&gt;junit&lt;\/groupId&gt;\n      &lt;artifactId&gt;junit&lt;\/artifactId&gt;\n      &lt;version&gt;3.8.1&lt;\/version&gt;\n      &lt;scope&gt;test&lt;\/scope&gt;\n    &lt;\/dependency&gt;\n    &lt;!-- GridDB dependencies --&gt;\n    &lt;dependency&gt;\n      &lt;groupId&gt;com.github.griddb&lt;\/groupId&gt;\n      &lt;artifactId&gt;gridstore&lt;\/artifactId&gt;\n      &lt;version&gt;5.6.0&lt;\/version&gt;\n    &lt;\/dependency&gt;\n    &lt;!-- Spring Boot dependencies --&gt;\n    &lt;dependency&gt;\n      &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n      &lt;artifactId&gt;spring-boot-starter-web&lt;\/artifactId&gt;\n      &lt;exclusions&gt;\n        &lt;exclusion&gt;\n          &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n          &lt;artifactId&gt;spring-boot-starter-logging&lt;\/artifactId&gt;\n        &lt;\/exclusion&gt;\n      &lt;\/exclusions&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n      &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n      &lt;artifactId&gt;spring-boot-starter-test&lt;\/artifactId&gt;\n      &lt;scope&gt;test&lt;\/scope&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n      &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n      &lt;artifactId&gt;spring-boot-starter-thymeleaf&lt;\/artifactId&gt;\n    &lt;\/dependency&gt;\n    &lt;!-- JSON processing --&gt;\n    &lt;dependency&gt;\n      &lt;groupId&gt;com.fasterxml.jackson.core&lt;\/groupId&gt;\n      &lt;artifactId&gt;jackson-databind&lt;\/artifactId&gt;\n      &lt;version&gt;2.15.0&lt;\/version&gt; &lt;!-- or the latest version --&gt;\n    &lt;\/dependency&gt;\n    &lt;!-- Lombok --&gt;\n    &lt;dependency&gt;\n      &lt;groupId&gt;org.projectlombok&lt;\/groupId&gt;\n      &lt;artifactId&gt;lombok&lt;\/artifactId&gt;\n      &lt;optional&gt;true&lt;\/optional&gt;\n    &lt;\/dependency&gt;\n  &lt;\/dependencies&gt;\n&lt;\/project&gt;<\/code><\/pre>\n<\/div>\n<p><strong>Configure GridDB Connection<\/strong><\/p>\n<p>After adding the GridDB dependency, the next step is configuring the connection details for our GridDB cluster in our Spring Boot application. This is usually configured in the <code>application.properties<\/code> file, where you can specify various settings for the application.<\/p>\n<p>Here\u2019s a quick example of how to set up those connection details:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-bash\">GRIDDB_NOTIFICATION_MEMBER=127.0.0.1:10001\nGRIDDB_CLUSTER_NAME=myCluster\nGRIDDB_USER=admin\nGRIDDB_PASSWORD=admin\nmanagement.endpoints.web.exposure.include=*\nserver.port=9090\n#API token \napi.token=&lt;enter your API Key>&lt;\/enter><\/code><\/pre>\n<\/div>\n<ul>\n<li>\n<p><code>griddb.cluster.port<\/code>: The port number on which the GridDB cluster is listening.<\/p>\n<\/li>\n<li>\n<p><code>griddb.cluster.user<\/code>: The username for accessing the GridDB cluster.<\/p>\n<\/li>\n<li>\n<p><code>griddb.cluster.password<\/code>: The password for the specified GridDB user (replace with ouractual password).<\/p>\n<\/li>\n<li>\n<p><code>server.port=9090<\/code>: Sets the port on which ourSpring Boot application will run.<\/p>\n<\/li>\n<li>\n<p><code>api.token<\/code> : API token for authentication purposes.<\/p>\n<\/li>\n<\/ul>\n<p><strong>Create GridDB Client Bean<\/strong><\/p>\n<p>To interact effectively with GridDB in our Spring Boot application,we need to create a dedicated Spring Bean to manage the GridDB connection. This bean will establish the connection using the parameters defined in the <code>application.properties<\/code> file and will act as the central interface for interacting with the GridDB cluster across the application.<\/p>\n<p>Here&#8217;s an example of how to define this bean in a Java class named <code>GridDbConfig.java<\/code>:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">package mycode.config;\n\nimport java.util.Properties;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.PropertySource;\n\nimport com.toshiba.mwcloud.gs.GSException;\nimport com.toshiba.mwcloud.gs.GridStore;\nimport com.toshiba.mwcloud.gs.GridStoreFactory;\n\n@Configuration\n@PropertySource(\"classpath:application.properties\")\npublic class GridDBConfig {\n\n @Value(\"${GRIDDB_NOTIFICATION_MEMBER}\")\n\u00a0 private String notificationMember;\n\n @Value(\"${GRIDDB_CLUSTER_NAME}\")\n\u00a0 private String clusterName;\n\n @Value(\"${GRIDDB_USER}\")\n\u00a0 private String user;\n\n @Value(\"${GRIDDB_PASSWORD}\")\n\u00a0 private String password;\n\n @Bean\n\u00a0 public GridStore gridStore() throws GSException {\n\u00a0 \u00a0 \/\/ Acquiring a GridStore instance\n\u00a0 \u00a0 Properties properties = new Properties();\n\u00a0 \u00a0 properties.setProperty(\"notificationMember\", notificationMember);\n\u00a0 \u00a0 properties.setProperty(\"clusterName\", clusterName);\n\u00a0 \u00a0 properties.setProperty(\"user\", user);\n\u00a0 \u00a0 properties.setProperty(\"password\", password);\n\u00a0 \u00a0 return GridStoreFactory.getInstance().getGridStore(properties);\n }\n}<\/code><\/pre>\n<\/div>\n<h2>Metric Collection<\/h2>\n<p>Our primary focus is on the <code>MetricCollection.java<\/code> class, where API calls to external services are made, and the collected data is processed and stored. This class serves as a bridge between the external APIs and the backend system, ensuring seamless integration with GridDB for real-time analytics and decision-making.<\/p>\n<p>Ambee provides a rich set of endpoints to fetch real-time environmental data. For this project, we\u2019ll focus on the following key endpoints:<\/p>\n<ul>\n<li>\n<p><strong>Pollen Data API<\/strong>:<br \/>\nThis endpoint provides allergen levels for specific locations, helping to monitor pollen concentrations and predict allergy outbreaks. It is essential for public health, as it allows authorities to issue timely advisories for people with respiratory conditions or allergies.<\/p>\n<\/li>\n<li>\n<p><strong>Air Quality API<\/strong>:<br \/>\nThis API provides data on various pollutants such as PM2.5, PM10, CO, and NO2. Monitoring air quality is crucial for ensuring compliance with health standards and mitigating pollution\u2019s impact on public health. It helps cities take proactive steps in reducing pollution and protecting residents&#8217; well-being.<\/p>\n<\/li>\n<li>\n<p><strong>Illness Risk API<\/strong>:<br \/>\nThis endpoint returns calculated risk scores based on environmental conditions such as pollution levels, temperature, and humidity. It plays a critical role in public health, enabling early detection of potential health risks and informing decisions on preventive measures to reduce illness outbreaks in urban areas.<\/p>\n<\/li>\n<\/ul>\n<p>All above APIs use RESTful architecture and return responses in JSON format.<\/p>\n<h3>Key Components of the MetricCollection.java Class<\/h3>\n<ul>\n<li>\n<p><strong>API Key Management<\/strong>: The API key is injected into the service via the <code>@Value<\/code> annotation. This allows the project to securely access the external Ambee API services without hardcoding sensitive credentials directly into the codebase.<\/p>\n<\/li>\n<li>\n<p><strong>RestTemplate for API Calls<\/strong>: The <code>RestTemplate<\/code> object is used for making HTTP requests. It simplifies the process of invoking REST APIs and handling the response data. We are using <code>restTemplate.getForObject()<\/code> to fetch JSON data from the APIs and return it as a string. This data can then be processed or converted into a more structured format, like objects or entities, for further analysis.<\/p>\n<\/li>\n<li>\n<p><strong>Data Storage in GridDB<\/strong>:<br \/>\nThe environmental data fetched from the APIs is stored in GridDB&#8217;s time-series containers for efficient management and querying. Here&#8217;s how the data is persisted:<\/p>\n<ul>\n<li>\n<p><strong>Pollen Data<\/strong>:<br \/>\nA time-series container named <code>\"PollenData\"<\/code> is created using the <code>PollenDataDTO<\/code> class. Each data entry is appended to this container.<\/p>\n<\/li>\n<li>\n<p><strong>Illness Risk Data<\/strong>:<br \/>\nA similar container, <code>\"IllnessRiskData\"<\/code>, is created for storing data related to contamination risks using the <code>IllnessRiskDTO<\/code> class.<\/p>\n<\/li>\n<li>\n<p><strong>Air Quality Data<\/strong>:<br \/>\nAnother time-series container, <code>\"AirQualityData\"<\/code>, is set up for storing air quality metrics using the <code>AirQualityDTO<\/code> class.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>Fetching and Processing the Data<\/h4>\n<p>Each method in the <code>MetricCollection.java<\/code> class is designed to collect specific environmental data:<\/p>\n<ul>\n<li>\n<p><strong>Air Quality<\/strong>: The <code>getAirQualityData<\/code> method is responsible for fetching real-time air quality data for a given city. It contacts the Ambee air quality API and retrieves the data in JSON format.<\/p>\n<\/li>\n<li>\n<p><strong>Pollen Data<\/strong>: Similarly, the <code>getPollenData<\/code> method makes a request to the Ambee pollen API to gather pollen data, which is vital for assessing allergens in the air, particularly for individuals with respiratory conditions.<\/p>\n<\/li>\n<li>\n<p><strong>Illness Risk<\/strong>: The <code>getIllnessRiskData<\/code> method provides critical insights into potential health risks caused by environmental factors such as pollution levels or seasonal changes, allowing for proactive health management.<\/p>\n<\/li>\n<\/ul>\n<h4>Data Transformation<\/h4>\n<p>After retrieving the raw JSON data, it can be parsed and converted into Java objects for streamlined processing. By mapping the JSON response to custom Java classes, such as <code>AirQualityDTO<\/code>, <code>IllnessRiskDTO<\/code>, and <code>PollenDataDTO<\/code>, the data becomes easier to manage and transform within the system for further analysis and visualization.<\/p>\n<p>Below is the implementation of these DTO classes.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class AirQualityDTO {\n  @RowKey\n  public Date updatedAt;\n  private double lat;\n  private double lng;\n  private String city;\n  private String state;\n  private double pm10;\n  private double pm25;\n  private double no2;\n  private double so2;\n  private double co;\n  private double ozone;\n  private int aqi;\n  private String pollutant;\n  private double concentration;\n  private String category;\n}<\/code><\/pre>\n<\/div>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IllnessRiskDTO {\n  @RowKey\n  public Date createdAt;\n  private double lat;\n  private double lng;\n  private String iliRisk;\n}<\/code><\/pre>\n<\/div>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class PollenDataDTO {\n  @RowKey\n  public Date updatedAt;\n  private double lat;\n  private double lng;\n  private String grassPollenRisk;\n  private String treePollenRisk;\n  private String weedPollenRisk;\n  private int grassPollenCount;\n  private int treePollenCount;\n  private int weedPollenCount;\n}<\/code><\/pre>\n<\/div>\n<h4>Storing Data in GridDB<\/h4>\n<p>After transforming the data into Java objects, it is stored in GridDB for real-time querying and analysis.<\/p>\n<p>Here\u2019s a brief snippet of how the data insertion look:<\/p>\n<h5>Scheduling Data Collection<\/h5>\n<p>To ensure the data is regularly collected, you can use Spring Boot&#8217;s <code>@Scheduled<\/code> annotation to trigger API calls at fixed intervals. This makes sure the data is updated regularly to support real-time monitoring and analytics.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">  @Scheduled(fixedRate = 4000)\n  public void collectMetrics() throws GSException, JsonMappingException, JsonProcessingException, ParseException {\n\n    List&lt;pollendatadto> pollenData = fetchPollenData();\n    List&lt;illnessriskdto> illnessRiskData = fetchIllnessRiskData();\n    List&lt;airqualitydto> airQualityData = fetchAirQualityData();\n\n    \/\/ Store Pollen Data\n    TimeSeries&lt;pollendatadto> pollenSeries = store.putTimeSeries(\"PollenData\", PollenDataDTO.class);\n    for (PollenDataDTO data : pollenData) {\n      pollenSeries.append(data);\n    }\n\n    \/\/ Store Illness Risk Data\n    TimeSeries&lt;illnessriskdto> illnessRiskSeries = store.putTimeSeries(\"IllnessRiskData\", IllnessRiskDTO.class);\n    for (IllnessRiskDTO data : illnessRiskData) {\n      illnessRiskSeries.append(data);\n    }\n\n    \/\/ Store Air Quality Data\n    TimeSeries&lt;airqualitydto> airQualitySeries = store.putTimeSeries(\"AirQualityData\", AirQualityDTO.class);\n    for (AirQualityDTO data : airQualityData) {\n      airQualitySeries.append(data);\n    }\n  }&lt;\/airqualitydto>&lt;\/illnessriskdto>&lt;\/pollendatadto>&lt;\/airqualitydto>&lt;\/illnessriskdto>&lt;\/pollendatadto><\/code><\/pre>\n<\/div>\n<p>By following above steps, we can effectively extract data from <a href=\"https:\/\/www.getambee.com\/\">Ambee<\/a>, load it into GridDB database.<\/p>\n<h2><strong>Data Querying in GridDB and Visualization with Thymeleaf<\/strong><\/h2>\n<p>Once the data is stored and available in GridDB, the next step is to visualize this data in a way that provides actionable insights.<\/p>\n<p>In this section, we\u2019ll explore how to build a dashboard using Spring Boot, <code>Thymeleaf<\/code>, and <code>Chart.js<\/code> to render charts that displays realtime environment data.<\/p>\n<p>Here are the steps to achieve this:<\/p>\n<ul>\n<li><strong>Building the Chart Controller<\/strong><\/li>\n<\/ul>\n<p>The <code>ChartController<\/code> acts as the intermediary between backend data in GridDB and the frontend visualizations displayed on the dashboard. Its responsibilities include handling HTTP requests, interacting with the service layer to fetch data, and passing that data to Thymeleaf templates for rendering.<\/p>\n<p>Here\u2019s how the <code>ChartController<\/code> is implemented:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">package mycode.controller;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.GetMapping;\n\nimport mycode.service.ChartService;\nimport mycode.dto.AirQualityDTO;\nimport mycode.dto.IllnessRiskDTO;\nimport mycode.dto.PollenDataDTO;\n\nimport java.util.List;\n\n@Controller\npublic class ChartController {\n\n  @Autowired\n  private ChartService chartService;\n\n  @GetMapping(\"\/charts\")\n  public String showCharts(Model model) {\n    try {\n      \/\/ Fetch data for charts\n      List&lt;pollendatadto> pollenData = chartService.getPollenData();\n      List&lt;illnessriskdto> illnessRiskData = chartService.getIllnessRiskData();\n      List&lt;airqualitydto> airQualityData = chartService.getAirQualityData();\n\n      \/\/ Add data to the model for Thymeleaf\n      model.addAttribute(\"pollenData\", pollenData);\n      model.addAttribute(\"illnessRiskData\", illnessRiskData);\n      model.addAttribute(\"airQualityData\", airQualityData);\n    } catch (Exception e) {\n      model.addAttribute(\"error\", \"Unable to fetch data: \" + e.getMessage());\n    }\n\n    return \"charts\";\n  }\n}&lt;\/airqualitydto>&lt;\/illnessriskdto>&lt;\/pollendatadto><\/code><\/pre>\n<\/div>\n<ul>\n<li><strong>Implementing the Chart Service<\/strong><\/li>\n<\/ul>\n<p>The <code>ChartService<\/code> acts as the business logic layer, encapsulating the operations needed to query GridDB and process the results.<\/p>\n<p>In this context, the <code>ChartService<\/code> class accesses a GridStore database container to retrieve environmental monitoring data. The service then compiles these objects into a list representing the environmental metrics, ready for use in analysis or visualization.<\/p>\n<p>Here&#8217;s how the <code>ChartService<\/code> is implemented:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-java\">package mycode.service;\n\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport com.toshiba.mwcloud.gs.Container;\nimport com.toshiba.mwcloud.gs.GridStore;\nimport com.toshiba.mwcloud.gs.Query;\nimport com.toshiba.mwcloud.gs.Row;\nimport com.toshiba.mwcloud.gs.RowSet;\nimport com.toshiba.mwcloud.gs.TimeSeries;\n\nimport mycode.dto.AirQualityDTO;\nimport mycode.dto.IllnessRiskDTO;\nimport mycode.dto.PollenDataDTO;\n\n@Service\npublic class ChartService {\n\n  @Autowired\n  GridStore store;\n\n  public List&lt;pollendatadto> getPollenData() throws Exception {\n    Container<?, Row> container = store.getContainer(\"PollenData\");\n    if (container == null) {\n      throw new Exception(\"PollenData container not found.\");\n    }\n\n    List&lt;\/pollendatadto>&lt;pollendatadto> pollenDataList = new ArrayList&lt;>();\n    SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\");\n    Date now = new Date();\n    String nowString = dateFormat.format(now);\n    String startTime = \"1971-12-23T18:18:52.000Z\";\n\n    String queryString = \"select * where updatedAt >= TIMESTAMP('\" + startTime\n        + \"') and UpdatedAt &lt;= TIMESTAMP('\" + nowString + \"')\";\n    Query&lt;row> query = container.query(queryString);\n    RowSet&lt;\/row>&lt;row> rs = query.fetch();\n\n    while (rs.hasNext()) {\n      Row row = rs.next();\n      PollenDataDTO pollenData = new PollenDataDTO();\n      pollenData.setUpdatedAt(row.getTimestamp(0));\n      pollenData.setTreePollenCount(row.getInteger(4));\n      pollenData.setGrassPollenCount(row.getInteger(8));\n      pollenData.setWeedPollenCount(row.getInteger(5));\n      pollenDataList.add(pollenData);\n    }\n    return pollenDataList;\n  }\n\n  public List&lt;illnessriskdto> getIllnessRiskData() throws Exception {\n    Container\n\n<?, Row> container = store.getContainer(\"IllnessRiskData\");\n    if (container == null) {\n      throw new Exception(\"IllnessRiskData container not found.\");\n    }\n\n    List&lt;\/illnessriskdto>&lt;illnessriskdto> illnessRiskList = new ArrayList&lt;>();\n    SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\");\n    Date now = new Date();\n    String nowString = dateFormat.format(now);\n    String startTime = \"1971-12-23T18:18:52.000Z\";\n\n    String queryString = \"select * where createdAt >= TIMESTAMP('\" + startTime\n        + \"') and createdAt &lt;= TIMESTAMP('\" + nowString + \"')\";\n    Query&lt;row> query = container.query(queryString);\n    RowSet&lt;\/row>&lt;row> rs = query.fetch();\n\n    while (rs.hasNext()) {\n      Row row = rs.next();\n      IllnessRiskDTO illnessRisk = new IllnessRiskDTO();\n      illnessRisk.setCreatedAt(row.getTimestamp(0));\n      illnessRisk.setLat(row.getDouble(1));\n      illnessRisk.setLng(row.getDouble(2));\n      illnessRisk.setIliRisk(row.getString(3));\n      illnessRiskList.add(illnessRisk);\n    }\n    return illnessRiskList;\n  }\n\n  public List&lt;airqualitydto> getAirQualityData() throws Exception {\n    Container\n\n<?, Row> container = store.getContainer(\"AirQualityData\");\n    if (container == null) {\n      throw new Exception(\"AirQualityData container not found.\");\n    }\n\n    List&lt;\/airqualitydto>&lt;airqualitydto> airQualityList = new ArrayList&lt;>();\n    SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\");\n    Date now = new Date();\n    String nowString = dateFormat.format(now);\n    String startTime = \"1971-12-23T18:18:52.000Z\";\n\n    String queryString = \"select * where updatedAt >= TIMESTAMP('\" + startTime\n        + \"') and updatedAt &lt;= TIMESTAMP('\" + nowString + \"')\";\n    Query&lt;row> query = container.query(queryString);\n    RowSet&lt;\/row>&lt;row> rs = query.fetch();\n\n    while (rs.hasNext()) {\n      Row row = rs.next();\n      AirQualityDTO airQuality = new AirQualityDTO();\n      airQuality.setUpdatedAt(row.getTimestamp(0));\n      airQuality.setLat(row.getDouble(2));\n      airQuality.setLng(row.getDouble(3));\n      airQuality.setPm25(row.getDouble(7));\n      airQuality.setPm10(row.getDouble(12));\n      airQuality.setOzone(row.getDouble(14));\n      airQuality.setAqi(row.getInteger(9));\n      airQuality.setCategory(row.getString(5));\n      airQualityList.add(airQuality);\n    }\n    return airQualityList;\n  }\n}&lt;\/row>&lt;\/airqualitydto>&lt;\/row>&lt;\/illnessriskdto>&lt;\/row>&lt;\/pollendatadto><\/code><\/pre>\n<\/div>\n<ul>\n<li><strong>Rendering Charts with Thymeleaf<\/strong><\/li>\n<\/ul>\n<p>Once we\u2019ve retrieved the data from GridDB, we can pass it to a Thymeleaf template for visualization. Thymeleaf provides an efficient way to generate dynamic HTML pages, making it ideal for rendering the query results as charts, tables, or other visual components.<\/p>\n<p>Below is the implementation of <code>charts.html<\/code>:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-html\">&lt;!DOCTYPE html&gt;\n&lt;html xmlns_th=\"http:\/\/www.thymeleaf.org\"&gt;\n\n&lt;head&gt;\n  &lt;title&gt;Environmental Monitoring Data&lt;\/title&gt;\n  &lt;script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js\"&gt;&lt;\/script&gt;\n  &lt;style&gt;\n    body {\n      font-family: Arial, sans-serif;\n      margin: 20px;\n    }\n\n    h1 {\n      text-align: center;\n      color: #333;\n    }\n\n    h2 {\n      margin-top: 40px;\n      color: #555;\n    }\n\n    .chart-container {\n      position: relative;\n      margin: auto;\n      max-width: 800px;\n      padding: 20px;\n    }\n\n    canvas {\n      background: #f9f9f9;\n      border-radius: 8px;\n      box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n    }\n\n    .no-data {\n      text-align: center;\n      color: #999;\n      margin-top: 20px;\n    }\n  &lt;\/style&gt;\n&lt;\/head&gt;\n\n&lt;body&gt;\n  &lt;h1&gt;Environmental Monitoring Data&lt;\/h1&gt;\n\n  &lt;!-- Pollen Data Chart --&gt;\n  &lt;h2&gt;Pollen Data&lt;\/h2&gt;\n  &lt;div class=\"chart-container\"&gt;\n    &lt;canvas id=\"pollenChart\"&gt;&lt;\/canvas&gt;\n    &lt;div id=\"pollenNoData\" class=\"no-data\" style=\"display: none;\"&gt;No pollen data available&lt;\/div&gt;\n  &lt;\/div&gt;\n  &lt;script th_inline=\"javascript\"&gt;\n    const pollenData = \/*[[${pollenData}]]*\/[];\n    if (pollenData.length &gt; 0) {\n      const pollenLabels = pollenData.map(d =&gt; d.updatedAt);\n      const treePollen = pollenData.map(d =&gt; d.treePollenCount);\n      const grassPollen = pollenData.map(d =&gt; d.grassPollenCount);\n      const weedPollen = pollenData.map(d =&gt; d.weedPollenCount);\n\n      new Chart(document.getElementById('pollenChart'), {\n        type: 'bar',\n        data: {\n          labels: pollenLabels,\n          datasets: [\n            { label: 'Tree Pollen', data: treePollen, backgroundColor: 'rgba(75, 192, 192, 0.6)' },\n            { label: 'Grass Pollen', data: grassPollen, backgroundColor: 'rgba(54, 162, 235, 0.6)' },\n            { label: 'Weed Pollen', data: weedPollen, backgroundColor: 'rgba(255, 206, 86, 0.6)' }\n          ]\n        },\n        options: {\n          responsive: true,\n          plugins: {\n            legend: { position: 'top' },\n            title: { display: true, text: 'Pollen Count Data' }\n          }\n        }\n      });\n    } else {\n      document.getElementById('pollenNoData').style.display = 'block';\n    }\n  &lt;\/script&gt;\n\n  &lt;!-- Illness Risk Chart --&gt;\n  &lt;h2&gt;Illness Risk Data&lt;\/h2&gt;\n  &lt;div class=\"chart-container\"&gt;\n    &lt;canvas id=\"illnessRiskChart\"&gt;&lt;\/canvas&gt;\n    &lt;div id=\"illnessNoData\" class=\"no-data\" style=\"display: none;\"&gt;No illness risk data available&lt;\/div&gt;\n  &lt;\/div&gt;\n  &lt;script th_inline=\"javascript\"&gt;\n    const illnessData = \/*[[${illnessRiskData}]]*\/[];\n    if (illnessData.length &gt; 0) {\n      const riskLevelToNumeric = { \"Low\": 1, \"Moderate\": 2, \"High\": 3 };\n      const illnessLabels = illnessData.map(d =&gt; d.createdAt);\n      const illnessValues = illnessData.map(d =&gt; riskLevelToNumeric[d.iliRisk] || 0);\n\n      new Chart(document.getElementById('illnessRiskChart'), {\n        type: 'line',\n        data: {\n          labels: illnessLabels,\n          datasets: [{ label: 'Illness Risk', data: illnessValues, borderColor: 'rgba(75, 192, 192, 1)', fill: false }]\n        },\n        options: {\n          responsive: true,\n          plugins: {\n            legend: { position: 'top' },\n            title: { display: true, text: 'Illness Risk Levels' }\n          }\n        }\n      });\n    } else {\n      document.getElementById('illnessNoData').style.display = 'block';\n    }\n  &lt;\/script&gt;\n\n  &lt;!-- Air Quality Chart --&gt;\n  &lt;h2&gt;Air Quality Data&lt;\/h2&gt;\n  &lt;div class=\"chart-container\"&gt;\n    &lt;canvas id=\"airQualityChart\"&gt;&lt;\/canvas&gt;\n    &lt;div id=\"airQualityNoData\" class=\"no-data\" style=\"display: none;\"&gt;No air quality data available&lt;\/div&gt;\n  &lt;\/div&gt;\n  &lt;script th_inline=\"javascript\"&gt;\n    const airQualityData = \/*[[${airQualityData}]]*\/[];\n    if (airQualityData.length &gt; 0) {\n      const airQualityLabels = airQualityData.map(d =&gt; d.updatedAt);\n      const aqiValues = airQualityData.map(d =&gt; d.aqi);\n      const pm10Values = airQualityData.map(d =&gt; d.pm10);\n      const pm25Values = airQualityData.map(d =&gt; d.pm25);\n\n      new Chart(document.getElementById('airQualityChart'), {\n        type: 'line',\n        data: {\n          labels: airQualityLabels,\n          datasets: [\n            { label: 'AQI', data: aqiValues, borderColor: 'rgba(255, 99, 132, 1)', fill: false },\n            { label: 'PM10', data: pm10Values, borderColor: 'rgba(54, 162, 235, 1)', fill: false },\n            { label: 'PM2.5', data: pm25Values, borderColor: 'rgba(75, 192, 192, 1)', fill: false }\n          ]\n        },\n        options: {\n          responsive: true,\n          plugins: {\n            legend: { position: 'top' },\n            title: { display: true, text: 'Air Quality Metrics' }\n          }\n        }\n      });\n    } else {\n      document.getElementById('airQualityNoData').style.display = 'block';\n    }\n  &lt;\/script&gt;\n\n&lt;\/body&gt;\n\n&lt;\/html&gt;<\/code><\/pre>\n<\/div>\n<h3>Running the Project<\/h3>\n<p>To run the project, execute the following command to build and run our application:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">mvn clean install && mvn spring-boot:run \u00a0<\/code><\/pre>\n<\/div>\n<h3>Accessing the Dashboard<\/h3>\n<p>After starting the application, open a web browser and go to <code>http:\/\/localhost:9090<\/code>.<\/p>\n<p>This URL provides access to our Thymeleaf-powered dashboard, showcasing visualizations of environmental metrics, including air quality, pollen levels, and contamination risks, presented through interactive charts.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2025\/07\/Data_3.webp\"><img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2025\/07\/Data_3.webp\" alt=\"\" width=\"796\" height=\"543\" class=\"aligncenter size-full wp-image-32088\" srcset=\"\/wp-content\/uploads\/2025\/07\/Data_3.webp 796w, \/wp-content\/uploads\/2025\/07\/Data_3-300x205.webp 300w, \/wp-content\/uploads\/2025\/07\/Data_3-768x524.webp 768w, \/wp-content\/uploads\/2025\/07\/Data_3-600x409.webp 600w\" sizes=\"(max-width: 796px) 100vw, 796px\" \/><\/a><\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2025\/07\/Data_2.webp\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2025\/07\/Data_2.webp\" alt=\"\" width=\"828\" height=\"423\" class=\"aligncenter size-full wp-image-32087\" srcset=\"\/wp-content\/uploads\/2025\/07\/Data_2.webp 828w, \/wp-content\/uploads\/2025\/07\/Data_2-300x153.webp 300w, \/wp-content\/uploads\/2025\/07\/Data_2-768x392.webp 768w, \/wp-content\/uploads\/2025\/07\/Data_2-600x307.webp 600w\" sizes=\"(max-width: 828px) 100vw, 828px\" \/><\/a><\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2025\/07\/Data_1.webp\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2025\/07\/Data_1.webp\" alt=\"\" width=\"865\" height=\"488\" class=\"aligncenter size-full wp-image-32086\" srcset=\"\/wp-content\/uploads\/2025\/07\/Data_1.webp 865w, \/wp-content\/uploads\/2025\/07\/Data_1-300x169.webp 300w, \/wp-content\/uploads\/2025\/07\/Data_1-768x433.webp 768w, \/wp-content\/uploads\/2025\/07\/Data_1-150x85.webp 150w, \/wp-content\/uploads\/2025\/07\/Data_1-600x338.webp 600w\" sizes=\"(max-width: 865px) 100vw, 865px\" \/><\/a><\/p>\n<p>The charts on this dashboard is dynamically rendered using real time data retrieved from Ambee and processed by the application\u2019s <code>ChartService<\/code>.<\/p>\n<p><strong>Data Access in GridDB:<\/strong><\/p>\n<p>The GridDB Shell tool also allows for access and querying of data via the command line, as illustrated below.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-bash\">gs[public]> select * from AirQualityData;\ngs[public]> select * from IllnessRiskData;\ngs[public]> select * from PollenData;\ngs[public]> get 1<\/code><\/pre>\n<\/div>\n<h3><strong>Conclusion:<\/strong><\/h3>\n<p>Real-time environmental data is essential for smart cities to optimize urban management and enhance public health. By aggregating and analyzing data such as air quality, traffic flow, and illness risk, authorities can make precise, data-driven decisions for resource allocation and risk mitigation.<\/p>\n<p>GridDB\u2019s high-performance, distributed architecture is tailored for handling large-scale, time-series data with minimal latency. Its ability to process vast amounts of data in real time allows for efficient querying and aggregation, making it the ideal solution for smart city applications that require fast, scalable data analysis to support informed, actionable insights.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Smart cities are transforming urban landscapes by leveraging technology to improve efficiency and sustainability. A key component of smart cities is environmental monitoring, which involves the collection, aggregation, and analysis of real-time data to address challenges like air pollution, traffic congestion, and resource management. By leveraging innovative database technologies, smart cities can unlock actionable [&hellip;]<\/p>\n","protected":false},"author":41,"featured_media":52181,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-52180","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>GridDB for Environmental Monitoring in Smart Cities | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"Introduction Smart cities are transforming urban landscapes by leveraging technology to improve efficiency and sustainability. A key component of smart\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"GridDB for Environmental Monitoring in Smart Cities | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"Introduction Smart cities are transforming urban landscapes by leveraging technology to improve efficiency and sustainability. A key component of smart\" \/>\n<meta property=\"og:url\" content=\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/\" \/>\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=\"2025-07-09T07:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/griddb.net\/wp-content\/uploads\/2025\/12\/A_flat-style_digital_illustration_in_a_promotional_wordpress.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\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=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/\"},\"author\":{\"name\":\"griddb-admin\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\"},\"headline\":\"GridDB for Environmental Monitoring in Smart Cities\",\"datePublished\":\"2025-07-09T07:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/\"},\"wordCount\":1862,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/griddb.net\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2025\/12\/A_flat-style_digital_illustration_in_a_promotional_wordpress.webp\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/\",\"url\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/\",\"name\":\"GridDB for Environmental Monitoring in Smart Cities | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2025\/12\/A_flat-style_digital_illustration_in_a_promotional_wordpress.webp\",\"datePublished\":\"2025-07-09T07:00:00+00:00\",\"description\":\"Introduction Smart cities are transforming urban landscapes by leveraging technology to improve efficiency and sustainability. A key component of smart\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/#primaryimage\",\"url\":\"\/wp-content\/uploads\/2025\/12\/A_flat-style_digital_illustration_in_a_promotional_wordpress.webp\",\"contentUrl\":\"\/wp-content\/uploads\/2025\/12\/A_flat-style_digital_illustration_in_a_promotional_wordpress.webp\",\"width\":1200,\"height\":628},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/griddb.net\/en\/#website\",\"url\":\"https:\/\/griddb.net\/en\/\",\"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:\/\/griddb.net\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/griddb.net\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/griddb.net\/en\/#organization\",\"name\":\"Fixstars\",\"url\":\"https:\/\/griddb.net\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"contentUrl\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"width\":200,\"height\":83,\"caption\":\"Fixstars\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/#\/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:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\",\"name\":\"griddb-admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/#\/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:\/\/griddb.net\/en\/author\/griddb-admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"GridDB for Environmental Monitoring in Smart Cities | GridDB: Open Source Time Series Database for IoT","description":"Introduction Smart cities are transforming urban landscapes by leveraging technology to improve efficiency and sustainability. A key component of smart","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:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/","og_locale":"en_US","og_type":"article","og_title":"GridDB for Environmental Monitoring in Smart Cities | GridDB: Open Source Time Series Database for IoT","og_description":"Introduction Smart cities are transforming urban landscapes by leveraging technology to improve efficiency and sustainability. A key component of smart","og_url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2025-07-09T07:00:00+00:00","og_image":[{"width":1200,"height":628,"url":"https:\/\/griddb.net\/wp-content\/uploads\/2025\/12\/A_flat-style_digital_illustration_in_a_promotional_wordpress.webp","type":"image\/webp"}],"author":"griddb-admin","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"griddb-admin","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/#article","isPartOf":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/"},"author":{"name":"griddb-admin","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233"},"headline":"GridDB for Environmental Monitoring in Smart Cities","datePublished":"2025-07-09T07:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/"},"wordCount":1862,"commentCount":0,"publisher":{"@id":"https:\/\/griddb.net\/en\/#organization"},"image":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2025\/12\/A_flat-style_digital_illustration_in_a_promotional_wordpress.webp","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/","url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/","name":"GridDB for Environmental Monitoring in Smart Cities | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/griddb.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/#primaryimage"},"image":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2025\/12\/A_flat-style_digital_illustration_in_a_promotional_wordpress.webp","datePublished":"2025-07-09T07:00:00+00:00","description":"Introduction Smart cities are transforming urban landscapes by leveraging technology to improve efficiency and sustainability. A key component of smart","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/griddb-for-environmental-monitoring-in-smart-cities\/#primaryimage","url":"\/wp-content\/uploads\/2025\/12\/A_flat-style_digital_illustration_in_a_promotional_wordpress.webp","contentUrl":"\/wp-content\/uploads\/2025\/12\/A_flat-style_digital_illustration_in_a_promotional_wordpress.webp","width":1200,"height":628},{"@type":"WebSite","@id":"https:\/\/griddb.net\/en\/#website","url":"https:\/\/griddb.net\/en\/","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:\/\/griddb.net\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/griddb.net\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/griddb.net\/en\/#organization","name":"Fixstars","url":"https:\/\/griddb.net\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/","url":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","contentUrl":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","width":200,"height":83,"caption":"Fixstars"},"image":{"@id":"https:\/\/griddb.net\/en\/#\/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:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233","name":"griddb-admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/#\/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:\/\/griddb.net\/en\/author\/griddb-admin\/"}]}},"_links":{"self":[{"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/posts\/52180","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/comments?post=52180"}],"version-history":[{"count":0,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/posts\/52180\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/media\/52181"}],"wp:attachment":[{"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/media?parent=52180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/categories?post=52180"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/tags?post=52180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}