{"id":46710,"date":"2022-07-15T00:00:00","date_gmt":"2022-07-15T07:00:00","guid":{"rendered":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/blog\/gern-stack\/"},"modified":"2025-11-13T12:56:05","modified_gmt":"2025-11-13T20:56:05","slug":"gern-stack","status":"publish","type":"post","link":"https:\/\/www.griddb.net\/en\/blog\/gern-stack\/","title":{"rendered":"An Alternative to the MERN Stack: Create a Query Builder with the GERN Stack"},"content":{"rendered":"<p>This blog serves as a soft follow up to a <a href=\"https:\/\/griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/\">previous blog<\/a> in which we used <a href=\"https:\/\/reactjs.org\/\">Facebook&#8217;s React<\/a>, paired with the GridDB Web API, to ingest a CSV file and then visualize said data. In this follow up, we will again use React, but this time we will be using the GridDB Node.js connector instead of the Web API to ingest and serve data to our frontend. You can think of this configuration as the GERN stack: GridDB, Express, React, and node.js; this is an obvious play on the hugely popular <a href=\"https:\/\/www.geeksforgeeks.org\/mern-stack\/\"> MERN stack <\/a><\/p>\n<p>The main and obvious difference between the MERN stack and the GERN Stack is of course the database being deployed. The original acronym stands for MongoDB, Express.js, React.js, and node.js. If you are unfamiliar with MongoDB, it is a document-based database which allows for quick prototyping as the NoSQL schema allows for very fluid ingestion of data without any sort of foresight or pre-planning. Using the GERN stack over the MERN stack depends solely on your use case &#8212; if you need much higher performance, if you need to store time series data, or if your data is from IoT sensors &#8212; you would opt to use GridDB over MongoDB.<\/p>\n<h2>Project Overview<\/h2>\n<p>To showcase these products, we will create a simple query builder app that will display data that a user selects via dropdown menus. We will go through the process of installing the GridDB node.js client via npm, ingesting our open source data from <a href=\"https:\/\/www.kaggle.com\/datasets\/crawford\/80-cereals\">Kaggle<\/a>, and then setting up a React frontend to work with a node.js server (backend) connected to GridDB. We will also set the project up to build out the static React assets and be able to deploy this sort of project onto a website (and to avoid using two running node.js servers).<\/p>\n<p>From there, we can move on to the frontend which will be simple: three dropdowns to allow a user to find some data points relating to the dataset which was ingested. We will then showcase sending query strings to our backend to run against our DB and then pushing the results back up to the frontend.<\/p>\n<p><a href=\"https:\/\/github.com\/griddbnet\/Blogs\/tree\/query_builder\">Full Source Code Found Here<\/a><\/p>\n<p>Here is a quick example of the completed project:<\/p>\n<div style=\"text-align:center\">\n<iframe src='https:\/\/gfycat.com\/ifr\/SaneWeightyBlackfish' frameborder='0' scrolling='no' allowfullscreen width='640' height='404'><\/iframe>\n<\/div>\n<h2>Prerequisites<\/h2>\n<p>The following prerequisites are required to run this project:<\/p>\n<ul>\n<li>GridDB<\/li>\n<li>node.js<\/li>\n<li>GridDB c-client<\/li>\n<li>GridDB node.js client <\/li>\n<\/ul>\n<p><style>\n  ul {\n        padding-left: 36px;\n    }<\/p>\n<pre><code>.toc_container {\n    border: 1px solid #aaa !important;\n    display: table !important;\n    font-size: 95%;\n    margin-bottom: 1em;\n    padding: 20px;\n    width: auto;\n}\n\n.toc_title {\n    font-weight: 700;\n    text-align: center;\n}\n\n.toc_container li,\n.toc_container ul,\n.toc_container ul li,\n.toc_container ol li {\n    list-style: outside none none !important;\n}\n<\/code><\/pre>\n<p>.single-post .post>.entry-content { font-size: 14px !important }<\/p>\n<\/style>\n<div id=\"toc-block\"\n    style=\"background: #f9f9f9 none repeat scroll 0 0;border: 1px solid #aaa; padding: 20px; width: auto; display: table;margin-bottom: 1em;\"><\/p>\n<h5 id=\"toc\">\n    Table of Contents<br \/>\n  <\/h5>\n<div class=\"toc_container\">\n<ul id=\"toc-list\" style=\"list-style-type: none !important;\">\n<li>\n        <a href=\"#details\">Technical Details<\/a>\n      <\/li>\n<li style=\"list-style: outside none none !important;\">\n<div class=\"inner-list\">\n<ul style=\"list-style-type: none !important; padding-left: 9px;\">\n<li>\n              <a href=\"#architecture \">Architecture Overview <\/a>\n            <\/li>\n<li>\n              <a href=\"#frontend-backend \"> Setting up the Frontend to Work with the Backend  <\/a>\n            <\/li>\n<\/ul><\/div>\n<\/li>\n<li>\n        <a href=\"#building\">Building and Running<\/a>\n      <\/li>\n<li style=\"list-style: outside none none !important;\">\n<div class=\"inner-list\">\n<ul style=\"list-style-type: none !important; padding-left: 9px;\">\n<li>\n              <a href=\"#first\"> First Steps<\/a>\n            <\/li>\n<li>\n              <a href=\"#installing-npm\"> Installing the GridDB node.js Connector (via npm) <\/a>\n            <\/li>\n<li>\n              <a href=\"#ingest\">How to Create Ingesting Script with Node.js<\/a>\n            <\/li>\n<li>\n              <a href=\"#running-ingest\">Running the Ingest<\/a>\n            <\/li>\n<li>\n              <a href=\"#implementation\">Running The Frontend and Backend<\/a>\n            <\/li>\n<\/ul><\/div>\n<\/li>\n<li>\n        <a href=\"#set-up\"> Setting Up Project Code <\/a>\n      <\/li>\n<li style=\"list-style: outside none none !important;\">\n<div class=\"inner-list\">\n<ul style=\"list-style-type: none !important; padding-left: 9px;\">\n<li>\n              <a href=\"#getting-started\">Getting Started<\/a>\n            <\/li>\n<li>\n              <a href=\"#querying\"> How to Query with GridDB&#8217;s node.js Connector <\/a>\n            <\/li>\n<li>\n              <a href=\"#react\"> Using React with GridDB <\/a>\n            <\/li>\n<li>\n              <a href=\"#query-builder\"> Creating a Query Builder with React <\/a>\n            <\/li>\n<\/ul><\/div>\n<\/li>\n<li>\n        <a href=\"#conclusion\">Conclusion<\/a>\n      <\/li>\n<\/ul><\/div>\n<\/div>\n<h2><span id=\"details\"> Technical Details <\/span><\/h2>\n<h3><span id=\"architecture\"> Architecture Overview  <\/span><\/h3>\n<p>As explained above, the technologies being used here fit nicely into the acronym GERN: GridDB, Express, React, node.js. My personal environment was as follows: a CentOS 7 server running GridDB on bare metal. For the web app&#8217;s backend, I ran the <a href=\"https:\/\/github.com\/griddb\/node-api\">GridDB node.js connector<\/a> along with the node.js server and the express.js framework. The frontend consists of React.js being ran via the react bundler tool in its own frontend server; data is shared between the backend and frontend via API endpoints. The end goal will have the React frontend built out to static assets which are then displayed by the backend.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2022\/06\/diaghram-1.png\"><img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2022\/06\/diaghram-1.png\" alt=\"\" width=\"1280\" height=\"720\" class=\"aligncenter size-full wp-image-28479\" srcset=\"\/wp-content\/uploads\/2022\/06\/diaghram-1.png 1280w, \/wp-content\/uploads\/2022\/06\/diaghram-1-300x169.png 300w, \/wp-content\/uploads\/2022\/06\/diaghram-1-1024x576.png 1024w, \/wp-content\/uploads\/2022\/06\/diaghram-1-768x432.png 768w, \/wp-content\/uploads\/2022\/06\/diaghram-1-150x85.png 150w, \/wp-content\/uploads\/2022\/06\/diaghram-1-600x338.png 600w\" sizes=\"(max-width: 1280px) 100vw, 1280px\" \/><\/a><\/p>\n<p>The frontend server portion was set up using the <a href=\"https:\/\/reactjs.org\/docs\/create-a-new-react-app.html\">npx integrated toolchain<\/a>. The backend was built simply by creating and adding some express.js code into the <code>app.js<\/code> file.<\/p>\n<h3><span id=\"frontend-backend\"> Setting up the Frontend to Work with the Backend <\/span><\/h3>\n<p>One interesting point was adding in a line for proxy in the frontend portion. Because the frontend and backend use their own servers, they each have their own set of packages required to run, so you will need to run <code>npm install<\/code> on both the backend and the frontend. This also means that each server will have its own <code>package.json<\/code>, so in the frontend file, we added in a line indicating a proxy URL for the frontend: <code>\"proxy\": \"http:\/\/localhost:5000\"<\/code>. This address and port combination correspond to the backend we built using nodejs\/griddb\/express.<\/p>\n<p>The purpose of adding this line here means that our fetch API endpoints in the frontend can simply call the endpoint rather than calling the entire address (for example, calling <code>\/query<\/code> directly rather than calling <code>http:\/\/localhost:5000\/query<\/code>). This is perfect for running in a dev environment as it totally squashes CORS issues and keeps things simple.<\/p>\n<p>Another point of interest was setting up the workflow to work with just one server. When running this content within your dev environment, you will likely be running two simultaneous servers (one backend, one frontend), but when deploying to production or just checking out the demo, there is another step you can do.<\/p>\n<p>In the <code>package.json<\/code> of the root directory, we need to add an <code>npm run build<\/code> script:<\/p>\n<p><code>\"build\": \"cd frontend &amp;&amp; npm install &amp;&amp; npm run build\"<\/code><\/p>\n<p>This will build our React frontend to be static files within the <code>frontend\/build<\/code> directory.<\/p>\n<p>And then we add a snippet of code in our backend server (<code>app.js<\/code>):<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-js\">const path = require('path');\napp.use(express.static(path.resolve(__dirname, 'frontend\/build')));\n\napp.get('*', (req, res) => {\n    res.sendFile(path.resolve(__dirname, 'frontend\/build', 'index.html'));\n  });\n  <\/code><\/pre>\n<\/div>\n<p>This tells our server to serve up our Frontend of our newly built React contents found within the <code>frontend\/build<\/code> directory.<\/p>\n<h2><span id=\"building\"> Building and Running <\/span><\/h2>\n<h3><span id=\"first\"> First Steps <\/span><\/h3>\n<p>Before we get into the frontend and backend code, let&#8217;s briefly explain the exact steps of running this on your local machine.<\/p>\n<p>First and foremost, let&#8217;s do a git clone for the full project&#8217;s source code<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ git clone --branch query_builder https:\/\/github.com\/griddbnet\/Blogs.git<\/code><\/pre>\n<\/div>\n<p>And then let&#8217;s install GridDB and run as a service:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ wget --no-check-certificate https:\/\/github.com\/griddb\/griddb\/releases\/download\/v5.0.0\/griddb_5.0.0_amd64.deb\n$ sudo dpkg -i griddb_5.0.0_amd64.deb\n$ sudo systemctl start gridstore<\/code><\/pre>\n<\/div>\n<p><a href=\"https:\/\/github.com\/griddb\/griddb\/releases\">Here is a link to the GitHub Releases page for all distros and for the most up to date release <\/a><\/p>\n<p>Next steps will be installing the Node.js client and then setting up and running the ingest for our demo dataset.<\/p>\n<h3><span id=\"installing-npm\"> Installing the GridDB node.js Connector (via npm) <\/span><\/h3>\n<p>To install the node.js connector, you will first need to install the GridDB c-client. To do so, you can grab appropriate package files from the <a href=\"https:\/\/github.com\/griddb\/c_client\/releases\">GitHub page<\/a>.<\/p>\n<p>On Ubuntu you can install like so:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ wget https:\/\/github.com\/griddb\/c_client\/releases\/download\/v5.0.0\/griddb-c-client_5.0.0_amd64.deb\n$ sudo dpkg -i griddb-c-client_5.0.0_amd64.deb<\/code><\/pre>\n<\/div>\n<p>Now with the GridDB c-client installed, you can simply grab the <a href=\"https:\/\/www.npmjs.com\/package\/griddb-node-api\">nodejs package<\/a> using npm<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ npm i griddb-node-api<\/code><\/pre>\n<\/div>\n<p>And everything should run now. You can now run the ingest to ingest the <code>cereal.csv<\/code> file and then run project itself.<\/p>\n<h3><span id=\"ingest\"> How to Create Ingesting Script with Node.js <\/span><\/h3>\n<p>To start, let&#8217;s create a simple node.js script to ingest our data from the <code>csv<\/code> file provided by Kaggle. If you are familiar at all with the <a href=\"https:\/\/griddb.net\/en\/blog\/griddb-python-client-adds-new-time-series-functions\/\">Python GridDB Client<\/a>, the node.js iteration will be very familiar.<\/p>\n<p>First, you must import the griddb library, along with the csv parser. To install the parser, simply use <code>npm<\/code>.<\/p>\n<p><code>npm install --save csv-parse<\/code><\/p>\n<p>Next up is setting the credentials with the griddb factory get store.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">const griddb = require('griddb-node-api');\nvar { parse } = require('csv-parse');\n\nvar fs = require('fs');\nvar factory = griddb.StoreFactory.getInstance();\nvar store = factory.getStore({\n    \"host\": process.argv[2],\n    \"port\": parseInt(process.argv[3]),\n    \"clusterName\": process.argv[4],\n    \"username\": process.argv[5],\n    \"password\": process.argv[6]\n});<\/code><\/pre>\n<\/div>\n<p>The schema of the data to be imported is set up as a javascript variable<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">var containerName = \"Cereal\"\nconst conInfo = new griddb.ContainerInfo({\n    'name': containerName,\n    'columnInfoList': [\n        [\"name\", griddb.Type.STRING],\n        [\"mfr\", griddb.Type.STRING],\n        [\"type\", griddb.Type.STRING],\n        [\"calories\", griddb.Type.INTEGER],\n        [\"protein\", griddb.Type.INTEGER],\n        [\"fat\", griddb.Type.INTEGER],\n        [\"sodium\", griddb.Type.INTEGER],\n        [\"fiber\", griddb.Type.FLOAT],\n        [\"carbo\", griddb.Type.FLOAT],\n        [\"sugars\", griddb.Type.INTEGER],\n        [\"potass\", griddb.Type.INTEGER],\n        [\"vitamins\", griddb.Type.INTEGER],\n        [\"shelf\", griddb.Type.INTEGER],\n        [\"weight\", griddb.Type.FLOAT],\n        [\"cups\", griddb.Type.FLOAT],\n        [\"rating\", griddb.Type.FLOAT]\n    ],\n    'type': griddb.ContainerType.COLLECTION,\n    'rowKey': false\n});<\/code><\/pre>\n<\/div>\n<p>Once the proposed schema is set up, we simply read the <code>csv<\/code> file from using the native node.js file system reader and then loop through the contents of each line and grab the proper values to be inserted into our database<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">var arr = []\nfs.createReadStream(__dirname + '\/cereal.csv')\n    .pipe(parse({ columns: true }))\n    .on('data', (row) => {\n        arr.push(row)\n    })\n    .on('end', () => {\n        store.dropContainer(containerName)\n            .then(() => {\n                return store.putContainer(conInfo)\n            })\n            .then(col => {\n                arr.forEach(row => {\n                    return col.put([\n                        row['name'],\n                        row['mfr'],\n                        row['type'],\n                        parseInt(row['calories']),\n                        parseInt(row['protein']),\n                        parseInt(row['fat']),\n                        parseInt(row['sodium']),\n                        parseFloat(row['fiber']),\n                        parseFloat(row['carbo']),\n                        parseInt(row['sugars']),\n                        parseInt(row[\"potass\"]),\n                        parseInt(row[\"vitamins\"]),\n                        parseInt(row[\"shelf\"]),\n                        parseFloat(row[\"weight\"]),\n                        parseFloat(row[\"cups\"]),\n                        parseFloat(row[\"rating\"])\n                    ]);\n                })\n            })\n            .then(() => {\n                console.log(\"Success!\");\n                return true;\n            })\n            .catch(err => {\n                console.log(err);\n            });\n    })<\/code><\/pre>\n<\/div>\n<h3><span id=\"running-ingest\"> Running the Ingest <\/span><\/h3>\n<p>To ingest the <code>cereal.csv<\/code> file, you can imply run the following code.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ node ingest.js 127.0.0.1:10001 myCluster admin admin<\/code><\/pre>\n<\/div>\n<p>Once you run this, the entirety of the data should be available in your GridDB server under the container name <code>Cereal<\/code>.<\/p>\n<p>To verify, you can drop into your GridDB shell and check<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ sudo su gsadm\n  $ gs_sh\n  gs[public]> showcontainer Cereal<\/code><\/pre>\n<\/div>\n<pre><code>Database    : public\nName        : Cereal\nType        : COLLECTION\nPartition ID: 35\nDataAffinity: -\n\nColumns:\nNo  Name                  Type            CSTR  RowKey\n------------------------------------------------------------------------------\n 0  name                  STRING                \n 1  mfr                   STRING                \n 2  type                  STRING                \n 3  calories              INTEGER               \n 4  protein               INTEGER               \n 5  fat                   INTEGER               \n 6  sodium                INTEGER               \n 7  fiber                 FLOAT                 \n 8  carbo                 FLOAT                 \n 9  sugars                INTEGER               \n10  potass                INTEGER               \n11  vitamins              INTEGER               \n12  shelf                 INTEGER               \n13  weight                FLOAT                 \n14  cups                  FLOAT                 \n15  rating                FLOAT\n<\/code><\/pre>\n<h3><span id=\"implementation\"> Running The Frontend and Backend <span><\/span><\/span><\/h3>\n<p>To run this project, you have two options: running as dev mode, or running just one server. To run in a development environment, you will need to run the frontend server first:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ cd frontend && npm install && npm run start<\/code><\/pre>\n<\/div>\n<p>And then in another terminal you will need to run the backend. After running <code>$ npm install<\/code>, you can run:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ npm run start 127.0.0.1:10001 myCluster admin admin<\/code><\/pre>\n<\/div>\n<p><strong><em>NOTE: When running GridDB v5.0 as a service, GridDB will be run in FIXED_LIST mode (as opposed to Multicast). You can read more about it <a href=\"https:\/\/docs.griddb.net\/architecture\/structure-of-griddb\/#cluster-configuration-methods\">here<\/a>.<\/em><\/strong><\/p>\n<p>If you are following along and ran GridDB as a service, the above command will work. If you are running GridDB in Multicast mode, the IP address and port may be different. Please use the correct credentials for your configuration.<\/p>\n<p>Of course, you will need to enter in your own credentials along with the run command; these are all GridDB default values.<\/p>\n<p>But if you want a simpler way to run this project with only one terminal, you can build out the React static assets and simply run the backend server.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ npm run build # builds out the frontend into frontend\/build\n  $ npm install # installs backend packages\n  $ npm run start 127.0.0.1:10001 myCluster admin admin #command line arguments for GridDB server creds<\/code><\/pre>\n<\/div>\n<h2><span id=\"set-up\"> Setting Up Project Code<\/span><\/h2>\n<h3><span id=\"getting-started\"> Getting Started <\/span><\/h3>\n<p>To get started, we need to connect to the GridDB instance in the same way as handled above in the ingest section. Of course, to host the frontend portion of our app, we will need to set up a frontend server which hosts our React frontend app. We will also need to set up some endpoints within the node.js code (<code>app.js<\/code>). To help us to easily set up the endpoints, we will install the often-used <code>express<\/code> web framework.<\/p>\n<h3><span id=\"querying\"> How to Query with GridDB&#8217;s node.js Connector <\/span><\/h3>\n<p>When querying a container, the results will be in the form of promises, which either resolve or reject once they are finished running. So, to properly run this code, you need to either utilize <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Guide\/Using_promises#chaining\">promise chaining<\/a>, or you can opt to use the newer form of handling promises: <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Statements\/async_function\">JavaScript Async functions<\/a>.<\/p>\n<p>This is what querying a container looks like<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">containerName = 'Cereal';\n\nconst queryCont = async (queryStr) => {\n\n    var data = []\n    try {\n        const col = await store.getContainer(containerName)\n        const query = await col.query(queryStr)\n        const rs = await query.fetch(query)\n        while(rs.hasNext()) {\n            data.push(rs.next())\n        }\n        return data\n    } catch (error) {\n        console.log(\"error: \", error)\n    }\n}<\/code><\/pre>\n<\/div>\n<p>We call the above code in our endpoint of <code>\/all<\/code> which will run the query of <code>select *<\/code>, meaning we fetch all available data. So, whenever we fetch from <code>\/all<\/code>, we run the <code>queryCont<\/code> function and return the results back to the agent creating the REQUEST, usually the browser and our React frontend.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">app.get('\/all', async (req, res) => {\n    try {\n        let queryStr = \"select *\"\n        var results = await queryCont(queryStr)\n        res.json({\n            results\n        });\n    } catch (error) {\n        console.log(\"try error: \", error)\n    }\n});<\/code><\/pre>\n<\/div>\n<p>A couple of things to notice here: 1, we use the express framework to set our endpoint; if we run an HTTP GET Request on the endpoint of <code>\/all<\/code>, it will run this code and respond with a json file. And 2, when we call our <code>queryCont<\/code> function, we must call it with the <code>await<\/code> keyword as it returns a promise, not just a static variable.<\/p>\n<p>With React, we will run this query on page load to grab all the data with an HTTP GET request. This is done simply for demo purposes as an easy way to populate our dropdown menu. In production code, you would not run this.<\/p>\n<h3><span id=\"react\"> Using React with GridDB <\/span><\/h3>\n<p>Now that we have the basics of our backend, we can set up our frontend. When building a new React app, it&#8217;s usually easiest to use the integrating bundling tools maintained by Facebook\/Meta. To shortcut your way to a ready-made project, you can simply run:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">$ npx create-react-app frontend<\/code><\/pre>\n<\/div>\n<p>As mentioned <a href=\"#architecture\">earlier<\/a>, it is wise to add in a line about which proxy to use in the frontend&#8217;s <code>package.json<\/code> file. This will allow you to use endpoints that point directly to the address and not need to indicate IP address or port, etc.<\/p>\n<p>To make edits to the code, we simply edit the <code>src\/App.js<\/code> file. For this project, I simply stuck in all of our frontend code inside that file.<\/p>\n<p>The <code>App.js<\/code> file is essentially just one JavaScript function which then gets exported (at the bottom of the file). This function returns <code>JSX<\/code> which builds out app; in this case it will produce all of the elements we see in our frontend app.<\/p>\n<p>And with that, we can get on to writing our actual React code.<\/p>\n<h3><span id=\"query-builder\"> Creating a Query Builder with React <\/span><\/h3>\n<p>The full code for this project is available on <a href=\"https:\/\/github.com\/griddbnet\/Blogs\/tree\/query_builder\">Github<\/a>, so you can see in detail how this portion was created &#8212; we will not be delving into too much into detail from here. But the basic idea of it is that there are three separate dropdown menus for the user to select various options from. The user can select from a variety of different nutrients, and then pick greater than, less than, or equals, and then finally they can pick a specific cereal to run the query against.<\/p>\n<p>So for example: say you would like to find out which cereals have more fiber than Frosted Mini-Wheats, you would simply select, Fiber, then Greater Than, and finally the cereal name. The query will then be sent to the nodejs server, run the query, and then sent back up to the React code via an endpoint.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-17-at-11.14.46-AM.png\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-17-at-11.14.46-AM.png\" alt=\"\" width=\"2840\" height=\"844\" class=\"aligncenter size-full wp-image-28265\" srcset=\"\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-17-at-11.14.46-AM.png 2840w, \/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-17-at-11.14.46-AM-300x89.png 300w, \/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-17-at-11.14.46-AM-1024x304.png 1024w, \/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-17-at-11.14.46-AM-768x228.png 768w, \/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-17-at-11.14.46-AM-1536x456.png 1536w, \/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-17-at-11.14.46-AM-2048x609.png 2048w, \/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-17-at-11.14.46-AM-600x178.png 600w\" sizes=\"(max-width: 2840px) 100vw, 2840px\" \/><\/a><\/p>\n<p>Sending the data back to the node.js server is done via an HTTP POST request. With this request, we can send back a payload of data, in this case JSON, to which we will use to build out our GridDB SQL query.<\/p>\n<p>Once the user sets their parameters, they will click the submit button, which will fire off our HTTP Request:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\"> const handleSubmit = async (event) => {\n            fetch('\/query', {\n                method: 'POST',\n                headers: {\n                    'Content-Type': 'application\/json'\n                },\n                body: JSON.stringify({'list': list, 'comp': comp, 'name': nameDropDown})\n            }).then(function(response) {\n                console.log(response)\n                return response.json();\n            });<\/code><\/pre>\n<\/div>\n<p>The body contains the user-chosen parameters of the dropdown list. On the backend\/node.js side, we will grab these values and form our query.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">var userResult = {\"null\": \"null\"}\nvar userVal;\n\napp.post('\/query', jsonParser, async (req, res) => {\n    const {list, comp, name} = req.body \n\n    try {\n        var results = await querySpecific(name)\n        let type = checkType(list) \/\/grabs array position of proper value\n        let compVal = checkComp(comp)\n        let val = results[0][type] \/\/ the specific value being queried against\n  \n        userVal = val\n        let specificRes = await queryVal(list, compVal, val)\n        userResult = specificRes\n        res.status(200).json(userResult);\n    } catch (error) {\n        console.log(\"try error: \", error)\n    }\n});<\/code><\/pre>\n<\/div>\n<p>So, once a user sets their parameters, the REQUEST comes back to this endpoint. First, we grab the proper values: <code>list<\/code>, <code>comp<\/code>, and <code>name<\/code>. Then, we use our <code>querySpecific<\/code> function which will form one of our queries based on the chosen cereal name.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">const querySpecific = async (cerealName) => {\n\n    var data = []\n    let q = `SELECT * WHERE name='${cerealName}'`\n    try {\n        const col = await store.getContainer(containerName)\n        const query = await col.query(q)\n        const rs = await query.fetch(query)\n        while(rs.hasNext()) {\n            data.push(rs.next())\n        }\n        return data\n    } catch (error) {\n        console.log(\"error: \", error)\n    }\n}<\/code><\/pre>\n<\/div>\n<p>So, if our user wanted to know all of the cereals with a higher fiber content than Frosted Mini-Wheats, we must first grab the entire row where the name is Frosted Mini Wheats. From there, we can grab the array position for which value is the fiber, and then run a second query to find all cereals with a fiber count higher than the value we found.<\/p>\n<p>The <code>checkType<\/code> and <code>checkComp<\/code> functions simply convert the user&#8217;s selected parameters to the proper array position for both the nutrient type (calories, fiber, etc), as well as the proper sign for equals, or less than, etc.<\/p>\n<p>Now that we have the user&#8217;s full parameters, as well as the value of the item being compared, we can run our full query with <code>queryVal<\/code>. This function is very similar to the previous two functions but instead takes more parameters to build out a more complex query:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">const queryVal = async (list, comp, val) => {\n\n    var data = []\n    let q = `SELECT * WHERE ${list} ${comp} ${val} `\n\n    try {\n        const col = await store.getContainer(containerName)\n        const query = await col.query(q)\n        const rs = await query.fetch(query)\n        while(rs.hasNext()) {\n            data.push(rs.next())\n        }\n        return data\n    } catch (error) {\n        console.log(\"error: \", error)\n    }\n}<\/code><\/pre>\n<\/div>\n<p>The body and query were printed out to console and look like this:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">query val string:  SELECT * WHERE fiber > 3 \nreq body:  { list: 'fiber', comp: 'Greater Than', name: 'Frosted Mini-Wheats' }<\/code><\/pre>\n<\/div>\n<p>And now that the data has been retrieved, we can run one more HTTP GET Request to retrieve the rows of our query and then add them into our rudimentary HTML table:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">app.get(\"\/data\", (req, res) => {\n    res.json({\n        userVal,\n        userResult\n    })\n});<\/code><\/pre>\n<\/div>\n<p>And on the frontend:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">let response = await fetch(`\/data`)\n            let result = await response.text()\n            let resp = await JSON.parse(result)\n            \/\/ the Specific react state will set off other functions to form our table rows and columns to be inserted into our table with all the relevant information\n            setSpecific(resp)<\/code><\/pre>\n<\/div>\n<p>And now with the data in our state, we can properly build out our table rows to be inserted into our HTML table to be displayed for the user.<\/p>\n<p>Here is that brief demo again:<\/p>\n<div style=\"text-align:center\">\n<iframe src='https:\/\/gfycat.com\/ifr\/SaneWeightyBlackfish' frameborder='0' scrolling='no' allowfullscreen width='640' height='404'><\/iframe>\n<\/div>\n<h2><span id=\"conclusion\"> Conclusion <\/span><\/h2>\n<p>In this blog, we covered quite a lot. We covered how to install the latest GridDB node.js connector (and c_client), how to ingest a CSV file using the node.js connector, how to build a simple express server to serve up your GridDB data, how to use React with GridDB and its bundling tools, and finally, how to run queries on your GridDB server which can be sent up to your React app.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This blog serves as a soft follow up to a previous blog in which we used Facebook&#8217;s React, paired with the GridDB Web API, to ingest a CSV file and then visualize said data. In this follow up, we will again use React, but this time we will be using the GridDB Node.js connector instead [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":28483,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-46710","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>An Alternative to the MERN Stack: Create a Query Builder with the GERN Stack | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"This blog serves as a soft follow up to a previous blog in which we used Facebook&#039;s React, paired with the GridDB Web API, to ingest a CSV file and then\" \/>\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.net\/en\/blog\/gern-stack\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"An Alternative to the MERN Stack: Create a Query Builder with the GERN Stack | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"This blog serves as a soft follow up to a previous blog in which we used Facebook&#039;s React, paired with the GridDB Web API, to ingest a CSV file and then\" \/>\n<meta property=\"og:url\" content=\"https:\/\/griddb.net\/en\/blog\/gern-stack\/\" \/>\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=\"2022-07-15T07:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-13T20:56:05+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.griddb.net\/wp-content\/uploads\/2022\/06\/gern.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1160\" \/>\n\t<meta property=\"og:image:height\" content=\"653\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Israel\" \/>\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=\"Israel\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/gern-stack\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/gern-stack\/\"},\"author\":{\"name\":\"Israel\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/c8a430e7156a9e10af73b1fbb46c2740\"},\"headline\":\"An Alternative to the MERN Stack: Create a Query Builder with the GERN Stack\",\"datePublished\":\"2022-07-15T07:00:00+00:00\",\"dateModified\":\"2025-11-13T20:56:05+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/gern-stack\/\"},\"wordCount\":2471,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/griddb.net\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/gern-stack\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2022\/06\/gern.png\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/gern-stack\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/gern-stack\/\",\"url\":\"https:\/\/griddb.net\/en\/blog\/gern-stack\/\",\"name\":\"An Alternative to the MERN Stack: Create a Query Builder with the GERN Stack | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/gern-stack\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/gern-stack\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2022\/06\/gern.png\",\"datePublished\":\"2022-07-15T07:00:00+00:00\",\"dateModified\":\"2025-11-13T20:56:05+00:00\",\"description\":\"This blog serves as a soft follow up to a previous blog in which we used Facebook's React, paired with the GridDB Web API, to ingest a CSV file and then\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/gern-stack\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/gern-stack\/#primaryimage\",\"url\":\"\/wp-content\/uploads\/2022\/06\/gern.png\",\"contentUrl\":\"\/wp-content\/uploads\/2022\/06\/gern.png\",\"width\":1160,\"height\":653},{\"@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\/c8a430e7156a9e10af73b1fbb46c2740\",\"name\":\"Israel\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g\",\"caption\":\"Israel\"},\"url\":\"https:\/\/www.griddb.net\/en\/author\/israel\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"An Alternative to the MERN Stack: Create a Query Builder with the GERN Stack | GridDB: Open Source Time Series Database for IoT","description":"This blog serves as a soft follow up to a previous blog in which we used Facebook's React, paired with the GridDB Web API, to ingest a CSV file and then","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.net\/en\/blog\/gern-stack\/","og_locale":"en_US","og_type":"article","og_title":"An Alternative to the MERN Stack: Create a Query Builder with the GERN Stack | GridDB: Open Source Time Series Database for IoT","og_description":"This blog serves as a soft follow up to a previous blog in which we used Facebook's React, paired with the GridDB Web API, to ingest a CSV file and then","og_url":"https:\/\/griddb.net\/en\/blog\/gern-stack\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2022-07-15T07:00:00+00:00","article_modified_time":"2025-11-13T20:56:05+00:00","og_image":[{"width":1160,"height":653,"url":"https:\/\/www.griddb.net\/wp-content\/uploads\/2022\/06\/gern.png","type":"image\/png"}],"author":"Israel","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"Israel","Est. reading time":"16 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/griddb.net\/en\/blog\/gern-stack\/#article","isPartOf":{"@id":"https:\/\/griddb.net\/en\/blog\/gern-stack\/"},"author":{"name":"Israel","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/c8a430e7156a9e10af73b1fbb46c2740"},"headline":"An Alternative to the MERN Stack: Create a Query Builder with the GERN Stack","datePublished":"2022-07-15T07:00:00+00:00","dateModified":"2025-11-13T20:56:05+00:00","mainEntityOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/gern-stack\/"},"wordCount":2471,"commentCount":0,"publisher":{"@id":"https:\/\/griddb.net\/en\/#organization"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/gern-stack\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2022\/06\/gern.png","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/griddb.net\/en\/blog\/gern-stack\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/griddb.net\/en\/blog\/gern-stack\/","url":"https:\/\/griddb.net\/en\/blog\/gern-stack\/","name":"An Alternative to the MERN Stack: Create a Query Builder with the GERN Stack | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/griddb.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/gern-stack\/#primaryimage"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/gern-stack\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2022\/06\/gern.png","datePublished":"2022-07-15T07:00:00+00:00","dateModified":"2025-11-13T20:56:05+00:00","description":"This blog serves as a soft follow up to a previous blog in which we used Facebook's React, paired with the GridDB Web API, to ingest a CSV file and then","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/griddb.net\/en\/blog\/gern-stack\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/blog\/gern-stack\/#primaryimage","url":"\/wp-content\/uploads\/2022\/06\/gern.png","contentUrl":"\/wp-content\/uploads\/2022\/06\/gern.png","width":1160,"height":653},{"@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\/c8a430e7156a9e10af73b1fbb46c2740","name":"Israel","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g","caption":"Israel"},"url":"https:\/\/www.griddb.net\/en\/author\/israel\/"}]}},"_links":{"self":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46710","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\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/comments?post=46710"}],"version-history":[{"count":1,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46710\/revisions"}],"predecessor-version":[{"id":51382,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46710\/revisions\/51382"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media\/28483"}],"wp:attachment":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media?parent=46710"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/categories?post=46710"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/tags?post=46710"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}