{"id":46598,"date":"2020-04-06T00:00:00","date_gmt":"2020-04-06T07:00:00","guid":{"rendered":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/blog\/nyc-taxi-open-data-node-js\/"},"modified":"2025-11-13T12:54:52","modified_gmt":"2025-11-13T20:54:52","slug":"nyc-taxi-open-data-node-js","status":"publish","type":"post","link":"https:\/\/www.griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/","title":{"rendered":"Analyzing NYC Taxi Open Data with GridDB and NodeJS"},"content":{"rendered":"<p>In this blog, we\u00e2\u20ac\u2122ll take a look at some open data provided by the NYC Taxi Commission and showcase some simple scripts to ingest and analyze the data. The principles shown here are applicable to many different types of problems.<\/p>\n<p>If you haven\u00e2\u20ac\u2122t set up a GridDB server yet, follow this <a href=https:\/\/griddb.net\/en\/blog\/griddb-quickstart\/>quickstart<\/a>. If you need to setup GridDB for Node.js, this <a href=https:\/\/griddb.net\/en\/blog\/nodejs-client\/>blog <\/a> will get you up and running. You can download and find further details about the NYC Taxi data on the <a   href=\"https:\/\/data.cityofnewyork.us\/Transportation\/2018-Yellow-Taxi-Trip-Data\/t29m-gskq\">NYC Open Data website<\/a>.<\/p>\n<h2>Data Model<\/h2>\n<pre>\nVendorID,tpep_pickup_datetime,tpep_dropoff_datetime,passenger_count,trip_distance,RatecodeID,store_and_fwd_flag,PULocationID,DOLocationID,payment_type,fare_amount,extra,mta_tax,tip_amount,tolls_amount,improvement_surcharge,total_amount\n2,03\/13\/2018 02:58:38 PM,03\/13\/2018 03:00:22 PM,1,0.31,1,N,132,132,2,3.5,0,0.5,0,0,0.3,4.3\n1,03\/13\/2018 02:34:11 PM,03\/13\/2018 02:40:35 PM,1,2.3,1,N,132,132,1,9,0,0.5,1.95,0,0.3,11.75\n1,03\/13\/2018 02:42:12 PM,03\/13\/2018 03:21:44 PM,1,17.5,2,N,132,230,1,52,0,0.5,5,5.76,0.3,63.56\n1,03\/13\/2018 02:36:05 PM,03\/13\/2018 03:04:08 PM,1,10.5,1,N,230,138,1,32.5,0,0.5,7.8,5.76,0.3,46.86\n1,03\/13\/2018 02:41:52 PM,03\/13\/2018 02:45:41 PM,1,0.7,1,N,264,264,2,5,0,0.5,0,0,0.3,5.8\n1,03\/13\/2018 02:47:40 PM,03\/13\/2018 02:55:06 PM,1,1.3,1,N,264,264,1,7,0,0.5,2,0,0.3,9.8\n1,03\/13\/2018 02:27:57 PM,03\/13\/2018 02:48:45 PM,1,4.8,1,N,142,13,1,18.5,0,0.5,3.85,0,0.3,23.15\n1,03\/13\/2018 02:03:27 PM,03\/13\/2018 02:10:51 PM,1,0.6,1,N,164,100,1,6,0,0.5,1.36,0,0.3,8.16\n1,03\/13\/2018 02:12:58 PM,03\/13\/2018 02:25:04 PM,1,1,1,N,100,230,2,8.5,0,0.5,0,0,0.3,9.3\n<\/pre>\n<p>The open data has 17 fields so our first decision is to determine how to split the data into multiple containers. The ideal method would be for the data from each individual taxi cab to be put in individual containers, but a unique identifier for each cab is not provided as the data is anonymized. The next best field to use is <code>PULocationID<\/code>, which is an integer from 1-265 which represents a unique identifier of each of the New York MTA neighborhoods.<\/p>\n<p>Since different taxi cabs could be picking up passengers at the exact same time in the exact same neighbourhood, <code>tpep_pickup_datetime<\/code> does not make a good primary key. Instead, we\u00e2\u20ac\u2122ll have to use a unique integer that is incremented for every row added.<\/p>\n<p>We also add a few calculated fields: <code>hour_of_day<\/code> and <code>day_of_week<\/code> which will be useful in the analysis of the taxi data.<\/p>\n<table>\n<tr>\n<td>\n<pre>\nvar colInfo = new griddb.ContainerInfo({\n    'name': \"col\"+data['PULocationID'],\n    'columnInfoList': [\n        [\"id\" , griddb.Type.LONG],\n        [\"duration\" , griddb.Type.INTEGER],\n        [\"VendorID\", griddb.Type.INTEGER ],\n        [\"tpep_pickup_datetime\", griddb.Type.TIMESTAMP ],\n        [\"tpep_dropoff_datetime\", griddb.Type.TIMESTAMP ],\n        [\"passenger_count\", griddb.Type.LONG],\n        [\"store_and_fwd_flag\" , griddb.Type.BOOL],\n        [\"PULocationID\", griddb.Type.INTEGER],\n        [\"DOLocationID\", griddb.Type.INTEGER],\n        [\"payment_type\", griddb.Type.INTEGER],\n        [\"fare_amount\", griddb.Type.FLOAT],\n        [\"extra\", griddb.Type.FLOAT],\n        [\"mta_tax\", griddb.Type.FLOAT],\n        [\"tip_amount\", griddb.Type.FLOAT],\n        [\"tolls_aount\", griddb.Type.FLOAT],\n        [\"improvement_surcharge\", griddb.Type.FLOAT],\n        [\"total_amount\", griddb.Type.FLOAT], \n        [\"hour_of_day\", griddb.Type.INTEGER], \n        [\"day_of_week\", griddb.Type.INTEGER]],\n   'type': griddb.ContainerType.COLLECTION, 'rowKey': true\n});\n<\/pre>\n<\/td>\n<td>\n            <img fetchpriority=\"high\" decoding=\"async\" alt=\"NYC Taxi Open Data Schema\"\n                src=\"https:\/\/griddb.net\/wp-content\/uploads\/2020\/02\/Screen-Shot-2020-02-26-at-1.15.00-PM.png\" alt=\"\"\n                width=\"296\" height=\"614\" class=\"alignnone size-full wp-image-26340\" srcset=\"\/wp-content\/uploads\/2020\/02\/Screen-Shot-2020-02-26-at-1.15.00-PM.png 296w, \/wp-content\/uploads\/2020\/02\/Screen-Shot-2020-02-26-at-1.15.00-PM-145x300.png 145w\" sizes=\"(max-width: 296px) 100vw, 296px\" \/>\n        <\/td>\n<\/tr>\n<\/table>\n<h2>Ingestion<\/h2>\n<p>The actual ingestion process is quite simple using the <a href=\"https:\/\/www.npmjs.com\/package\/csv-parser\">csv-parser npm module<\/a>. Data is streamed from and processed by the CSV parser and then we convert it to a simple array that is put into the appropriate GridDB container.<\/p>\n<pre>\nvar griddb = require('griddb_node');\nvar fs = require('fs');\nvar csv = require('csv-parser')\n\nlet factory = griddb.StoreFactory.getInstance();\nlet store = factory.getStore({\n    \"host\": '239.0.0.1',\n    \"port\": 31999,\n    \"clusterName\": \"defaultCluster\",\n    \"username\": \"admin\",\n    \"password\": \"admin\"\n});\n\nlet cols = {}\nlet count=0\n\nfs.createReadStream('data.csv')\n  .pipe(csv())\n  .on('data', (data) => {\n    let row = []\n    row[0] = count++;\n    row[1] = parseInt(Date.parse(data['tpep_dropoff_datetime'])-Date.parse(data['tpep_pickup_datetime']))\/1000)\n    row[2] = parseInt(data['VendorID'], 10);\n    row[3] = Date.parse(data['tpep_pickup_datetime'])\n    row[4] = Date.parse(data['tpep_dropoff_datetime'])\n    row[5] = parseInt(data['passenger_count'], 10)\n    if(data['store_and_fwd_flag'] == 'Y')\n        row[6] = true\n    else\n        row[6] = false\n    row[7] = parseInt(data['PULocationID'])\n    row[8] = parseInt(data['DOLocationID'])\n    row[9] = parseInt(data['payment_type'])\n    row[10] = Number(data['fare_amount'])\n    row[11] = Number(data['extra'])\n    row[12] = Number(data['mta_tax'])\n    row[13] = Number(data['tip_amount'])\n    row[14] = Number(data['tolls_amount'])\n    row[15] = Number(data['improvement_surcharge'])\n    row[16] = Number(data['total_amount'])\n    let date = new Date(row[3])\n    row[17] = date.getHours()\n    row[18] = date.getDay()\n\n    var colInfo = . . . snipped above . . .\n    store.putContainer(colInfo, false)\n        .then(cont => {\n            cont.put(row)\n            console.log(row[0])\n        })\n    .catch(err => {\n        if (err.constructor.name == \"GSException\") {\n            for (var i = 0; i < err.getErrorStackSize(); i++) {\n                console.log(\"[\", i, \"]\");\n                console.log(err.getErrorCode(i));\n                console.log(err.getMessage(i));\n            }\n        } else {\n            console.log(err);\n        }\n    });\n});\n<\/pre>\n<h2>Analysis<\/h2>\n<p>There are many different queries that could yield interesting results; what was the longest trip? The most expensive?<br \/>\nWhich area is the busiest?<\/p>\n<pre>\n\/\/ standard boilerplate\nvar griddb = require('griddb_node');\nvar fs = require('fs');\nvar csv = require('csv-parser')\n\n\/\/ our Cluster's credentials\nlet factory = griddb.StoreFactory.getInstance();\nlet store = factory.getStore({\n    \"host\": '239.0.0.1',\n    \"port\": 31999,\n    \"clusterName\": \"defaultCluster\",\n    \"username\": \"admin\",\n    \"password\": \"admin\"\n});\n\nlet promises = []\nlet results = {}\n\nvar iterate = function(locID) {\n    return function(rowset) {\n        if(rowset != null) {\n            if (rowset.hasNext()) {\n                row = rowset.next();\n                results[locID] = row;\n                \/\/ if result is an aggregation use this instead\n                \/\/ results[locID] = row..get(griddb.GS_TYPE_LONG);\n            }\n        }\n    }\n}\n\nvar query = function (locID) {\n    return function(cont) {\n        if(cont != null) {\n            q = cont.query(\"SELECT * ORDER BY fare_amount DESC LIMIT 1 \");\n            return q.fetch()\n        }\n    }\n}\n\nfor (let i=0; i < 100; i++) {\n    var locID = i\n    promise = store.getContainer(\"col\"+i)\n    .then(query(i))\n    .then(iterate(i))\n    .catch(err => {\n        if (err.constructor.name == \"GSException\") {\n            for (var i = 0; i < err.getErrorStackSize(); i++) {\n                console.log(\"[\", i, \"]\");\n                console.log(err.getErrorCode(i));\n                console.log(err.getMessage(i));\n            }\n        } else {\n            console.log(err);\n        }\n    })\n    promises.push(promise)\n}\n\nPromise.all(promises).then(values => {\n    var retval=null;\n    console.log(\"sorting...\")\n    for (var k in results) {\n        if (retval == null || results[k][10] > retval[10])\n            retval=results[k]\n    }\n    console.log(retval)\n})\n<\/pre>\n<p>The above code finds the most expensive trip which was on March 22 and was over 3 hours long and cost $475 total:<\/p>\n<pre>\n[ 1725438,\n  true,\n  2,\n  2018-03-22T06:43:13.000Z,\n  2018-03-22T09:59:34.000Z,\n  1,\n  false,\n  93,\n  265,\n  1,\n  450,\n  0,\n  0,\n  0,\n  24.760000228881836,\n  0.30000001192092896,\n  475.05999755859375,\n  6,\n  4 ]\n<\/pre>\n<p>With the asynchronous nature of Node.js, two tricks are required: first is determining what the query parameters were (locationID). This one is a bit tricky and is placed within a promise chain and solved with the aid of <a href=https:\/\/en.wikipedia.org\/wiki\/Currying> currying <\/a> which is where a function is specified in a then() call as follows:<\/p>\n<pre>\nfor (let i=0; i < 100; i++) {\n    promise=store.getContainer(\"col\"+i) .then(query(i)) .then(iterate(i))\n    ...\n}\n<\/pre>\n<p>Since all queries execute simultaneously in the background, we need to wait for them to finish.<br \/>\nFirst we add the query promise to a list:<\/p>\n<pre>\n    promises.push(promise)\n<\/pre>\n<p>and then we can wait for all promises to complete:<\/p>\n<pre>\nPromise.all(promises).then(values => {\n    \/\/ display results\n}\n<\/pre>\n<p>To modify this for the longest trip, you'd change \"fare_amount\" to \"duration\" and the final comparison key from \"10\" to \"1\":<\/p>\n<pre>\n...\n\n            q = cont.query(\"SELECT * ORDER BY duration DESC LIMIT 1 \");\n\n...\n\n        if (retval == null || results[k][1] > retval[1])\n\n...\n<\/pre>\n<p>If you were interested in the busiest locations, an aggregation query would need to be used which would also change the result fetching and final sorting.<\/p>\n<pre>\n...\n\nvar iterate = function(locID) {\n    return function(rowset) {\n        if(rowset != null) {\n            if (rowset.hasNext()) {\n                row = rowset.next();\n                results[locID] = row.get(griddb.GS_TYPE_LONG);\n            }\n        }\n    }\n}\n\nvar query = function (locID) {\n    return function(cont) {\n        if(cont != null) {\n            q = cont.query(\"SELECT COUNT(*)\");\n            return q.fetch()\n        }\n    }\n}\n\n...\n\nPromise.all(promises).then(values => {\n    var items = Object.keys(results).map(function(key) {\n        return [key, results[key]];\n    });\n\n    items.sort(function(first, second) {\n        return second[1] - first[1];\n    });\n\n    console.log(items.slice(0, 10))\n})\n<\/pre>\n<p>Which outputs the following, we can see area 161 (Manhattan Midtown) is the busiest with 156727 trips.<\/p>\n<pre>\n[ [ '161', 156727 ],\n  [ '237', 153388 ],\n  [ '162', 144923 ],\n  [ '230', 143784 ],\n  [ '186', 136234 ],\n  [ '236', 136093 ],\n  [ '170', 134533 ],\n  [ '48', 131547 ],\n  [ '234', 130747 ],\n  [ '79', 115052 ] ]\n<\/pre>\n<h2>More Complex Analysis<\/h2>\n<p>The above simple queries provide interesting insights, but a more complex query such as \u00e2\u20ac\u0153Which areas are busiest for a given hour of the day?\u00e2\u20ac\u009d allow for taxi companies to determine how to deploy their cabs for maximizing profits.<\/p>\n<p>To do this, we can determine how many trips are taken from each neighborhood on a given hour of the day using multiple queries. For each location and each hour, a simple count aggregation is run.<\/p>\n<p>The results are placed into a 2-dimensional dictionary for further processing.<\/p>\n<pre>\nvar iterate = function(locID, hour ) {\n    return function(rowset) {\n        if(rowset != null) {\n            while (rowset.hasNext()) {\n                row = rowset.next();\n                results[hour][locID] = row.get(griddb.GS_TYPE_LONG)\n            }\n        }\n    }\n}\n\nvar query = function (locID, hour) {\n    return function(cont) {\n        if(cont != null) {\n            q = cont.query(\"SELECT count(*) where hour_of_day = \"+hour);\n            return q.fetch()\n        }\n    }\n}\n\nfor(let hour=0; hour < 24; hour++) {\n    results[hour] = {};\n    for (loc=0; loc < 265; loc++)\n        results[hour][loc] = 0\n\n    for (let i=0; i < 265; i++) {\n        var locID = i\n        promise = store.getContainer(\"col\"+i)\n        .then(query(i, hour))\n        .then(iterate(i, hour))\n        .catch(err => {\n            if (err.constructor.name == \"GSException\") {\n                for (var i = 0; i < err.getErrorStackSize(); i++) {\n                    console.log(\"[\", i, \"]\");\n                    console.log(err.getErrorCode(i));\n                    console.log(err.getMessage(i));\n                }\n            } else {\n                console.log(err);\n            }\n        })\n        promises.push(promise)\n    }\n}\n<\/pre>\n<p>The script then waits for all of the query promises before doing final processing which prints the 10 busiest locations.<\/p>\n<pre>\nPromise.all(promises).then(values => {\n    for (hour=0; hour < 24; hour++) {\n        var items = Object.keys(results[hour]).map(function(key) {\n            return [key, results[hour][key]];\n        });\n\n        items.sort(function(first, second) {\n            return second[1] - first[1];\n        });\n  \n        locations = items.map(function(item) {\n            return item[0]\n        })\n\n        console.log(hour+\": \"+locations.slice(0, 10))\n    }\n})\n<\/pre>\n<pre>\n0: 79,230,48,249,148,234,132,161,164,114\n1: 79,148,48,230,249,114,164,132,234,68\n2: 79,148,48,114,249,68,230,164,158,234\n3: 79,148,68,48,230,249,114,164,158,144\n4: 79,48,230,148,68,164,249,186,107,114\n5: 48,100,132,186,79,230,170,236,107,263\n6: 186,48,100,132,236,170,162,68,107,263\n7: 186,236,48,170,100,237,141,162,107,140\n8: 236,237,170,186,48,141,162,107,140,239\n9: 236,237,170,162,186,48,141,239,138,161\n10: 237,236,186,138,162,170,161,48,230,142\n11: 237,236,161,162,186,170,138,230,142,234\n12: 237,236,161,162,186,170,230,234,239,138\n13: 237,161,236,162,170,186,234,239,163,230\n14: 237,161,236,162,234,170,239,163,138,186\n15: 237,161,236,162,234,138,170,186,239,142\n16: 161,237,236,162,138,234,132,170,230,239\n17: 161,237,162,230,236,234,170,138,163,186\n18: 161,162,237,230,234,236,170,163,186,142\n19: 161,162,234,237,170,230,186,163,138,142\n20: 161,162,234,230,170,237,79,186,48,138\n21: 230,161,162,234,48,79,186,138,170,142\n22: 230,161,48,79,234,186,162,142,164,138\n23: 230,79,48,142,234,161,138,249,132,186\n<\/pre>\n<p>The results show that area 79 (East Village) is busiest in the early morning hours while area 237 (Upper East Side) is busiest mid-day and 161 (Manhattan Midtown) in the late afternoon and evening.<\/p>\n<p>It would be simple to change the final processing to calculate the number of trips on a percentile basis or modify the above query find the potential maximum revenue.<\/p>\n<p>Complete versions of the scripts can be downloaded <a href=\"https:\/\/griddb.net\/en\/download\/26412\/\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this blog, we\u00e2\u20ac\u2122ll take a look at some open data provided by the NYC Taxi Commission and showcase some simple scripts to ingest and analyze the data. The principles shown here are applicable to many different types of problems. If you haven\u00e2\u20ac\u2122t set up a GridDB server yet, follow this quickstart. If you need [&hellip;]<\/p>\n","protected":false},"author":71,"featured_media":26289,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-46598","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>Analyzing NYC Taxi Open Data with GridDB and NodeJS | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"In this blog, we\u00e2\u20ac\u2122ll take a look at some open data provided by the NYC Taxi Commission and showcase some simple scripts to ingest and analyze the data.\" \/>\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\/nyc-taxi-open-data-node-js\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Analyzing NYC Taxi Open Data with GridDB and NodeJS | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"In this blog, we\u00e2\u20ac\u2122ll take a look at some open data provided by the NYC Taxi Commission and showcase some simple scripts to ingest and analyze the data.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/\" \/>\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=\"2020-04-06T07:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-13T20:54:52+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.griddb.net\/wp-content\/uploads\/2020\/01\/taxi_1920x1276.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"1276\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Owen\" \/>\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=\"Owen\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/\"},\"author\":{\"name\":\"Owen\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/0f2f6d4b593adde8c43cf3ea5c794c66\"},\"headline\":\"Analyzing NYC Taxi Open Data with GridDB and NodeJS\",\"datePublished\":\"2020-04-06T07:00:00+00:00\",\"dateModified\":\"2025-11-13T20:54:52+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/\"},\"wordCount\":652,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/griddb.net\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2020\/01\/taxi_1920x1276.jpg\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/\",\"url\":\"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/\",\"name\":\"Analyzing NYC Taxi Open Data with GridDB and NodeJS | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2020\/01\/taxi_1920x1276.jpg\",\"datePublished\":\"2020-04-06T07:00:00+00:00\",\"dateModified\":\"2025-11-13T20:54:52+00:00\",\"description\":\"In this blog, we\u00e2\u20ac\u2122ll take a look at some open data provided by the NYC Taxi Commission and showcase some simple scripts to ingest and analyze the data.\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/#primaryimage\",\"url\":\"\/wp-content\/uploads\/2020\/01\/taxi_1920x1276.jpg\",\"contentUrl\":\"\/wp-content\/uploads\/2020\/01\/taxi_1920x1276.jpg\",\"width\":1920,\"height\":1276},{\"@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\/0f2f6d4b593adde8c43cf3ea5c794c66\",\"name\":\"Owen\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/47438a5c81215c7a9043be1b427e0bbd8dc0f77bd536f147f8495575149e4325?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/47438a5c81215c7a9043be1b427e0bbd8dc0f77bd536f147f8495575149e4325?s=96&d=mm&r=g\",\"caption\":\"Owen\"},\"url\":\"https:\/\/www.griddb.net\/en\/author\/owen\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Analyzing NYC Taxi Open Data with GridDB and NodeJS | GridDB: Open Source Time Series Database for IoT","description":"In this blog, we\u00e2\u20ac\u2122ll take a look at some open data provided by the NYC Taxi Commission and showcase some simple scripts to ingest and analyze the data.","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\/nyc-taxi-open-data-node-js\/","og_locale":"en_US","og_type":"article","og_title":"Analyzing NYC Taxi Open Data with GridDB and NodeJS | GridDB: Open Source Time Series Database for IoT","og_description":"In this blog, we\u00e2\u20ac\u2122ll take a look at some open data provided by the NYC Taxi Commission and showcase some simple scripts to ingest and analyze the data.","og_url":"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2020-04-06T07:00:00+00:00","article_modified_time":"2025-11-13T20:54:52+00:00","og_image":[{"width":1920,"height":1276,"url":"https:\/\/www.griddb.net\/wp-content\/uploads\/2020\/01\/taxi_1920x1276.jpg","type":"image\/jpeg"}],"author":"Owen","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"Owen","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/#article","isPartOf":{"@id":"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/"},"author":{"name":"Owen","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/0f2f6d4b593adde8c43cf3ea5c794c66"},"headline":"Analyzing NYC Taxi Open Data with GridDB and NodeJS","datePublished":"2020-04-06T07:00:00+00:00","dateModified":"2025-11-13T20:54:52+00:00","mainEntityOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/"},"wordCount":652,"commentCount":0,"publisher":{"@id":"https:\/\/griddb.net\/en\/#organization"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2020\/01\/taxi_1920x1276.jpg","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/","url":"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/","name":"Analyzing NYC Taxi Open Data with GridDB and NodeJS | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/griddb.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/#primaryimage"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2020\/01\/taxi_1920x1276.jpg","datePublished":"2020-04-06T07:00:00+00:00","dateModified":"2025-11-13T20:54:52+00:00","description":"In this blog, we\u00e2\u20ac\u2122ll take a look at some open data provided by the NYC Taxi Commission and showcase some simple scripts to ingest and analyze the data.","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/blog\/nyc-taxi-open-data-node-js\/#primaryimage","url":"\/wp-content\/uploads\/2020\/01\/taxi_1920x1276.jpg","contentUrl":"\/wp-content\/uploads\/2020\/01\/taxi_1920x1276.jpg","width":1920,"height":1276},{"@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\/0f2f6d4b593adde8c43cf3ea5c794c66","name":"Owen","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/47438a5c81215c7a9043be1b427e0bbd8dc0f77bd536f147f8495575149e4325?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/47438a5c81215c7a9043be1b427e0bbd8dc0f77bd536f147f8495575149e4325?s=96&d=mm&r=g","caption":"Owen"},"url":"https:\/\/www.griddb.net\/en\/author\/owen\/"}]}},"_links":{"self":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46598","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\/71"}],"replies":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/comments?post=46598"}],"version-history":[{"count":1,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46598\/revisions"}],"predecessor-version":[{"id":51283,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46598\/revisions\/51283"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media\/26289"}],"wp:attachment":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media?parent=46598"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/categories?post=46598"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/tags?post=46598"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}