From a4fcfa1a344c2a45ca9abd133abecb6a058469b9 Mon Sep 17 00:00:00 2001 From: "sumit shinde ( Roni )" Date: Tue, 11 Jun 2024 21:49:08 +0530 Subject: [PATCH 01/13] blog : Using Node-RED as an ETL tool --- .../etl-with-node-red-chart-based-on-age.png | Bin 0 -> 25369 bytes ...th-node-red-chart-based-on-job-profile.png | Bin 0 -> 67476 bytes .../2024/06/using-node-red-as-an-etl-tool.md | 224 ++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 src/blog/2024/06/images/etl-with-node-red-chart-based-on-age.png create mode 100644 src/blog/2024/06/images/etl-with-node-red-chart-based-on-job-profile.png create mode 100644 src/blog/2024/06/using-node-red-as-an-etl-tool.md diff --git a/src/blog/2024/06/images/etl-with-node-red-chart-based-on-age.png b/src/blog/2024/06/images/etl-with-node-red-chart-based-on-age.png new file mode 100644 index 0000000000000000000000000000000000000000..d13f8834041c6751b1eebbece32844e5d75470f6 GIT binary patch literal 25369 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 wjZhnQ73s|eC?$~^ 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 pR literal 0 HcmV?d00001 diff --git a/src/blog/2024/06/using-node-red-as-an-etl-tool.md b/src/blog/2024/06/using-node-red-as-an-etl-tool.md new file mode 100644 index 0000000000..310b750320 --- /dev/null +++ b/src/blog/2024/06/using-node-red-as-an-etl-tool.md @@ -0,0 +1,224 @@ +--- +title: Using Node-RED as an ETL Tool +subtitle: A Step-by-Step Guide on How to Use Node-RED as an ETL Tool +description: Learn how to utilize Node-RED as an ETL (Extract, Transform, Load) tool, and explore its advantages and disadvantages in this context. +date: 2024-06-05 +authors:["Sumit Shinde"] +image: +tags: + - etl + - extract + - transform + - load + - analysis + - business intelligence +--- + +ETL is essential for data integration and analysis, playing a crucial role in many business contexts by helping to gain detailed business insights. Node-RED, known for its ease in creating IoT applications, has also been recognized for its potential in ETL tasks. When IBM published its blog on using Node-RED for ETL, the topic garnered significant attention and sparked discussions on whether it could be effectively utilized for ETL. In this guide, we'll explore how to use Node-RED for ETL, discussing both its strengths and weaknesses along the way. + + + +## What is ETL + +[ETL](https://en.wikipedia.org/wiki/Extract,_transform,_load) (Extract, Transform, Load) is a fundamental process in data integration and data warehousing. It encompasses three main stages: extracting data from various sources, transforming it into a format suitable for analysis, and loading it into a target database or data warehouse. This process allows businesses to consolidate data from multiple sources, ensuring it is clean, consistent, and ready for generating insights and making informed decisions. + +## Node-RED as ETL a tool + +Node-RED is specifically used for building various types of IoT applications. During the development of such applications, Node-RED is sometimes used as an ETL (Extract, Transform, Load) tool without even realizing it. For instance, when monitoring sensors across a facility, the process involves extracting data from sensors, transforming (cleaning and formatting) sensor data, and loading it into a database. There are thousands of other examples like this. This demonstrates that Node-RED has already been adopted as an ETL tool for certain scenarios. + +### Extracting + +Node-RED can extract data from various sources, including APIs, databases, local filesystems, and IoT devices using built-in nodes and community-contributed nodes. For example, the HTTP request node can be used to pull data from web services, while nodes for MySQL, MongoDB, and PostgreSQL can extract data from databases. Nodes for MQTT and Kafka can fetch data from message brokers. Additionally, there are cloud nodes such as AWS, Google Cloud Platform (GCP), and IBM Watson that allow extraction of data from cloud storage services. + +### Transforming + +Transformation in Node-RED involves converting data into the desired format, applying business rules, and cleaning it. This can be done using function nodes for custom JavaScript code, along with nodes like JSON, split, join, change CSV, and XML for parsing and formatting. + +### Loading + +The final step in the ETL process is loading the transformed data into a target system, such as a database or data warehouse. Node-RED supports various output nodes to send data to different destinations. For instance, you can use the MySQL node to insert data into a MySQL database, or the HTTP request node to send data to a web service endpoint. + +### Visualizing and Analyzing + +In addition to the core ETL (Extract, Transform, Load) process, visualizing and analyzing data is a crucial step for gaining insights. While visualization isn't part of the ETL acronym itself, it plays a significant role in understanding and interpreting transformed data. In Node-RED, you can easily visualize data using Node-RED Dashboard 2.0 charts. + +Node-RED Dashboard 2.0 provides several chart options, and more are expected in the future. For more information and to explore available chart types, refer to the [Node-RED Dashboard 2.0 charts documentation](https://dashboard.flowfuse.com/nodes/widgets/ui-chart.html). + +*Note: We have mentioned only a few nodes that can be used in the ETL process, but there are thousands of other nodes that you can explore yourself by visiting the [Node-RED Nodes Library](https://flows.nodered.org/search?type=node)* + +## Building a Simple ETL Project Using Node-RED + +Let's walk through a simple project where we use Node-RED as an ETL tool to extract sample customer data from an API, transform it, and then load cleaned data into a MongoDB database and process data into a local file. + +*Note: The goal of this project is to understand how to utilize Node-RED as an ETL tool. We assume that the reader has a basic knowledge of Node-RED.* + +## Prerequisite + +Before proceeding further make sure you have installed the following nodes. + +1. [node-red-contrib-mongodb4](https://flows.nodered.org/node/node-red-contrib-mongodb4) +2. [@flowfuse/node-red-dashboard](https://dashboard.flowfuse.com/) + +## Extracting Data + +1. Drag an Inject node onto the canvas. +2. Drag an HTTP Request node onto the canvas, double-click on it, and set the URL to `https://api.slingacademy.com/v1/sample-data/files/customers.json`. +3. Drag a Link Out node onto the canvas. +4. Connect the Inject node's output to the input of the HTTP Request node, and the HTTP Request node's output to the input of the Link Out node. + +Now, if you add a Debug node after the HTTP Request node, you will see an array of objects containing customer data in the Debug panel. Each object has properties such as `first_name`, `last_name`, `email`, and others. + +Next, we'll perform a transformation to replace the existing properties `first_name` and `last_name` with a single property `full_name` that concatenates them. We'll cover this transformation in the next section. + +## Transforming Data + +### Data Cleaning + +1. Drag a Link In node onto the canvas, double-click on it, and select the name of the Link Out node added in the above section. +2. Drag a Split node onto the canvas. +3. Drag a Change node onto the canvas and Set `msg.payload.full_name` to `payload.first_name & " " & payload.last_name` as the JSONata expression, then delete unnecessary properties like `first_name` and `last_name`. +4. Drag a Join node onto the canvas. + +until now we have created a flow that will create a new property in customer data objects called full_name and then it will delete the unnecessary properties. in summary, we have cleaned the data according to our needs. + +### Customer Data Deduplication + +1. Drag a Change node onto the canvas, and set `msg.data` to `msg.payload` and `msg.payload` to `[]`. +2. Drag a MongoDB4 node onto the canvas, and configure it with your correct details. If you haven't used MongoDB with Node-RED, please refer to the [Node-RED MongoDB documentation](https://flows.nodered.org/node/node-red-contrib-mongodb4). Enter `find` into the Operation field. +3. Drag a Function node onto the canvas and insert the following code into it: + +```javascript +// Check if previously stored customer data is present, and ensure it's an array +let previously_stored_customer_data = Array.isArray(msg.payload) ? msg.payload : (msg.payload ? [msg.payload] : []); + +// Ensure latest customer data is an array +let latest_customer_data = Array.isArray(msg.data) ? Array.from(msg.data) : (msg.data ? [msg.data] : []); + +// Check if both previously stored and latest customer data are not empty +if (latest_customer_data.length !== 0 && previously_stored_customer_data.length !== 0) { +    // Extract emails from previously stored customer data +    let emailArray1 = previously_stored_customer_data.map(customer => customer.email); + +    // Filter out customers that are already in previously stored data +    let filtered_customer_data = latest_customer_data.filter(customer => !emailArray1.includes(customer.email)); + + msg.payload = filtered_customer_data; +    return msg; +} else { +    // Case where there's no previously stored data (first ETL cycle after deploying flow) + msg.payload = latest_customer_data; +    return msg; +} +``` + +4. Drag a Link-out node onto the canvas. + +Now, we have added some more nodes that perform data deduplication. This means we will create a new array containing unique data that is not already stored in the database to avoid data duplications. + +## Data Processing + +1. Drag a Function node onto the canvas and insert the following code into it: + +```javascript +let data = msg.payload; + +// Initialize counters +let ageRanges = { +    "0-20": 0, +    "21-30": 0, +    "31-40": 0, +    "41+": 0 +}; + +let genderTotals = { +    male: 0, +    female: 0, +    other: 0  // Default to 'other' if gender is not specified +}; + +let jobStatusTotals = {}; + +// Process each document in the data array +data.forEach(doc => { +    // Calculate age range +    let age = parseInt(doc.age); +    let ageRange; +    if (age <= 20) { +        ageRange = "0-20"; + } else if (age <= 30) { +        ageRange = "21-30"; + } else if (age <= 40) { +        ageRange = "31-40"; + } else { +        ageRange = "41+"; + } + ageRanges[ageRange]++; // Increment age range count + +    // Count gender +    let gender = doc.gender || 'other'; // Default to 'other' if gender is not specified + genderTotals[gender]++; + +    // Count job status +    let job = doc.job || 'Unknown'; // Default to 'Unknown' if job is not specified +    if (jobStatusTotals[job]) { + jobStatusTotals[job]++; + } else { + jobStatusTotals[job] = 1; + } +}); + +// Prepare output payload +msg.payload = { +    "Age Ranges": ageRanges, +    "genderTotals": genderTotals, +    "JobStatus Totals": jobStatusTotals +}; + +return msg; +``` +2. Drag another Link-out node onto the canvas. + +Finally, in this phase of transformation, we are tallying the total number of users based on age, gender, and job title. This allows us to quickly analyze and understand our user demographics based on these details so that later we can visualize this data easily. + +## Loading data + +1. Drag a Link-in node onto the canvas, double-click on it, and select the name of the Link-out node connected to the data deduplication function. Then, drag another Link-in node and connect it to the Link-out node connected to the data processing function node. + +2. Drag a MongoDB4 node onto the canvas and configure it correctly. Select the correct collection and enter `insertMany` into the Operation field. + +3. Drag a File Write node onto the canvas, set the path, and select the action to "override". + +!["Screenshot of dashboard visualizing process customer data based on job profile"](./images/etl-with-node-red-chart-based-on-job-profile.png "Screenshot of dashboard visualizing process customer data based on job profile"){data-zoomable} + +!["Screenshot of dashboard visualizing process customer data based on age group"](./images/etl-with-node-red-chart-based-on-age.png "Screenshot of dashboard visualizing process customer data based on age group"){data-zoomable} + + +Following is the complete flow of the project along with dashboard visualization. + +{% renderFlow %, 400} +[{"id":"e85cb581eb249115","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["218b698ddba2210b","638eddcd2b5f645e","9773152e6a0f2287","fd68d5c864a0e7c9"],"x":114,"y":159,"w":532,"h":182},{"id":"218b698ddba2210b","type":"http request","z":"977143edb097b685","g":"e85cb581eb249115","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.slingacademy.com/v1/sample-data/files/customers.json","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":430,"y":300,"wires":[["fd68d5c864a0e7c9"]]},{"id":"638eddcd2b5f645e","type":"inject","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extract Data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":300,"wires":[["218b698ddba2210b"]]},{"id":"9773152e6a0f2287","type":"comment","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extracting customer data from api","info":"","x":330,"y":200,"wires":[]},{"id":"fd68d5c864a0e7c9","type":"link out","z":"977143edb097b685","g":"e85cb581eb249115","name":"link out 1","mode":"link","links":["0e0129a95e24355c"],"x":605,"y":300,"wires":[]},{"id":"e0adf6e180ec1a7c","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["ace58c34d1566f51","d2a48c9825b224b4","9cd9d88bb507cc49","ef5e8501b76cfec8","d3a842120a526a7f","6f472c26ef54f974","a88a07f39e0e941d","0e0129a95e24355c","c7150b3b68fc34a0","3f3ad8e528f5800b","dd3fb62233d5477e"],"x":104,"y":379,"w":1342,"h":202},{"id":"ace58c34d1566f51","type":"split","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":250,"y":500,"wires":[["d2a48c9825b224b4"]]},{"id":"d2a48c9825b224b4","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","rules":[{"t":"set","p":"payload.full_name","pt":"msg","to":"payload.first_name & \" \" & payload.last_name","tot":"jsonata"},{"t":"delete","p":"payload.first_name","pt":"msg"},{"t":"delete","p":"payload.last_name","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":500,"wires":[["ef5e8501b76cfec8"]]},{"id":"9cd9d88bb507cc49","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"data processing","func":"let data = msg.payload\n\nlet ageRanges = {\n    \"0-20\": 0,\n    \"21-30\": 0,\n    \"31-40\": 0,\n    \"41+\": 0\n};\n\nlet genderTotals = {\n    male: 0,\n    female: 0,\n    other: 0  // Add other genders as needed\n};\n\nlet jobStatusTotals = {};\n\n// Iterate through each document to calculate counts\ndata.forEach(doc => {\n    // Calculate age range\n    let age = parseInt(doc.age);\n    let ageRange;\n    if (age <= 20) {\n        ageRange = \"0-20\";\n    } else if (age <= 30) {\n        ageRange = \"21-30\";\n    } else if (age <= 40) {\n        ageRange = \"31-40\";\n    } else {\n        ageRange = \"41+\";\n    }\n    // Increment age range count\n    ageRanges[ageRange]++;\n\n    // Increment gender count\n    if (doc.gender === 'male') {\n        genderTotals.male++;\n    } else if (doc.gender === 'female') {\n        genderTotals.female++;\n    } else {\n        genderTotals.other++;\n    }\n\n    // Increment job status count\n    if (jobStatusTotals[doc.job]) {\n        jobStatusTotals[doc.job]++;\n    } else {\n        jobStatusTotals[doc.job] = 1;\n    }\n});\n\n\nmsg.payload = {\n    \"ageRanges\": ageRanges,\n    \"genderTotals\": genderTotals,\n    \"jobStatusTotals\": jobStatusTotals\n}; \n\n// Return the aggregated counts object\nreturn msg","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":980,"y":540,"wires":[["3f3ad8e528f5800b"]]},{"id":"ef5e8501b76cfec8","type":"join","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":690,"y":500,"wires":[["9cd9d88bb507cc49","6f472c26ef54f974"]]},{"id":"d3a842120a526a7f","type":"comment","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Tranforming customer data","info":"","x":330,"y":420,"wires":[]},{"id":"6f472c26ef54f974","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","rules":[{"t":"set","p":"data","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":970,"y":420,"wires":[["a88a07f39e0e941d"]]},{"id":"a88a07f39e0e941d","type":"mongodb4","z":"977143edb097b685","g":"e0adf6e180ec1a7c","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"find","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":1130,"y":420,"wires":[["dd3fb62233d5477e"]]},{"id":"0e0129a95e24355c","type":"link in","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link in 1","links":["fd68d5c864a0e7c9"],"x":145,"y":500,"wires":[["ace58c34d1566f51"]]},{"id":"c7150b3b68fc34a0","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 2","mode":"link","links":["78176aee11393705"],"x":1405,"y":420,"wires":[]},{"id":"3f3ad8e528f5800b","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 3","mode":"link","links":["ecfa23782d33d813"],"x":1115,"y":540,"wires":[]},{"id":"dd3fb62233d5477e","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","func":"let previously_stored_customer_data = Array.isArray(msg.payload) ? msg.payload : (msg.payload ? [msg.payload] : []);\nlet latest_customer_data = Array.isArray(msg.data) ? Array.from(msg.data) : (msg.data ? [msg.data] : []);\n\nif (latest_customer_data.length !== 0 && previously_stored_customer_data.length !== 0) {\n    let fullNameArray1 = previously_stored_customer_data.map(customer => customer.full_name);\n    let filtered_customer_data = latest_customer_data.filter(customer => !fullNameArray1.includes(customer.full_name));\n    msg.payload = [filtered_customer_data];\n    return msg\n} else {\n    // Case where there's no previously stored data\n    msg.payload = [latest_customer_data];\n    return msg\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1290,"y":420,"wires":[["c7150b3b68fc34a0"]]},{"id":"a0c7c3410ffb0e89","type":"mongodb4-client","name":"","protocol":"mongodb+srv","hostname":"","port":"","dbName":"mydb","appName":"","authSource":"","authMechanism":"DEFAULT","tls":false,"tlsCAFile":"","tlsCertificateKeyFile":"","tlsInsecure":false,"connectTimeoutMS":"30000","socketTimeoutMS":"0","minPoolSize":"0","maxPoolSize":"100","maxIdleTimeMS":"0","uri":"mongodb+srv://cluster0.uxibwot.mongodb.net","advanced":"{}","uriTabActive":"tab-uri-advanced"},{"id":"ac5e2cabb6251314","type":"group","z":"977143edb097b685","name":"","style":{"label":true},"nodes":["d6a4a19c23a0f42b","78176aee11393705","ecfa23782d33d813","dab90d6302b1c885","bc4afbc715e3b64d","d781431fed20d650","f19a1157e25b47df"],"x":114,"y":619,"w":592,"h":222},{"id":"d6a4a19c23a0f42b","type":"mongodb4","z":"977143edb097b685","g":"ac5e2cabb6251314","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"insertMany","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":370,"y":720,"wires":[["bc4afbc715e3b64d"]]},{"id":"78176aee11393705","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 2","links":["c7150b3b68fc34a0"],"x":155,"y":720,"wires":[["d6a4a19c23a0f42b"]]},{"id":"ecfa23782d33d813","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 3","links":["3f3ad8e528f5800b"],"x":155,"y":800,"wires":[["dab90d6302b1c885"]]},{"id":"dab90d6302b1c885","type":"file","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"","filename":"./customer_data_analytics","filenameType":"str","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":390,"y":800,"wires":[["d781431fed20d650"]]},{"id":"bc4afbc715e3b64d","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":720,"wires":[]},{"id":"d781431fed20d650","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":600,"y":800,"wires":[]},{"id":"f19a1157e25b47df","type":"comment","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Loading data into file and database","info":"","x":380,"y":660,"wires":[]},{"id":"520f961e35d10da4","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["9b534cdc46dfc52a","52c6d1c11c84571c","ed6fc24b155aef33","af4bc1c2a6e6d020","572c04ca900af9d5","b64ddca6aab82cb2","a135a8ed2c447561"],"x":114,"y":879,"w":1372,"h":142},{"id":"9b534cdc46dfc52a","type":"ui-chart","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"chart","order":2,"chartType":"bar","category":"category","categoryType":"property","xAxisProperty":"","xAxisPropertyType":"msg","xAxisType":"category","yAxisProperty":"value","ymin":"","ymax":"","action":"replace","pointShape":"circle","pointRadius":4,"showLegend":false,"removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"width":"13","height":8,"className":"","x":1410,"y":980,"wires":[[]]},{"id":"52c6d1c11c84571c","type":"function","z":"977143edb097b685","g":"520f961e35d10da4","name":"function 1","func":"let selectedDataForChart = global.get(\"selectedDataForChart\")\n// Assuming msg.payload is an object\nlet data = msg.payload[selectedDataForChart]\nlet result = [];\n\n// Loop through each key in the payload object\nObject.keys(data).forEach(key => {\n    result.push({ category: key, value: data[key] });\n});\n\nmsg.payload = result\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1240,"y":980,"wires":[["9b534cdc46dfc52a"]]},{"id":"ed6fc24b155aef33","type":"ui-dropdown","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"Select Option:","tooltip":"","order":1,"width":0,"height":0,"passthru":false,"multiple":false,"options":[{"label":"Based on age group","value":"ageRanges","type":"str"},{"label":"Based on gender group","value":"genderTotals","type":"str"},{"label":"Based on job profile","value":"jobStatusTotals","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":220,"y":980,"wires":[["b64ddca6aab82cb2"]]},{"id":"af4bc1c2a6e6d020","type":"file in","z":"977143edb097b685","g":"520f961e35d10da4","name":"","filename":"./customer_data_analytics","filenameType":"str","format":"lines","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":810,"y":980,"wires":[["572c04ca900af9d5"]]},{"id":"572c04ca900af9d5","type":"json","z":"977143edb097b685","g":"520f961e35d10da4","name":"","property":"payload","action":"","pretty":false,"x":1050,"y":980,"wires":[["52c6d1c11c84571c"]]},{"id":"b64ddca6aab82cb2","type":"change","z":"977143edb097b685","g":"520f961e35d10da4","name":"store selected data in global context","rules":[{"t":"set","p":"selectedDataForChart","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":980,"wires":[["af4bc1c2a6e6d020"]]},{"id":"a135a8ed2c447561","type":"comment","z":"977143edb097b685","g":"520f961e35d10da4","name":"Visualizing data on charts","info":"","x":350,"y":920,"wires":[]},{"id":"1859e113313a5279","type":"ui-group","name":"chart","page":"f10b4d0259e43aeb","width":"13","height":"1","order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"f10b4d0259e43aeb","type":"ui-page","name":"home","ui":"cb79bc4520925e32","path":"/","icon":"","layout":"grid","theme":"2c5d702b11de7dd1","order":1,"className":"","visible":true,"disabled":"false"},{"id":"cb79bc4520925e32","type":"ui-base","name":"My UI","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false},{"id":"2c5d702b11de7dd1","type":"ui-theme","name":"Theme Name","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"}}] +{% endrenderFlow %} + +## What are the limitations of using ETL as an ETL tool + +While Node-RED is versatile, there are some limitations to consider: + +- **Scalability:** Node-RED might struggle with extremely large datasets compared to dedicated ETL tools. +- **Performance:** For very complex transformations or high-volume data, performance might not match that of specialized ETL solutions. +- **Advanced Features:** Some advanced ETL features, like automated schema detection and sophisticated error handling, might require additional customization or external modules. +- **Data Governance:** Node-RED does not inherently provide robust data governance and lineage tracking which are often essential in enterprise ETL tools. + +## Benefits of using Node-RED as an ETL tool. + +Despite its limitations, Node-RED offers several benefits: + +1. **Ease of Use:** Its visual programming interface makes it accessible to non-developers. +2. **Flexibility:** A wide range of nodes and the ability to write custom JavaScript allow for flexible data processing. +3. **Integration:** Strong support for IoT and real-time data processing, making it ideal for integrating diverse data sources. +4. **Cost-Effective:** Being open-source, Node-RED can be a cost-effective alternative to expensive ETL tools. +5. **Community Support:** A large community provides a wealth of nodes, examples, and support. + +## Additional resources + +- [Implementing ETL flows with Node-RED](https://developer.ibm.com/articles/implementing-etl-flows-with-node-red/): Read this IBM blog where a team member explains how they replaced a dedicated ETL tool with Node-RED. +- [Node-RED Forum Thread](https://discourse.nodered.org/t/etl-pipelines-with-node-red/): Explore this Node-RED forum thread where community members discussed how to utilize Node-RED as an ETL tool, including solutions for handling large datasets. \ No newline at end of file From c94a79eb86feed8b096a09df2f0867eb56086206 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:21:42 +0000 Subject: [PATCH 02/13] Optimised images with calibre/image-actions --- .../etl-with-node-red-chart-based-on-age.png | Bin 25369 -> 23986 bytes ...th-node-red-chart-based-on-job-profile.png | Bin 67476 -> 61432 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/blog/2024/06/images/etl-with-node-red-chart-based-on-age.png b/src/blog/2024/06/images/etl-with-node-red-chart-based-on-age.png index d13f8834041c6751b1eebbece32844e5d75470f6..49484f8e46ae32a8957bb4c8695a665dbefbf5d3 100644 GIT binary patch literal 23986 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 wjUy; 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⪙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 pR From 94eaa1fa6fa42a4583930b4bb1d893527377bb29 Mon Sep 17 00:00:00 2001 From: "sumit shinde ( Roni )" <110285294+sumitshinde-84@users.noreply.github.com> Date: Tue, 11 Jun 2024 21:51:58 +0530 Subject: [PATCH 03/13] Update using-node-red-as-an-etl-tool.md --- src/blog/2024/06/using-node-red-as-an-etl-tool.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/blog/2024/06/using-node-red-as-an-etl-tool.md b/src/blog/2024/06/using-node-red-as-an-etl-tool.md index 310b750320..4e4b100091 100644 --- a/src/blog/2024/06/using-node-red-as-an-etl-tool.md +++ b/src/blog/2024/06/using-node-red-as-an-etl-tool.md @@ -3,8 +3,8 @@ title: Using Node-RED as an ETL Tool subtitle: A Step-by-Step Guide on How to Use Node-RED as an ETL Tool description: Learn how to utilize Node-RED as an ETL (Extract, Transform, Load) tool, and explore its advantages and disadvantages in this context. date: 2024-06-05 -authors:["Sumit Shinde"] -image: +authors: ["sumit-shinde"] +image: tags: - etl - extract @@ -221,4 +221,4 @@ Despite its limitations, Node-RED offers several benefits: ## Additional resources - [Implementing ETL flows with Node-RED](https://developer.ibm.com/articles/implementing-etl-flows-with-node-red/): Read this IBM blog where a team member explains how they replaced a dedicated ETL tool with Node-RED. -- [Node-RED Forum Thread](https://discourse.nodered.org/t/etl-pipelines-with-node-red/): Explore this Node-RED forum thread where community members discussed how to utilize Node-RED as an ETL tool, including solutions for handling large datasets. \ No newline at end of file +- [Node-RED Forum Thread](https://discourse.nodered.org/t/etl-pipelines-with-node-red/): Explore this Node-RED forum thread where community members discussed how to utilize Node-RED as an ETL tool, including solutions for handling large datasets. From bed67501c7c337ae8c320eb7bebe7d3e9afb2608 Mon Sep 17 00:00:00 2001 From: "sumit shinde ( Roni )" <110285294+sumitshinde-84@users.noreply.github.com> Date: Tue, 11 Jun 2024 21:55:11 +0530 Subject: [PATCH 04/13] Update using-node-red-as-an-etl-tool.md --- src/blog/2024/06/using-node-red-as-an-etl-tool.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blog/2024/06/using-node-red-as-an-etl-tool.md b/src/blog/2024/06/using-node-red-as-an-etl-tool.md index 4e4b100091..0ada8c022a 100644 --- a/src/blog/2024/06/using-node-red-as-an-etl-tool.md +++ b/src/blog/2024/06/using-node-red-as-an-etl-tool.md @@ -195,7 +195,7 @@ Finally, in this phase of transformation, we are tallying the total number of us Following is the complete flow of the project along with dashboard visualization. -{% renderFlow %, 400} +{% renderFlow %} [{"id":"e85cb581eb249115","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["218b698ddba2210b","638eddcd2b5f645e","9773152e6a0f2287","fd68d5c864a0e7c9"],"x":114,"y":159,"w":532,"h":182},{"id":"218b698ddba2210b","type":"http request","z":"977143edb097b685","g":"e85cb581eb249115","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.slingacademy.com/v1/sample-data/files/customers.json","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":430,"y":300,"wires":[["fd68d5c864a0e7c9"]]},{"id":"638eddcd2b5f645e","type":"inject","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extract Data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":300,"wires":[["218b698ddba2210b"]]},{"id":"9773152e6a0f2287","type":"comment","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extracting customer data from api","info":"","x":330,"y":200,"wires":[]},{"id":"fd68d5c864a0e7c9","type":"link out","z":"977143edb097b685","g":"e85cb581eb249115","name":"link out 1","mode":"link","links":["0e0129a95e24355c"],"x":605,"y":300,"wires":[]},{"id":"e0adf6e180ec1a7c","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["ace58c34d1566f51","d2a48c9825b224b4","9cd9d88bb507cc49","ef5e8501b76cfec8","d3a842120a526a7f","6f472c26ef54f974","a88a07f39e0e941d","0e0129a95e24355c","c7150b3b68fc34a0","3f3ad8e528f5800b","dd3fb62233d5477e"],"x":104,"y":379,"w":1342,"h":202},{"id":"ace58c34d1566f51","type":"split","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":250,"y":500,"wires":[["d2a48c9825b224b4"]]},{"id":"d2a48c9825b224b4","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","rules":[{"t":"set","p":"payload.full_name","pt":"msg","to":"payload.first_name & \" \" & payload.last_name","tot":"jsonata"},{"t":"delete","p":"payload.first_name","pt":"msg"},{"t":"delete","p":"payload.last_name","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":500,"wires":[["ef5e8501b76cfec8"]]},{"id":"9cd9d88bb507cc49","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"data processing","func":"let data = msg.payload\n\nlet ageRanges = {\n    \"0-20\": 0,\n    \"21-30\": 0,\n    \"31-40\": 0,\n    \"41+\": 0\n};\n\nlet genderTotals = {\n    male: 0,\n    female: 0,\n    other: 0  // Add other genders as needed\n};\n\nlet jobStatusTotals = {};\n\n// Iterate through each document to calculate counts\ndata.forEach(doc => {\n    // Calculate age range\n    let age = parseInt(doc.age);\n    let ageRange;\n    if (age <= 20) {\n        ageRange = \"0-20\";\n    } else if (age <= 30) {\n        ageRange = \"21-30\";\n    } else if (age <= 40) {\n        ageRange = \"31-40\";\n    } else {\n        ageRange = \"41+\";\n    }\n    // Increment age range count\n    ageRanges[ageRange]++;\n\n    // Increment gender count\n    if (doc.gender === 'male') {\n        genderTotals.male++;\n    } else if (doc.gender === 'female') {\n        genderTotals.female++;\n    } else {\n        genderTotals.other++;\n    }\n\n    // Increment job status count\n    if (jobStatusTotals[doc.job]) {\n        jobStatusTotals[doc.job]++;\n    } else {\n        jobStatusTotals[doc.job] = 1;\n    }\n});\n\n\nmsg.payload = {\n    \"ageRanges\": ageRanges,\n    \"genderTotals\": genderTotals,\n    \"jobStatusTotals\": jobStatusTotals\n}; \n\n// Return the aggregated counts object\nreturn msg","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":980,"y":540,"wires":[["3f3ad8e528f5800b"]]},{"id":"ef5e8501b76cfec8","type":"join","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":690,"y":500,"wires":[["9cd9d88bb507cc49","6f472c26ef54f974"]]},{"id":"d3a842120a526a7f","type":"comment","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Tranforming customer data","info":"","x":330,"y":420,"wires":[]},{"id":"6f472c26ef54f974","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","rules":[{"t":"set","p":"data","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":970,"y":420,"wires":[["a88a07f39e0e941d"]]},{"id":"a88a07f39e0e941d","type":"mongodb4","z":"977143edb097b685","g":"e0adf6e180ec1a7c","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"find","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":1130,"y":420,"wires":[["dd3fb62233d5477e"]]},{"id":"0e0129a95e24355c","type":"link in","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link in 1","links":["fd68d5c864a0e7c9"],"x":145,"y":500,"wires":[["ace58c34d1566f51"]]},{"id":"c7150b3b68fc34a0","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 2","mode":"link","links":["78176aee11393705"],"x":1405,"y":420,"wires":[]},{"id":"3f3ad8e528f5800b","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 3","mode":"link","links":["ecfa23782d33d813"],"x":1115,"y":540,"wires":[]},{"id":"dd3fb62233d5477e","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","func":"let previously_stored_customer_data = Array.isArray(msg.payload) ? msg.payload : (msg.payload ? [msg.payload] : []);\nlet latest_customer_data = Array.isArray(msg.data) ? Array.from(msg.data) : (msg.data ? [msg.data] : []);\n\nif (latest_customer_data.length !== 0 && previously_stored_customer_data.length !== 0) {\n    let fullNameArray1 = previously_stored_customer_data.map(customer => customer.full_name);\n    let filtered_customer_data = latest_customer_data.filter(customer => !fullNameArray1.includes(customer.full_name));\n    msg.payload = [filtered_customer_data];\n    return msg\n} else {\n    // Case where there's no previously stored data\n    msg.payload = [latest_customer_data];\n    return msg\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1290,"y":420,"wires":[["c7150b3b68fc34a0"]]},{"id":"a0c7c3410ffb0e89","type":"mongodb4-client","name":"","protocol":"mongodb+srv","hostname":"","port":"","dbName":"mydb","appName":"","authSource":"","authMechanism":"DEFAULT","tls":false,"tlsCAFile":"","tlsCertificateKeyFile":"","tlsInsecure":false,"connectTimeoutMS":"30000","socketTimeoutMS":"0","minPoolSize":"0","maxPoolSize":"100","maxIdleTimeMS":"0","uri":"mongodb+srv://cluster0.uxibwot.mongodb.net","advanced":"{}","uriTabActive":"tab-uri-advanced"},{"id":"ac5e2cabb6251314","type":"group","z":"977143edb097b685","name":"","style":{"label":true},"nodes":["d6a4a19c23a0f42b","78176aee11393705","ecfa23782d33d813","dab90d6302b1c885","bc4afbc715e3b64d","d781431fed20d650","f19a1157e25b47df"],"x":114,"y":619,"w":592,"h":222},{"id":"d6a4a19c23a0f42b","type":"mongodb4","z":"977143edb097b685","g":"ac5e2cabb6251314","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"insertMany","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":370,"y":720,"wires":[["bc4afbc715e3b64d"]]},{"id":"78176aee11393705","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 2","links":["c7150b3b68fc34a0"],"x":155,"y":720,"wires":[["d6a4a19c23a0f42b"]]},{"id":"ecfa23782d33d813","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 3","links":["3f3ad8e528f5800b"],"x":155,"y":800,"wires":[["dab90d6302b1c885"]]},{"id":"dab90d6302b1c885","type":"file","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"","filename":"./customer_data_analytics","filenameType":"str","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":390,"y":800,"wires":[["d781431fed20d650"]]},{"id":"bc4afbc715e3b64d","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":720,"wires":[]},{"id":"d781431fed20d650","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":600,"y":800,"wires":[]},{"id":"f19a1157e25b47df","type":"comment","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Loading data into file and database","info":"","x":380,"y":660,"wires":[]},{"id":"520f961e35d10da4","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["9b534cdc46dfc52a","52c6d1c11c84571c","ed6fc24b155aef33","af4bc1c2a6e6d020","572c04ca900af9d5","b64ddca6aab82cb2","a135a8ed2c447561"],"x":114,"y":879,"w":1372,"h":142},{"id":"9b534cdc46dfc52a","type":"ui-chart","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"chart","order":2,"chartType":"bar","category":"category","categoryType":"property","xAxisProperty":"","xAxisPropertyType":"msg","xAxisType":"category","yAxisProperty":"value","ymin":"","ymax":"","action":"replace","pointShape":"circle","pointRadius":4,"showLegend":false,"removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"width":"13","height":8,"className":"","x":1410,"y":980,"wires":[[]]},{"id":"52c6d1c11c84571c","type":"function","z":"977143edb097b685","g":"520f961e35d10da4","name":"function 1","func":"let selectedDataForChart = global.get(\"selectedDataForChart\")\n// Assuming msg.payload is an object\nlet data = msg.payload[selectedDataForChart]\nlet result = [];\n\n// Loop through each key in the payload object\nObject.keys(data).forEach(key => {\n    result.push({ category: key, value: data[key] });\n});\n\nmsg.payload = result\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1240,"y":980,"wires":[["9b534cdc46dfc52a"]]},{"id":"ed6fc24b155aef33","type":"ui-dropdown","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"Select Option:","tooltip":"","order":1,"width":0,"height":0,"passthru":false,"multiple":false,"options":[{"label":"Based on age group","value":"ageRanges","type":"str"},{"label":"Based on gender group","value":"genderTotals","type":"str"},{"label":"Based on job profile","value":"jobStatusTotals","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":220,"y":980,"wires":[["b64ddca6aab82cb2"]]},{"id":"af4bc1c2a6e6d020","type":"file in","z":"977143edb097b685","g":"520f961e35d10da4","name":"","filename":"./customer_data_analytics","filenameType":"str","format":"lines","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":810,"y":980,"wires":[["572c04ca900af9d5"]]},{"id":"572c04ca900af9d5","type":"json","z":"977143edb097b685","g":"520f961e35d10da4","name":"","property":"payload","action":"","pretty":false,"x":1050,"y":980,"wires":[["52c6d1c11c84571c"]]},{"id":"b64ddca6aab82cb2","type":"change","z":"977143edb097b685","g":"520f961e35d10da4","name":"store selected data in global context","rules":[{"t":"set","p":"selectedDataForChart","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":980,"wires":[["af4bc1c2a6e6d020"]]},{"id":"a135a8ed2c447561","type":"comment","z":"977143edb097b685","g":"520f961e35d10da4","name":"Visualizing data on charts","info":"","x":350,"y":920,"wires":[]},{"id":"1859e113313a5279","type":"ui-group","name":"chart","page":"f10b4d0259e43aeb","width":"13","height":"1","order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"f10b4d0259e43aeb","type":"ui-page","name":"home","ui":"cb79bc4520925e32","path":"/","icon":"","layout":"grid","theme":"2c5d702b11de7dd1","order":1,"className":"","visible":true,"disabled":"false"},{"id":"cb79bc4520925e32","type":"ui-base","name":"My UI","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false},{"id":"2c5d702b11de7dd1","type":"ui-theme","name":"Theme Name","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"}}] {% endrenderFlow %} From ed57625aa5dc2d5026f242f632eb94c9d03309af Mon Sep 17 00:00:00 2001 From: "sumit shinde ( Roni )" Date: Wed, 12 Jun 2024 12:47:18 +0530 Subject: [PATCH 05/13] update blog --- ...red-chart-customer-data-on-debug-panel.png | Bin 0 -> 31332 bytes .../2024/06/using-node-red-as-an-etl-tool.md | 93 ++++++++++-------- 2 files changed, 50 insertions(+), 43 deletions(-) create mode 100644 src/blog/2024/06/images/etl-with-node-red-chart-customer-data-on-debug-panel.png diff --git a/src/blog/2024/06/images/etl-with-node-red-chart-customer-data-on-debug-panel.png b/src/blog/2024/06/images/etl-with-node-red-chart-customer-data-on-debug-panel.png new file mode 100644 index 0000000000000000000000000000000000000000..15d2635a96d8968bb66c73f0c14199079e9b6ed8 GIT binary patch literal 31332 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 R2{uE+$x13oREQY`{vQYC8}0xA literal 0 HcmV?d00001 diff --git a/src/blog/2024/06/using-node-red-as-an-etl-tool.md b/src/blog/2024/06/using-node-red-as-an-etl-tool.md index 0ada8c022a..bf670a64ef 100644 --- a/src/blog/2024/06/using-node-red-as-an-etl-tool.md +++ b/src/blog/2024/06/using-node-red-as-an-etl-tool.md @@ -1,6 +1,6 @@ --- -title: Using Node-RED as an ETL Tool -subtitle: A Step-by-Step Guide on How to Use Node-RED as an ETL Tool +title: Using Node-RED as an ETL Tool. +subtitle: A Step-by-Step Guide on How to Use Node-RED as an ETL Tool. description: Learn how to utilize Node-RED as an ETL (Extract, Transform, Load) tool, and explore its advantages and disadvantages in this context. date: 2024-06-05 authors: ["sumit-shinde"] @@ -20,41 +20,49 @@ ETL is essential for data integration and analysis, playing a crucial role in ma ## What is ETL -[ETL](https://en.wikipedia.org/wiki/Extract,_transform,_load) (Extract, Transform, Load) is a fundamental process in data integration and data warehousing. It encompasses three main stages: extracting data from various sources, transforming it into a format suitable for analysis, and loading it into a target database or data warehouse. This process allows businesses to consolidate data from multiple sources, ensuring it is clean, consistent, and ready for generating insights and making informed decisions. +[ETL](https://en.wikipedia.org/wiki/Extract,_transform,_load) (Extract, Transform, Load) is a fundamental process in managing data efficiently. It consists of three main stages: extraction, transformation, and loading. In the extraction phase, data is gathered from various sources such as databases, APIs, or files. Then, in the transformation stage, the data is converted into a format that is suitable for analysis by cleaning, filtering, and structuring it. Finally, in the loading stage, the transformed data is stored in a target database or data warehouse for further analysis and decision-making. ETL plays a significant role in ensuring that data is organized, consistent, and readily available for generating insights and making informed decisions in businesses and organizations. -## Node-RED as ETL a tool +## Node-RED as an ETL tool -Node-RED is specifically used for building various types of IoT applications. During the development of such applications, Node-RED is sometimes used as an ETL (Extract, Transform, Load) tool without even realizing it. For instance, when monitoring sensors across a facility, the process involves extracting data from sensors, transforming (cleaning and formatting) sensor data, and loading it into a database. There are thousands of other examples like this. This demonstrates that Node-RED has already been adopted as an ETL tool for certain scenarios. +Node-RED is specifically used for building various types of IoT applications. During the development of such applications, Node-RED is sometimes used as an ETL tool without even realizing it. For instance, when monitoring sensors across a facility, the process involves extracting data from sensors, transforming (cleaning and formatting) sensor data, and loading it into a database. There are thousands of other such examples. This demonstrates that Node-RED has already been adopted as an ETL tool at certain level. + +*Note: We have mentioned only a few nodes that can be used in the ETL process, but there are thousands of other nodes that you can explore yourself by visiting the [Node-RED Nodes Library](https://flows.nodered.org/search?type=node)* ### Extracting -Node-RED can extract data from various sources, including APIs, databases, local filesystems, and IoT devices using built-in nodes and community-contributed nodes. For example, the HTTP request node can be used to pull data from web services, while nodes for MySQL, MongoDB, and PostgreSQL can extract data from databases. Nodes for MQTT and Kafka can fetch data from message brokers. Additionally, there are cloud nodes such as AWS, Google Cloud Platform (GCP), and IBM Watson that allow extraction of data from cloud storage services. +Node-RED can extract data from various sources, including APIs, databases, local filesystems, and IoT devices using built-in nodes and community-contributed nodes. For example, the HTTP request node can be used to pull data from web services, while nodes for MySQL, MongoDB, and PostgreSQL can extract data from databases. Nodes for MQTT and Kafka can fetch data from message brokers. Additionally, there are diffrent cloud nodes for cloud platform such as AWS, GCP, and IBM Watson that allow extraction of data from cloud storage services. ### Transforming -Transformation in Node-RED involves converting data into the desired format, applying business rules, and cleaning it. This can be done using function nodes for custom JavaScript code, along with nodes like JSON, split, join, change CSV, and XML for parsing and formatting. +Transforming data involves cleaning, structuring, and applying business rules. This can be done using function nodes with custom JavaScript, along with nodes like JSON, split, join, change, CSV, and XML for parsing and formatting. ### Loading -The final step in the ETL process is loading the transformed data into a target system, such as a database or data warehouse. Node-RED supports various output nodes to send data to different destinations. For instance, you can use the MySQL node to insert data into a MySQL database, or the HTTP request node to send data to a web service endpoint. +The final step in the ETL process is loading the transformed data into a target system, such as a database or data warehouse. Node-RED supports various output nodes to send data to different destinations. For instance, you can use the MySQL node to insert data into a MySQL database, or the HTTP request node to send data to a web service endpoint or cloud nodes to send data to cloud storage services. ### Visualizing and Analyzing -In addition to the core ETL (Extract, Transform, Load) process, visualizing and analyzing data is a crucial step for gaining insights. While visualization isn't part of the ETL acronym itself, it plays a significant role in understanding and interpreting transformed data. In Node-RED, you can easily visualize data using Node-RED Dashboard 2.0 charts. +In addition to the core ETL process, visualizing and analyzing data is a crucial step for gaining insights. While visualization isn't part of the ETL acronym itself, it plays a significant role in understanding and interpreting transformed data. In Node-RED, you can easily visualize data using Node-RED Dashboard 2.0 charts. Node-RED Dashboard 2.0 provides several chart options, and more are expected in the future. For more information and to explore available chart types, refer to the [Node-RED Dashboard 2.0 charts documentation](https://dashboard.flowfuse.com/nodes/widgets/ui-chart.html). -*Note: We have mentioned only a few nodes that can be used in the ETL process, but there are thousands of other nodes that you can explore yourself by visiting the [Node-RED Nodes Library](https://flows.nodered.org/search?type=node)* +## Benefits of using Node-RED as an ETL tool. + +1. **Ease of Use:** Its visual programming interface makes it accessible to non-developers. +2. **Flexibility:** A wide range of nodes and the ability to write custom JavaScript allow for flexible data processing. +3. **Integration:** Strong support for IoT and real-time data processing, making it ideal for integrating diverse data sources. +4. **Cost-Effective:** Being open-source, Node-RED can be a cost-effective alternative to expensive ETL tools. +5. **Community Support:** A large community provides a wealth of nodes, examples, and support. ## Building a Simple ETL Project Using Node-RED -Let's walk through a simple project where we use Node-RED as an ETL tool to extract sample customer data from an API, transform it, and then load cleaned data into a MongoDB database and process data into a local file. +Let's walk through a simple project where we will use Node-RED as an ETL tool to extract sample customer data from an API, transform it, and then load cleaned data into a MongoDB database and process data into a local file. *Note: The goal of this project is to understand how to utilize Node-RED as an ETL tool. We assume that the reader has a basic knowledge of Node-RED.* ## Prerequisite -Before proceeding further make sure you have installed the following nodes. +Before proceeding further make sure you have installed the following nodes: 1. [node-red-contrib-mongodb4](https://flows.nodered.org/node/node-red-contrib-mongodb4) 2. [@flowfuse/node-red-dashboard](https://dashboard.flowfuse.com/) @@ -63,29 +71,32 @@ Before proceeding further make sure you have installed the following nodes. 1. Drag an Inject node onto the canvas. 2. Drag an HTTP Request node onto the canvas, double-click on it, and set the URL to `https://api.slingacademy.com/v1/sample-data/files/customers.json`. -3. Drag a Link Out node onto the canvas. -4. Connect the Inject node's output to the input of the HTTP Request node, and the HTTP Request node's output to the input of the Link Out node. +3. Drag a Link-out node onto the canvas. +4. Connect the Inject node's output to the input of the HTTP Request node, and the HTTP Request node's output to the input of the Link-out node. Now, if you add a Debug node after the HTTP Request node, you will see an array of objects containing customer data in the Debug panel. Each object has properties such as `first_name`, `last_name`, `email`, and others. -Next, we'll perform a transformation to replace the existing properties `first_name` and `last_name` with a single property `full_name` that concatenates them. We'll cover this transformation in the next section. +!["Screenshot of debug panel displaying printed customer data"](./images/etl-with-node-red-chart-customer-data-on-debug-panel.png "Screenshot of debug panel displaying printed customer data"){data-zoomable} + +In next section, we'll perform a transformation to replace the existing properties `first_name` and `last_name` with a single property `full_name` that concatenates them. ## Transforming Data ### Data Cleaning -1. Drag a Link In node onto the canvas, double-click on it, and select the name of the Link Out node added in the above section. +1. Drag a Link-in node onto the canvas, double-click on it, and select the name of the Link-out node added in the above section. 2. Drag a Split node onto the canvas. -3. Drag a Change node onto the canvas and Set `msg.payload.full_name` to `payload.first_name & " " & payload.last_name` as the JSONata expression, then delete unnecessary properties like `first_name` and `last_name`. +3. Drag a Change node onto the canvas and Set `msg.payload.full_name` to `payload.first_name & " " & payload.last_name` as the JSONata expression, this JSONata expression will concat the firstname and lastname properties, then delete unnecessary properties like `first_name` and `last_name`. 4. Drag a Join node onto the canvas. +5. Connect the output of Link-in node to the input of Split node, then split node output to the input of join node. -until now we have created a flow that will create a new property in customer data objects called full_name and then it will delete the unnecessary properties. in summary, we have cleaned the data according to our needs. +Up to this point, we've established a flow that creates a new property in customer data objects called 'full_name' and subsequently removes any unnecessary properties. In summary, we've cleaned the data according to our needs. ### Customer Data Deduplication 1. Drag a Change node onto the canvas, and set `msg.data` to `msg.payload` and `msg.payload` to `[]`. 2. Drag a MongoDB4 node onto the canvas, and configure it with your correct details. If you haven't used MongoDB with Node-RED, please refer to the [Node-RED MongoDB documentation](https://flows.nodered.org/node/node-red-contrib-mongodb4). Enter `find` into the Operation field. -3. Drag a Function node onto the canvas and insert the following code into it: +3. Drag a Function node onto the canvas and insert the following code into it and give it name "Data deplication": ```javascript // Check if previously stored customer data is present, and ensure it's an array @@ -112,12 +123,13 @@ if (latest_customer_data.length !== 0 && previously_stored_customer_data.length ``` 4. Drag a Link-out node onto the canvas. +5. Connect the output of Join node to the input of change node and output of change node to the input of MongoDB4 node and then MongoDB4 output to the input of function node named "Data deplication" and output of that function node to the input of Link-out node. -Now, we have added some more nodes that perform data deduplication. This means we will create a new array containing unique data that is not already stored in the database to avoid data duplications. +Now, we have added additional nodes that perform data deduplication. This means we will create a new array containing unique data that is not already stored in the database to avoid data duplications. For filtering that data, we are using JavaScript with a function node. ## Data Processing -1. Drag a Function node onto the canvas and insert the following code into it: +1. Drag a Function node onto the canvas and insert the following code into it and name this node "Data processing": ```javascript let data = msg.payload; @@ -177,48 +189,43 @@ msg.payload = { return msg; ``` 2. Drag another Link-out node onto the canvas. +3. Connect the Join node's output to the input of function node named "Data processing", and output of that function node to the input of Link-out node. -Finally, in this phase of transformation, we are tallying the total number of users based on age, gender, and job title. This allows us to quickly analyze and understand our user demographics based on these details so that later we can visualize this data easily. +In this phase of transformation, we are tallying the total number of users based on age, gender, and job title. This allows us to quickly analyze and understand our user demographics based on these details so that later we can visualize this data easily. ## Loading data -1. Drag a Link-in node onto the canvas, double-click on it, and select the name of the Link-out node connected to the data deduplication function. Then, drag another Link-in node and connect it to the Link-out node connected to the data processing function node. - +1. Drag a Link-in node onto the canvas, double-click on it, and select the name of the Link-out node connected to the "Data deduplication" function. Then, drag another Link-in node and connect it to the Link-out node which is connected to the "Data processing" function node. 2. Drag a MongoDB4 node onto the canvas and configure it correctly. Select the correct collection and enter `insertMany` into the Operation field. - 3. Drag a File Write node onto the canvas, set the path, and select the action to "override". +4. Connect the first Link-in node's output to the input of MongoDB4 node and then second Link-in node's output to the input of File write node. -!["Screenshot of dashboard visualizing process customer data based on job profile"](./images/etl-with-node-red-chart-based-on-job-profile.png "Screenshot of dashboard visualizing process customer data based on job profile"){data-zoomable} - -!["Screenshot of dashboard visualizing process customer data based on age group"](./images/etl-with-node-red-chart-based-on-age.png "Screenshot of dashboard visualizing process customer data based on age group"){data-zoomable} +Now, finally, in this loading phase, we are storing the cleaned, formatted, and unique customer data into the database. The processed data, such as total users by age, gender, and job profiles, is stored in the local file +## Deploying the flow Following is the complete flow of the project along with dashboard visualization. {% renderFlow %} -[{"id":"e85cb581eb249115","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["218b698ddba2210b","638eddcd2b5f645e","9773152e6a0f2287","fd68d5c864a0e7c9"],"x":114,"y":159,"w":532,"h":182},{"id":"218b698ddba2210b","type":"http request","z":"977143edb097b685","g":"e85cb581eb249115","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.slingacademy.com/v1/sample-data/files/customers.json","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":430,"y":300,"wires":[["fd68d5c864a0e7c9"]]},{"id":"638eddcd2b5f645e","type":"inject","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extract Data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":300,"wires":[["218b698ddba2210b"]]},{"id":"9773152e6a0f2287","type":"comment","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extracting customer data from api","info":"","x":330,"y":200,"wires":[]},{"id":"fd68d5c864a0e7c9","type":"link out","z":"977143edb097b685","g":"e85cb581eb249115","name":"link out 1","mode":"link","links":["0e0129a95e24355c"],"x":605,"y":300,"wires":[]},{"id":"e0adf6e180ec1a7c","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["ace58c34d1566f51","d2a48c9825b224b4","9cd9d88bb507cc49","ef5e8501b76cfec8","d3a842120a526a7f","6f472c26ef54f974","a88a07f39e0e941d","0e0129a95e24355c","c7150b3b68fc34a0","3f3ad8e528f5800b","dd3fb62233d5477e"],"x":104,"y":379,"w":1342,"h":202},{"id":"ace58c34d1566f51","type":"split","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":250,"y":500,"wires":[["d2a48c9825b224b4"]]},{"id":"d2a48c9825b224b4","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","rules":[{"t":"set","p":"payload.full_name","pt":"msg","to":"payload.first_name & \" \" & payload.last_name","tot":"jsonata"},{"t":"delete","p":"payload.first_name","pt":"msg"},{"t":"delete","p":"payload.last_name","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":500,"wires":[["ef5e8501b76cfec8"]]},{"id":"9cd9d88bb507cc49","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"data processing","func":"let data = msg.payload\n\nlet ageRanges = {\n    \"0-20\": 0,\n    \"21-30\": 0,\n    \"31-40\": 0,\n    \"41+\": 0\n};\n\nlet genderTotals = {\n    male: 0,\n    female: 0,\n    other: 0  // Add other genders as needed\n};\n\nlet jobStatusTotals = {};\n\n// Iterate through each document to calculate counts\ndata.forEach(doc => {\n    // Calculate age range\n    let age = parseInt(doc.age);\n    let ageRange;\n    if (age <= 20) {\n        ageRange = \"0-20\";\n    } else if (age <= 30) {\n        ageRange = \"21-30\";\n    } else if (age <= 40) {\n        ageRange = \"31-40\";\n    } else {\n        ageRange = \"41+\";\n    }\n    // Increment age range count\n    ageRanges[ageRange]++;\n\n    // Increment gender count\n    if (doc.gender === 'male') {\n        genderTotals.male++;\n    } else if (doc.gender === 'female') {\n        genderTotals.female++;\n    } else {\n        genderTotals.other++;\n    }\n\n    // Increment job status count\n    if (jobStatusTotals[doc.job]) {\n        jobStatusTotals[doc.job]++;\n    } else {\n        jobStatusTotals[doc.job] = 1;\n    }\n});\n\n\nmsg.payload = {\n    \"ageRanges\": ageRanges,\n    \"genderTotals\": genderTotals,\n    \"jobStatusTotals\": jobStatusTotals\n}; \n\n// Return the aggregated counts object\nreturn msg","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":980,"y":540,"wires":[["3f3ad8e528f5800b"]]},{"id":"ef5e8501b76cfec8","type":"join","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":690,"y":500,"wires":[["9cd9d88bb507cc49","6f472c26ef54f974"]]},{"id":"d3a842120a526a7f","type":"comment","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Tranforming customer data","info":"","x":330,"y":420,"wires":[]},{"id":"6f472c26ef54f974","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","rules":[{"t":"set","p":"data","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":970,"y":420,"wires":[["a88a07f39e0e941d"]]},{"id":"a88a07f39e0e941d","type":"mongodb4","z":"977143edb097b685","g":"e0adf6e180ec1a7c","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"find","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":1130,"y":420,"wires":[["dd3fb62233d5477e"]]},{"id":"0e0129a95e24355c","type":"link in","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link in 1","links":["fd68d5c864a0e7c9"],"x":145,"y":500,"wires":[["ace58c34d1566f51"]]},{"id":"c7150b3b68fc34a0","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 2","mode":"link","links":["78176aee11393705"],"x":1405,"y":420,"wires":[]},{"id":"3f3ad8e528f5800b","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 3","mode":"link","links":["ecfa23782d33d813"],"x":1115,"y":540,"wires":[]},{"id":"dd3fb62233d5477e","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","func":"let previously_stored_customer_data = Array.isArray(msg.payload) ? msg.payload : (msg.payload ? [msg.payload] : []);\nlet latest_customer_data = Array.isArray(msg.data) ? Array.from(msg.data) : (msg.data ? [msg.data] : []);\n\nif (latest_customer_data.length !== 0 && previously_stored_customer_data.length !== 0) {\n    let fullNameArray1 = previously_stored_customer_data.map(customer => customer.full_name);\n    let filtered_customer_data = latest_customer_data.filter(customer => !fullNameArray1.includes(customer.full_name));\n    msg.payload = [filtered_customer_data];\n    return msg\n} else {\n    // Case where there's no previously stored data\n    msg.payload = [latest_customer_data];\n    return msg\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1290,"y":420,"wires":[["c7150b3b68fc34a0"]]},{"id":"a0c7c3410ffb0e89","type":"mongodb4-client","name":"","protocol":"mongodb+srv","hostname":"","port":"","dbName":"mydb","appName":"","authSource":"","authMechanism":"DEFAULT","tls":false,"tlsCAFile":"","tlsCertificateKeyFile":"","tlsInsecure":false,"connectTimeoutMS":"30000","socketTimeoutMS":"0","minPoolSize":"0","maxPoolSize":"100","maxIdleTimeMS":"0","uri":"mongodb+srv://cluster0.uxibwot.mongodb.net","advanced":"{}","uriTabActive":"tab-uri-advanced"},{"id":"ac5e2cabb6251314","type":"group","z":"977143edb097b685","name":"","style":{"label":true},"nodes":["d6a4a19c23a0f42b","78176aee11393705","ecfa23782d33d813","dab90d6302b1c885","bc4afbc715e3b64d","d781431fed20d650","f19a1157e25b47df"],"x":114,"y":619,"w":592,"h":222},{"id":"d6a4a19c23a0f42b","type":"mongodb4","z":"977143edb097b685","g":"ac5e2cabb6251314","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"insertMany","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":370,"y":720,"wires":[["bc4afbc715e3b64d"]]},{"id":"78176aee11393705","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 2","links":["c7150b3b68fc34a0"],"x":155,"y":720,"wires":[["d6a4a19c23a0f42b"]]},{"id":"ecfa23782d33d813","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 3","links":["3f3ad8e528f5800b"],"x":155,"y":800,"wires":[["dab90d6302b1c885"]]},{"id":"dab90d6302b1c885","type":"file","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"","filename":"./customer_data_analytics","filenameType":"str","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":390,"y":800,"wires":[["d781431fed20d650"]]},{"id":"bc4afbc715e3b64d","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":720,"wires":[]},{"id":"d781431fed20d650","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":600,"y":800,"wires":[]},{"id":"f19a1157e25b47df","type":"comment","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Loading data into file and database","info":"","x":380,"y":660,"wires":[]},{"id":"520f961e35d10da4","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["9b534cdc46dfc52a","52c6d1c11c84571c","ed6fc24b155aef33","af4bc1c2a6e6d020","572c04ca900af9d5","b64ddca6aab82cb2","a135a8ed2c447561"],"x":114,"y":879,"w":1372,"h":142},{"id":"9b534cdc46dfc52a","type":"ui-chart","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"chart","order":2,"chartType":"bar","category":"category","categoryType":"property","xAxisProperty":"","xAxisPropertyType":"msg","xAxisType":"category","yAxisProperty":"value","ymin":"","ymax":"","action":"replace","pointShape":"circle","pointRadius":4,"showLegend":false,"removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"width":"13","height":8,"className":"","x":1410,"y":980,"wires":[[]]},{"id":"52c6d1c11c84571c","type":"function","z":"977143edb097b685","g":"520f961e35d10da4","name":"function 1","func":"let selectedDataForChart = global.get(\"selectedDataForChart\")\n// Assuming msg.payload is an object\nlet data = msg.payload[selectedDataForChart]\nlet result = [];\n\n// Loop through each key in the payload object\nObject.keys(data).forEach(key => {\n    result.push({ category: key, value: data[key] });\n});\n\nmsg.payload = result\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1240,"y":980,"wires":[["9b534cdc46dfc52a"]]},{"id":"ed6fc24b155aef33","type":"ui-dropdown","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"Select Option:","tooltip":"","order":1,"width":0,"height":0,"passthru":false,"multiple":false,"options":[{"label":"Based on age group","value":"ageRanges","type":"str"},{"label":"Based on gender group","value":"genderTotals","type":"str"},{"label":"Based on job profile","value":"jobStatusTotals","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":220,"y":980,"wires":[["b64ddca6aab82cb2"]]},{"id":"af4bc1c2a6e6d020","type":"file in","z":"977143edb097b685","g":"520f961e35d10da4","name":"","filename":"./customer_data_analytics","filenameType":"str","format":"lines","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":810,"y":980,"wires":[["572c04ca900af9d5"]]},{"id":"572c04ca900af9d5","type":"json","z":"977143edb097b685","g":"520f961e35d10da4","name":"","property":"payload","action":"","pretty":false,"x":1050,"y":980,"wires":[["52c6d1c11c84571c"]]},{"id":"b64ddca6aab82cb2","type":"change","z":"977143edb097b685","g":"520f961e35d10da4","name":"store selected data in global context","rules":[{"t":"set","p":"selectedDataForChart","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":980,"wires":[["af4bc1c2a6e6d020"]]},{"id":"a135a8ed2c447561","type":"comment","z":"977143edb097b685","g":"520f961e35d10da4","name":"Visualizing data on charts","info":"","x":350,"y":920,"wires":[]},{"id":"1859e113313a5279","type":"ui-group","name":"chart","page":"f10b4d0259e43aeb","width":"13","height":"1","order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"f10b4d0259e43aeb","type":"ui-page","name":"home","ui":"cb79bc4520925e32","path":"/","icon":"","layout":"grid","theme":"2c5d702b11de7dd1","order":1,"className":"","visible":true,"disabled":"false"},{"id":"cb79bc4520925e32","type":"ui-base","name":"My UI","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false},{"id":"2c5d702b11de7dd1","type":"ui-theme","name":"Theme Name","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"}}] +[{"id":"e85cb581eb249115","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["218b698ddba2210b","638eddcd2b5f645e","9773152e6a0f2287","fd68d5c864a0e7c9"],"x":114,"y":159,"w":532,"h":182},{"id":"218b698ddba2210b","type":"http request","z":"977143edb097b685","g":"e85cb581eb249115","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.slingacademy.com/v1/sample-data/files/customers.json","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":430,"y":300,"wires":[["fd68d5c864a0e7c9"]]},{"id":"638eddcd2b5f645e","type":"inject","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extract Data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":300,"wires":[["218b698ddba2210b"]]},{"id":"9773152e6a0f2287","type":"comment","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extracting customer data from api","info":"","x":330,"y":200,"wires":[]},{"id":"fd68d5c864a0e7c9","type":"Link-out","z":"977143edb097b685","g":"e85cb581eb249115","name":"Link-out 1","mode":"link","links":["0e0129a95e24355c"],"x":605,"y":300,"wires":[]},{"id":"e0adf6e180ec1a7c","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["ace58c34d1566f51","d2a48c9825b224b4","9cd9d88bb507cc49","ef5e8501b76cfec8","d3a842120a526a7f","6f472c26ef54f974","a88a07f39e0e941d","0e0129a95e24355c","c7150b3b68fc34a0","3f3ad8e528f5800b","dd3fb62233d5477e"],"x":104,"y":379,"w":1342,"h":202},{"id":"ace58c34d1566f51","type":"split","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":250,"y":500,"wires":[["d2a48c9825b224b4"]]},{"id":"d2a48c9825b224b4","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","rules":[{"t":"set","p":"payload.full_name","pt":"msg","to":"payload.first_name & \" \" & payload.last_name","tot":"jsonata"},{"t":"delete","p":"payload.first_name","pt":"msg"},{"t":"delete","p":"payload.last_name","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":500,"wires":[["ef5e8501b76cfec8"]]},{"id":"9cd9d88bb507cc49","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"data processing","func":"let data = msg.payload\n\nlet ageRanges = {\n    \"0-20\": 0,\n    \"21-30\": 0,\n    \"31-40\": 0,\n    \"41+\": 0\n};\n\nlet genderTotals = {\n    male: 0,\n    female: 0,\n    other: 0  // Add other genders as needed\n};\n\nlet jobStatusTotals = {};\n\n// Iterate through each document to calculate counts\ndata.forEach(doc => {\n    // Calculate age range\n    let age = parseInt(doc.age);\n    let ageRange;\n    if (age <= 20) {\n        ageRange = \"0-20\";\n    } else if (age <= 30) {\n        ageRange = \"21-30\";\n    } else if (age <= 40) {\n        ageRange = \"31-40\";\n    } else {\n        ageRange = \"41+\";\n    }\n    // Increment age range count\n    ageRanges[ageRange]++;\n\n    // Increment gender count\n    if (doc.gender === 'male') {\n        genderTotals.male++;\n    } else if (doc.gender === 'female') {\n        genderTotals.female++;\n    } else {\n        genderTotals.other++;\n    }\n\n    // Increment job status count\n    if (jobStatusTotals[doc.job]) {\n        jobStatusTotals[doc.job]++;\n    } else {\n        jobStatusTotals[doc.job] = 1;\n    }\n});\n\n\nmsg.payload = {\n    \"ageRanges\": ageRanges,\n    \"genderTotals\": genderTotals,\n    \"jobStatusTotals\": jobStatusTotals\n}; \n\n// Return the aggregated counts object\nreturn msg","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":980,"y":540,"wires":[["3f3ad8e528f5800b"]]},{"id":"ef5e8501b76cfec8","type":"join","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":690,"y":500,"wires":[["9cd9d88bb507cc49","6f472c26ef54f974"]]},{"id":"d3a842120a526a7f","type":"comment","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Tranforming customer data","info":"","x":330,"y":420,"wires":[]},{"id":"6f472c26ef54f974","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","rules":[{"t":"set","p":"data","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":970,"y":420,"wires":[["a88a07f39e0e941d"]]},{"id":"a88a07f39e0e941d","type":"mongodb4","z":"977143edb097b685","g":"e0adf6e180ec1a7c","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"find","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":1130,"y":420,"wires":[["dd3fb62233d5477e"]]},{"id":"0e0129a95e24355c","type":"Link-in","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Link-in 1","links":["fd68d5c864a0e7c9"],"x":145,"y":500,"wires":[["ace58c34d1566f51"]]},{"id":"c7150b3b68fc34a0","type":"Link-out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Link-out 2","mode":"link","links":["78176aee11393705"],"x":1405,"y":420,"wires":[]},{"id":"3f3ad8e528f5800b","type":"Link-out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Link-out 3","mode":"link","links":["ecfa23782d33d813"],"x":1115,"y":540,"wires":[]},{"id":"dd3fb62233d5477e","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","func":"let previously_stored_customer_data = Array.isArray(msg.payload) ? msg.payload : (msg.payload ? [msg.payload] : []);\nlet latest_customer_data = Array.isArray(msg.data) ? Array.from(msg.data) : (msg.data ? [msg.data] : []);\n\nif (latest_customer_data.length !== 0 && previously_stored_customer_data.length !== 0) {\n    let fullNameArray1 = previously_stored_customer_data.map(customer => customer.full_name);\n    let filtered_customer_data = latest_customer_data.filter(customer => !fullNameArray1.includes(customer.full_name));\n    msg.payload = [filtered_customer_data];\n    return msg\n} else {\n    // Case where there's no previously stored data\n    msg.payload = [latest_customer_data];\n    return msg\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1290,"y":420,"wires":[["c7150b3b68fc34a0"]]},{"id":"a0c7c3410ffb0e89","type":"mongodb4-client","name":"","protocol":"mongodb+srv","hostname":"","port":"","dbName":"mydb","appName":"","authSource":"","authMechanism":"DEFAULT","tls":false,"tlsCAFile":"","tlsCertificateKeyFile":"","tlsInsecure":false,"connectTimeoutMS":"30000","socketTimeoutMS":"0","minPoolSize":"0","maxPoolSize":"100","maxIdleTimeMS":"0","uri":"mongodb+srv://cluster0.uxibwot.mongodb.net","advanced":"{}","uriTabActive":"tab-uri-advanced"},{"id":"ac5e2cabb6251314","type":"group","z":"977143edb097b685","name":"","style":{"label":true},"nodes":["d6a4a19c23a0f42b","78176aee11393705","ecfa23782d33d813","dab90d6302b1c885","bc4afbc715e3b64d","d781431fed20d650","f19a1157e25b47df"],"x":114,"y":619,"w":592,"h":222},{"id":"d6a4a19c23a0f42b","type":"mongodb4","z":"977143edb097b685","g":"ac5e2cabb6251314","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"insertMany","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":370,"y":720,"wires":[["bc4afbc715e3b64d"]]},{"id":"78176aee11393705","type":"Link-in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Link-in 2","links":["c7150b3b68fc34a0"],"x":155,"y":720,"wires":[["d6a4a19c23a0f42b"]]},{"id":"ecfa23782d33d813","type":"Link-in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Link-in 3","links":["3f3ad8e528f5800b"],"x":155,"y":800,"wires":[["dab90d6302b1c885"]]},{"id":"dab90d6302b1c885","type":"file","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"","filename":"./customer_data_analytics","filenameType":"str","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":390,"y":800,"wires":[["d781431fed20d650"]]},{"id":"bc4afbc715e3b64d","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":720,"wires":[]},{"id":"d781431fed20d650","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":600,"y":800,"wires":[]},{"id":"f19a1157e25b47df","type":"comment","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Loading data into file and database","info":"","x":380,"y":660,"wires":[]},{"id":"520f961e35d10da4","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["9b534cdc46dfc52a","52c6d1c11c84571c","ed6fc24b155aef33","af4bc1c2a6e6d020","572c04ca900af9d5","b64ddca6aab82cb2","a135a8ed2c447561"],"x":114,"y":879,"w":1372,"h":142},{"id":"9b534cdc46dfc52a","type":"ui-chart","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"chart","order":2,"chartType":"bar","category":"category","categoryType":"property","xAxisProperty":"","xAxisPropertyType":"msg","xAxisType":"category","yAxisProperty":"value","ymin":"","ymax":"","action":"replace","pointShape":"circle","pointRadius":4,"showLegend":false,"removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"width":"13","height":8,"className":"","x":1410,"y":980,"wires":[[]]},{"id":"52c6d1c11c84571c","type":"function","z":"977143edb097b685","g":"520f961e35d10da4","name":"function 1","func":"let selectedDataForChart = global.get(\"selectedDataForChart\")\n// Assuming msg.payload is an object\nlet data = msg.payload[selectedDataForChart]\nlet result = [];\n\n// Loop through each key in the payload object\nObject.keys(data).forEach(key => {\n    result.push({ category: key, value: data[key] });\n});\n\nmsg.payload = result\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1240,"y":980,"wires":[["9b534cdc46dfc52a"]]},{"id":"ed6fc24b155aef33","type":"ui-dropdown","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"Select Option:","tooltip":"","order":1,"width":0,"height":0,"passthru":false,"multiple":false,"options":[{"label":"Based on age group","value":"ageRanges","type":"str"},{"label":"Based on gender group","value":"genderTotals","type":"str"},{"label":"Based on job profile","value":"jobStatusTotals","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":220,"y":980,"wires":[["b64ddca6aab82cb2"]]},{"id":"af4bc1c2a6e6d020","type":"file in","z":"977143edb097b685","g":"520f961e35d10da4","name":"","filename":"./customer_data_analytics","filenameType":"str","format":"lines","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":810,"y":980,"wires":[["572c04ca900af9d5"]]},{"id":"572c04ca900af9d5","type":"json","z":"977143edb097b685","g":"520f961e35d10da4","name":"","property":"payload","action":"","pretty":false,"x":1050,"y":980,"wires":[["52c6d1c11c84571c"]]},{"id":"b64ddca6aab82cb2","type":"change","z":"977143edb097b685","g":"520f961e35d10da4","name":"store selected data in global context","rules":[{"t":"set","p":"selectedDataForChart","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":980,"wires":[["af4bc1c2a6e6d020"]]},{"id":"a135a8ed2c447561","type":"comment","z":"977143edb097b685","g":"520f961e35d10da4","name":"Visualizing data on charts","info":"","x":350,"y":920,"wires":[]},{"id":"1859e113313a5279","type":"ui-group","name":"chart","page":"f10b4d0259e43aeb","width":"13","height":"1","order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"f10b4d0259e43aeb","type":"ui-page","name":"home","ui":"cb79bc4520925e32","path":"/","icon":"","layout":"grid","theme":"2c5d702b11de7dd1","order":1,"className":"","visible":true,"disabled":"false"},{"id":"cb79bc4520925e32","type":"ui-base","name":"My UI","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false},{"id":"2c5d702b11de7dd1","type":"ui-theme","name":"Theme Name","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"}}] {% endrenderFlow %} -## What are the limitations of using ETL as an ETL tool +1. To Deploy the flow, click on the top-right Deploy button +2. To visit the dashboard, Go to Dashboard 2.0 sidebar and click on the top-right "Open dashboard" button. -While Node-RED is versatile, there are some limitations to consider: +!["Screenshot of dashboard visualizing process customer data based on job profile"](./images/etl-with-node-red-chart-based-on-job-profile.png "Screenshot of dashboard visualizing process customer data based on job profile"){data-zoomable} -- **Scalability:** Node-RED might struggle with extremely large datasets compared to dedicated ETL tools. -- **Performance:** For very complex transformations or high-volume data, performance might not match that of specialized ETL solutions. -- **Advanced Features:** Some advanced ETL features, like automated schema detection and sophisticated error handling, might require additional customization or external modules. -- **Data Governance:** Node-RED does not inherently provide robust data governance and lineage tracking which are often essential in enterprise ETL tools. +!["Screenshot of dashboard visualizing process customer data based on age group"](./images/etl-with-node-red-chart-based-on-age.png "Screenshot of dashboard visualizing process customer data based on age group"){data-zoomable} -## Benefits of using Node-RED as an ETL tool. +## What are the limitations of using Node-RED as an ETL tool -Despite its limitations, Node-RED offers several benefits: +While Node-RED is versatile, there are some limitations to consider while using it as ETL tool: -1. **Ease of Use:** Its visual programming interface makes it accessible to non-developers. -2. **Flexibility:** A wide range of nodes and the ability to write custom JavaScript allow for flexible data processing. -3. **Integration:** Strong support for IoT and real-time data processing, making it ideal for integrating diverse data sources. -4. **Cost-Effective:** Being open-source, Node-RED can be a cost-effective alternative to expensive ETL tools. -5. **Community Support:** A large community provides a wealth of nodes, examples, and support. +- **Scalability:** Node-RED might struggle with extremely large datasets compared to dedicated ETL tools. +- **Advanced Features:** Some advanced ETL features, like automated schema detection and sophisticated error handling, might require additional customization or external modules. +- **Data Governance:** Node-RED does not inherently provide robust data governance and lineage tracking which are often essential in enterprise ETL tools. ## Additional resources - [Implementing ETL flows with Node-RED](https://developer.ibm.com/articles/implementing-etl-flows-with-node-red/): Read this IBM blog where a team member explains how they replaced a dedicated ETL tool with Node-RED. -- [Node-RED Forum Thread](https://discourse.nodered.org/t/etl-pipelines-with-node-red/): Explore this Node-RED forum thread where community members discussed how to utilize Node-RED as an ETL tool, including solutions for handling large datasets. +- [Node-RED Forum Thread](https://discourse.nodered.org/t/etl-pipelines-with-node-red/): Explore this Node-RED forum thread where community members discussed how to utilize Node-RED as an ETL tool, including solutions for handling large datasets. \ No newline at end of file From cec219a48f4d4a93ce68c4d0490901948fc07f97 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 07:19:46 +0000 Subject: [PATCH 06/13] Optimised images with calibre/image-actions --- ...red-chart-customer-data-on-debug-panel.png | Bin 31332 -> 16162 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/blog/2024/06/images/etl-with-node-red-chart-customer-data-on-debug-panel.png b/src/blog/2024/06/images/etl-with-node-red-chart-customer-data-on-debug-panel.png index 15d2635a96d8968bb66c73f0c14199079e9b6ed8..558fa8b28bb380d7cd76d25ee3bfb4a2eb7ca965 100644 GIT binary patch literal 16162 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 literal 31332 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 R2{uE+$x13oREQY`{vQYC8}0xA From 11abae9c71bf68a8ca40db8a0bce03eea174c1eb Mon Sep 17 00:00:00 2001 From: "sumit shinde ( Roni )" <110285294+sumitshinde-84@users.noreply.github.com> Date: Thu, 13 Jun 2024 00:34:37 +0530 Subject: [PATCH 07/13] Update using-node-red-as-an-etl-tool.md --- src/blog/2024/06/using-node-red-as-an-etl-tool.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/blog/2024/06/using-node-red-as-an-etl-tool.md b/src/blog/2024/06/using-node-red-as-an-etl-tool.md index bf670a64ef..358116b6e3 100644 --- a/src/blog/2024/06/using-node-red-as-an-etl-tool.md +++ b/src/blog/2024/06/using-node-red-as-an-etl-tool.md @@ -95,7 +95,7 @@ Up to this point, we've established a flow that creates a new property in custom ### Customer Data Deduplication 1. Drag a Change node onto the canvas, and set `msg.data` to `msg.payload` and `msg.payload` to `[]`. -2. Drag a MongoDB4 node onto the canvas, and configure it with your correct details. If you haven't used MongoDB with Node-RED, please refer to the [Node-RED MongoDB documentation](https://flows.nodered.org/node/node-red-contrib-mongodb4). Enter `find` into the Operation field. +2. Drag a MongoDB4 node onto the canvas, and configure it with your correct details. If you haven't used MongoDB with Node-RED, please refer to the [Using MongoDB with Node-RED](/blog/2024/04/using-mongodb-with-node-red/). Enter `find` into the Operation field. 3. Drag a Function node onto the canvas and insert the following code into it and give it name "Data deplication": ```javascript @@ -207,7 +207,7 @@ Now, finally, in this loading phase, we are storing the cleaned, formatted, and Following is the complete flow of the project along with dashboard visualization. {% renderFlow %} -[{"id":"e85cb581eb249115","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["218b698ddba2210b","638eddcd2b5f645e","9773152e6a0f2287","fd68d5c864a0e7c9"],"x":114,"y":159,"w":532,"h":182},{"id":"218b698ddba2210b","type":"http request","z":"977143edb097b685","g":"e85cb581eb249115","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.slingacademy.com/v1/sample-data/files/customers.json","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":430,"y":300,"wires":[["fd68d5c864a0e7c9"]]},{"id":"638eddcd2b5f645e","type":"inject","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extract Data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":300,"wires":[["218b698ddba2210b"]]},{"id":"9773152e6a0f2287","type":"comment","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extracting customer data from api","info":"","x":330,"y":200,"wires":[]},{"id":"fd68d5c864a0e7c9","type":"Link-out","z":"977143edb097b685","g":"e85cb581eb249115","name":"Link-out 1","mode":"link","links":["0e0129a95e24355c"],"x":605,"y":300,"wires":[]},{"id":"e0adf6e180ec1a7c","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["ace58c34d1566f51","d2a48c9825b224b4","9cd9d88bb507cc49","ef5e8501b76cfec8","d3a842120a526a7f","6f472c26ef54f974","a88a07f39e0e941d","0e0129a95e24355c","c7150b3b68fc34a0","3f3ad8e528f5800b","dd3fb62233d5477e"],"x":104,"y":379,"w":1342,"h":202},{"id":"ace58c34d1566f51","type":"split","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":250,"y":500,"wires":[["d2a48c9825b224b4"]]},{"id":"d2a48c9825b224b4","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","rules":[{"t":"set","p":"payload.full_name","pt":"msg","to":"payload.first_name & \" \" & payload.last_name","tot":"jsonata"},{"t":"delete","p":"payload.first_name","pt":"msg"},{"t":"delete","p":"payload.last_name","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":500,"wires":[["ef5e8501b76cfec8"]]},{"id":"9cd9d88bb507cc49","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"data processing","func":"let data = msg.payload\n\nlet ageRanges = {\n    \"0-20\": 0,\n    \"21-30\": 0,\n    \"31-40\": 0,\n    \"41+\": 0\n};\n\nlet genderTotals = {\n    male: 0,\n    female: 0,\n    other: 0  // Add other genders as needed\n};\n\nlet jobStatusTotals = {};\n\n// Iterate through each document to calculate counts\ndata.forEach(doc => {\n    // Calculate age range\n    let age = parseInt(doc.age);\n    let ageRange;\n    if (age <= 20) {\n        ageRange = \"0-20\";\n    } else if (age <= 30) {\n        ageRange = \"21-30\";\n    } else if (age <= 40) {\n        ageRange = \"31-40\";\n    } else {\n        ageRange = \"41+\";\n    }\n    // Increment age range count\n    ageRanges[ageRange]++;\n\n    // Increment gender count\n    if (doc.gender === 'male') {\n        genderTotals.male++;\n    } else if (doc.gender === 'female') {\n        genderTotals.female++;\n    } else {\n        genderTotals.other++;\n    }\n\n    // Increment job status count\n    if (jobStatusTotals[doc.job]) {\n        jobStatusTotals[doc.job]++;\n    } else {\n        jobStatusTotals[doc.job] = 1;\n    }\n});\n\n\nmsg.payload = {\n    \"ageRanges\": ageRanges,\n    \"genderTotals\": genderTotals,\n    \"jobStatusTotals\": jobStatusTotals\n}; \n\n// Return the aggregated counts object\nreturn msg","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":980,"y":540,"wires":[["3f3ad8e528f5800b"]]},{"id":"ef5e8501b76cfec8","type":"join","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":690,"y":500,"wires":[["9cd9d88bb507cc49","6f472c26ef54f974"]]},{"id":"d3a842120a526a7f","type":"comment","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Tranforming customer data","info":"","x":330,"y":420,"wires":[]},{"id":"6f472c26ef54f974","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","rules":[{"t":"set","p":"data","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":970,"y":420,"wires":[["a88a07f39e0e941d"]]},{"id":"a88a07f39e0e941d","type":"mongodb4","z":"977143edb097b685","g":"e0adf6e180ec1a7c","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"find","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":1130,"y":420,"wires":[["dd3fb62233d5477e"]]},{"id":"0e0129a95e24355c","type":"Link-in","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Link-in 1","links":["fd68d5c864a0e7c9"],"x":145,"y":500,"wires":[["ace58c34d1566f51"]]},{"id":"c7150b3b68fc34a0","type":"Link-out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Link-out 2","mode":"link","links":["78176aee11393705"],"x":1405,"y":420,"wires":[]},{"id":"3f3ad8e528f5800b","type":"Link-out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Link-out 3","mode":"link","links":["ecfa23782d33d813"],"x":1115,"y":540,"wires":[]},{"id":"dd3fb62233d5477e","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","func":"let previously_stored_customer_data = Array.isArray(msg.payload) ? msg.payload : (msg.payload ? [msg.payload] : []);\nlet latest_customer_data = Array.isArray(msg.data) ? Array.from(msg.data) : (msg.data ? [msg.data] : []);\n\nif (latest_customer_data.length !== 0 && previously_stored_customer_data.length !== 0) {\n    let fullNameArray1 = previously_stored_customer_data.map(customer => customer.full_name);\n    let filtered_customer_data = latest_customer_data.filter(customer => !fullNameArray1.includes(customer.full_name));\n    msg.payload = [filtered_customer_data];\n    return msg\n} else {\n    // Case where there's no previously stored data\n    msg.payload = [latest_customer_data];\n    return msg\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1290,"y":420,"wires":[["c7150b3b68fc34a0"]]},{"id":"a0c7c3410ffb0e89","type":"mongodb4-client","name":"","protocol":"mongodb+srv","hostname":"","port":"","dbName":"mydb","appName":"","authSource":"","authMechanism":"DEFAULT","tls":false,"tlsCAFile":"","tlsCertificateKeyFile":"","tlsInsecure":false,"connectTimeoutMS":"30000","socketTimeoutMS":"0","minPoolSize":"0","maxPoolSize":"100","maxIdleTimeMS":"0","uri":"mongodb+srv://cluster0.uxibwot.mongodb.net","advanced":"{}","uriTabActive":"tab-uri-advanced"},{"id":"ac5e2cabb6251314","type":"group","z":"977143edb097b685","name":"","style":{"label":true},"nodes":["d6a4a19c23a0f42b","78176aee11393705","ecfa23782d33d813","dab90d6302b1c885","bc4afbc715e3b64d","d781431fed20d650","f19a1157e25b47df"],"x":114,"y":619,"w":592,"h":222},{"id":"d6a4a19c23a0f42b","type":"mongodb4","z":"977143edb097b685","g":"ac5e2cabb6251314","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"insertMany","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":370,"y":720,"wires":[["bc4afbc715e3b64d"]]},{"id":"78176aee11393705","type":"Link-in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Link-in 2","links":["c7150b3b68fc34a0"],"x":155,"y":720,"wires":[["d6a4a19c23a0f42b"]]},{"id":"ecfa23782d33d813","type":"Link-in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Link-in 3","links":["3f3ad8e528f5800b"],"x":155,"y":800,"wires":[["dab90d6302b1c885"]]},{"id":"dab90d6302b1c885","type":"file","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"","filename":"./customer_data_analytics","filenameType":"str","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":390,"y":800,"wires":[["d781431fed20d650"]]},{"id":"bc4afbc715e3b64d","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":720,"wires":[]},{"id":"d781431fed20d650","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":600,"y":800,"wires":[]},{"id":"f19a1157e25b47df","type":"comment","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Loading data into file and database","info":"","x":380,"y":660,"wires":[]},{"id":"520f961e35d10da4","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["9b534cdc46dfc52a","52c6d1c11c84571c","ed6fc24b155aef33","af4bc1c2a6e6d020","572c04ca900af9d5","b64ddca6aab82cb2","a135a8ed2c447561"],"x":114,"y":879,"w":1372,"h":142},{"id":"9b534cdc46dfc52a","type":"ui-chart","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"chart","order":2,"chartType":"bar","category":"category","categoryType":"property","xAxisProperty":"","xAxisPropertyType":"msg","xAxisType":"category","yAxisProperty":"value","ymin":"","ymax":"","action":"replace","pointShape":"circle","pointRadius":4,"showLegend":false,"removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"width":"13","height":8,"className":"","x":1410,"y":980,"wires":[[]]},{"id":"52c6d1c11c84571c","type":"function","z":"977143edb097b685","g":"520f961e35d10da4","name":"function 1","func":"let selectedDataForChart = global.get(\"selectedDataForChart\")\n// Assuming msg.payload is an object\nlet data = msg.payload[selectedDataForChart]\nlet result = [];\n\n// Loop through each key in the payload object\nObject.keys(data).forEach(key => {\n    result.push({ category: key, value: data[key] });\n});\n\nmsg.payload = result\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1240,"y":980,"wires":[["9b534cdc46dfc52a"]]},{"id":"ed6fc24b155aef33","type":"ui-dropdown","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"Select Option:","tooltip":"","order":1,"width":0,"height":0,"passthru":false,"multiple":false,"options":[{"label":"Based on age group","value":"ageRanges","type":"str"},{"label":"Based on gender group","value":"genderTotals","type":"str"},{"label":"Based on job profile","value":"jobStatusTotals","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":220,"y":980,"wires":[["b64ddca6aab82cb2"]]},{"id":"af4bc1c2a6e6d020","type":"file in","z":"977143edb097b685","g":"520f961e35d10da4","name":"","filename":"./customer_data_analytics","filenameType":"str","format":"lines","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":810,"y":980,"wires":[["572c04ca900af9d5"]]},{"id":"572c04ca900af9d5","type":"json","z":"977143edb097b685","g":"520f961e35d10da4","name":"","property":"payload","action":"","pretty":false,"x":1050,"y":980,"wires":[["52c6d1c11c84571c"]]},{"id":"b64ddca6aab82cb2","type":"change","z":"977143edb097b685","g":"520f961e35d10da4","name":"store selected data in global context","rules":[{"t":"set","p":"selectedDataForChart","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":980,"wires":[["af4bc1c2a6e6d020"]]},{"id":"a135a8ed2c447561","type":"comment","z":"977143edb097b685","g":"520f961e35d10da4","name":"Visualizing data on charts","info":"","x":350,"y":920,"wires":[]},{"id":"1859e113313a5279","type":"ui-group","name":"chart","page":"f10b4d0259e43aeb","width":"13","height":"1","order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"f10b4d0259e43aeb","type":"ui-page","name":"home","ui":"cb79bc4520925e32","path":"/","icon":"","layout":"grid","theme":"2c5d702b11de7dd1","order":1,"className":"","visible":true,"disabled":"false"},{"id":"cb79bc4520925e32","type":"ui-base","name":"My UI","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false},{"id":"2c5d702b11de7dd1","type":"ui-theme","name":"Theme Name","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"}}] +[{"id":"e85cb581eb249115","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["218b698ddba2210b","638eddcd2b5f645e","9773152e6a0f2287","fd68d5c864a0e7c9"],"x":114,"y":159,"w":532,"h":182},{"id":"218b698ddba2210b","type":"http request","z":"977143edb097b685","g":"e85cb581eb249115","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.slingacademy.com/v1/sample-data/files/customers.json","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":430,"y":300,"wires":[["fd68d5c864a0e7c9"]]},{"id":"638eddcd2b5f645e","type":"inject","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extract Data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":300,"wires":[["218b698ddba2210b"]]},{"id":"9773152e6a0f2287","type":"comment","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extracting customer data from api","info":"","x":330,"y":200,"wires":[]},{"id":"fd68d5c864a0e7c9","type":"link out","z":"977143edb097b685","g":"e85cb581eb249115","name":"link out 1","mode":"link","links":["0e0129a95e24355c"],"x":605,"y":300,"wires":[]},{"id":"e0adf6e180ec1a7c","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["ace58c34d1566f51","d2a48c9825b224b4","9cd9d88bb507cc49","ef5e8501b76cfec8","d3a842120a526a7f","6f472c26ef54f974","a88a07f39e0e941d","0e0129a95e24355c","c7150b3b68fc34a0","3f3ad8e528f5800b","dd3fb62233d5477e"],"x":104,"y":379,"w":1342,"h":202},{"id":"ace58c34d1566f51","type":"split","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":250,"y":500,"wires":[["d2a48c9825b224b4"]]},{"id":"d2a48c9825b224b4","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","rules":[{"t":"set","p":"payload.full_name","pt":"msg","to":"payload.first_name & \" \" & payload.last_name","tot":"jsonata"},{"t":"delete","p":"payload.first_name","pt":"msg"},{"t":"delete","p":"payload.last_name","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":500,"wires":[["ef5e8501b76cfec8"]]},{"id":"9cd9d88bb507cc49","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"data processing","func":"let data = msg.payload\n\nlet ageRanges = {\n \"0-20\": 0,\n \"21-30\": 0,\n \"31-40\": 0,\n \"41+\": 0\n};\n\nlet genderTotals = {\n male: 0,\n female: 0,\n other: 0 // Add other genders as needed\n};\n\nlet jobStatusTotals = {};\n\n// Iterate through each document to calculate counts\ndata.forEach(doc => {\n // Calculate age range\n let age = parseInt(doc.age);\n let ageRange;\n if (age <= 20) {\n ageRange = \"0-20\";\n } else if (age <= 30) {\n ageRange = \"21-30\";\n } else if (age <= 40) {\n ageRange = \"31-40\";\n } else {\n ageRange = \"41+\";\n }\n // Increment age range count\n ageRanges[ageRange]++;\n\n // Increment gender count\n if (doc.gender === 'male') {\n genderTotals.male++;\n } else if (doc.gender === 'female') {\n genderTotals.female++;\n } else {\n genderTotals.other++;\n }\n\n // Increment job status count\n if (jobStatusTotals[doc.job]) {\n jobStatusTotals[doc.job]++;\n } else {\n jobStatusTotals[doc.job] = 1;\n }\n});\n\n\nmsg.payload = {\n \"ageRanges\": ageRanges,\n \"genderTotals\": genderTotals,\n \"jobStatusTotals\": jobStatusTotals\n}; \n\n// Return the aggregated counts object\nreturn msg","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":980,"y":540,"wires":[["3f3ad8e528f5800b"]]},{"id":"ef5e8501b76cfec8","type":"join","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":690,"y":500,"wires":[["9cd9d88bb507cc49","6f472c26ef54f974"]]},{"id":"d3a842120a526a7f","type":"comment","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Tranforming customer data","info":"","x":330,"y":420,"wires":[]},{"id":"6f472c26ef54f974","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","rules":[{"t":"set","p":"data","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":970,"y":420,"wires":[["a88a07f39e0e941d"]]},{"id":"a88a07f39e0e941d","type":"mongodb4","z":"977143edb097b685","g":"e0adf6e180ec1a7c","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"find","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":1130,"y":420,"wires":[["dd3fb62233d5477e"]]},{"id":"0e0129a95e24355c","type":"link in","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link in 1","links":["fd68d5c864a0e7c9"],"x":145,"y":500,"wires":[["ace58c34d1566f51"]]},{"id":"c7150b3b68fc34a0","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 2","mode":"link","links":["78176aee11393705"],"x":1405,"y":420,"wires":[]},{"id":"3f3ad8e528f5800b","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 3","mode":"link","links":["ecfa23782d33d813"],"x":1115,"y":540,"wires":[]},{"id":"dd3fb62233d5477e","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","func":"let previously_stored_customer_data = Array.isArray(msg.payload) ? msg.payload : (msg.payload ? [msg.payload] : []);\nlet latest_customer_data = Array.isArray(msg.data) ? Array.from(msg.data) : (msg.data ? [msg.data] : []);\n\nif (latest_customer_data.length !== 0 && previously_stored_customer_data.length !== 0) {\n let fullNameArray1 = previously_stored_customer_data.map(customer => customer.full_name);\n let filtered_customer_data = latest_customer_data.filter(customer => !fullNameArray1.includes(customer.full_name));\n msg.payload = [filtered_customer_data];\n return msg\n} else {\n // Case where there's no previously stored data\n msg.payload = [latest_customer_data];\n return msg\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1290,"y":420,"wires":[["c7150b3b68fc34a0"]]},{"id":"a0c7c3410ffb0e89","type":"mongodb4-client","name":"Mongodb configuration","protocol":"mongodb+srv","hostname":"","port":"","dbName":"${DATABASE}","appName":"","authSource":"","authMechanism":"DEFAULT","tls":false,"tlsCAFile":"","tlsCertificateKeyFile":"","tlsInsecure":false,"connectTimeoutMS":"30000","socketTimeoutMS":"0","minPoolSize":"0","maxPoolSize":"100","maxIdleTimeMS":"0","uri":"${HOST}","advanced":"{}","uriTabActive":"tab-uri-advanced"},{"id":"ac5e2cabb6251314","type":"group","z":"977143edb097b685","name":"","style":{"label":true},"nodes":["d6a4a19c23a0f42b","78176aee11393705","ecfa23782d33d813","dab90d6302b1c885","bc4afbc715e3b64d","d781431fed20d650","f19a1157e25b47df"],"x":114,"y":619,"w":592,"h":222},{"id":"d6a4a19c23a0f42b","type":"mongodb4","z":"977143edb097b685","g":"ac5e2cabb6251314","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"insertMany","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":370,"y":720,"wires":[["bc4afbc715e3b64d"]]},{"id":"78176aee11393705","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 2","links":["c7150b3b68fc34a0"],"x":155,"y":720,"wires":[["d6a4a19c23a0f42b"]]},{"id":"ecfa23782d33d813","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 3","links":["3f3ad8e528f5800b"],"x":155,"y":800,"wires":[["dab90d6302b1c885"]]},{"id":"dab90d6302b1c885","type":"file","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"","filename":"./customer_data_analytics","filenameType":"str","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":390,"y":800,"wires":[["d781431fed20d650"]]},{"id":"bc4afbc715e3b64d","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":720,"wires":[]},{"id":"d781431fed20d650","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":600,"y":800,"wires":[]},{"id":"f19a1157e25b47df","type":"comment","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Loading data into file and database","info":"","x":380,"y":660,"wires":[]},{"id":"520f961e35d10da4","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["9b534cdc46dfc52a","52c6d1c11c84571c","ed6fc24b155aef33","af4bc1c2a6e6d020","572c04ca900af9d5","b64ddca6aab82cb2","a135a8ed2c447561"],"x":114,"y":879,"w":1372,"h":142},{"id":"9b534cdc46dfc52a","type":"ui-chart","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"chart","order":2,"chartType":"bar","category":"category","categoryType":"property","xAxisProperty":"","xAxisPropertyType":"msg","xAxisType":"category","yAxisProperty":"value","ymin":"","ymax":"","action":"replace","pointShape":"circle","pointRadius":4,"showLegend":false,"removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"width":"13","height":8,"className":"","x":1410,"y":980,"wires":[[]]},{"id":"52c6d1c11c84571c","type":"function","z":"977143edb097b685","g":"520f961e35d10da4","name":"function 1","func":"let selectedDataForChart = global.get(\"selectedDataForChart\")\n// Assuming msg.payload is an object\nlet data = msg.payload[selectedDataForChart]\nlet result = [];\n\n// Loop through each key in the payload object\nObject.keys(data).forEach(key => {\n result.push({ category: key, value: data[key] });\n});\n\nmsg.payload = result\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1240,"y":980,"wires":[["9b534cdc46dfc52a"]]},{"id":"ed6fc24b155aef33","type":"ui-dropdown","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"Select Option:","tooltip":"","order":1,"width":0,"height":0,"passthru":false,"multiple":false,"options":[{"label":"Based on age group","value":"ageRanges","type":"str"},{"label":"Based on gender group","value":"genderTotals","type":"str"},{"label":"Based on job profile","value":"jobStatusTotals","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":220,"y":980,"wires":[["b64ddca6aab82cb2"]]},{"id":"af4bc1c2a6e6d020","type":"file in","z":"977143edb097b685","g":"520f961e35d10da4","name":"","filename":"./customer_data_analytics","filenameType":"str","format":"lines","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":810,"y":980,"wires":[["572c04ca900af9d5"]]},{"id":"572c04ca900af9d5","type":"json","z":"977143edb097b685","g":"520f961e35d10da4","name":"","property":"payload","action":"","pretty":false,"x":1050,"y":980,"wires":[["52c6d1c11c84571c"]]},{"id":"b64ddca6aab82cb2","type":"change","z":"977143edb097b685","g":"520f961e35d10da4","name":"store selected data in global context","rules":[{"t":"set","p":"selectedDataForChart","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":980,"wires":[["af4bc1c2a6e6d020"]]},{"id":"a135a8ed2c447561","type":"comment","z":"977143edb097b685","g":"520f961e35d10da4","name":"Visualizing data on charts","info":"","x":350,"y":920,"wires":[]},{"id":"1859e113313a5279","type":"ui-group","name":"chart","page":"","width":"13","height":"1","order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false"}] {% endrenderFlow %} 1. To Deploy the flow, click on the top-right Deploy button @@ -228,4 +228,4 @@ While Node-RED is versatile, there are some limitations to consider while using ## Additional resources - [Implementing ETL flows with Node-RED](https://developer.ibm.com/articles/implementing-etl-flows-with-node-red/): Read this IBM blog where a team member explains how they replaced a dedicated ETL tool with Node-RED. -- [Node-RED Forum Thread](https://discourse.nodered.org/t/etl-pipelines-with-node-red/): Explore this Node-RED forum thread where community members discussed how to utilize Node-RED as an ETL tool, including solutions for handling large datasets. \ No newline at end of file +- [Node-RED Forum Thread](https://discourse.nodered.org/t/etl-pipelines-with-node-red/): Explore this Node-RED forum thread where community members discussed how to utilize Node-RED as an ETL tool, including solutions for handling large datasets. From 63c33f6cb3cfda8606c8932ffc66e4543f237e45 Mon Sep 17 00:00:00 2001 From: "sumit shinde ( Roni )" <110285294+sumitshinde-84@users.noreply.github.com> Date: Thu, 13 Jun 2024 20:58:54 +0530 Subject: [PATCH 08/13] Update using-node-red-as-an-etl-tool.md --- .../2024/06/using-node-red-as-an-etl-tool.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/blog/2024/06/using-node-red-as-an-etl-tool.md b/src/blog/2024/06/using-node-red-as-an-etl-tool.md index 358116b6e3..3941a5ea2a 100644 --- a/src/blog/2024/06/using-node-red-as-an-etl-tool.md +++ b/src/blog/2024/06/using-node-red-as-an-etl-tool.md @@ -14,7 +14,7 @@ tags: - business intelligence --- -ETL is essential for data integration and analysis, playing a crucial role in many business contexts by helping to gain detailed business insights. Node-RED, known for its ease in creating IoT applications, has also been recognized for its potential in ETL tasks. When IBM published its blog on using Node-RED for ETL, the topic garnered significant attention and sparked discussions on whether it could be effectively utilized for ETL. In this guide, we'll explore how to use Node-RED for ETL, discussing both its strengths and weaknesses along the way. +ETL (Extract, Transform, Load) is essential for integrating and analyzing data, helping businesses unlock detailed insights. You might already know Node-RED for its user-friendly approach to creating IoT applications, but did you know it can also be a powerful tool for ETL tasks? When IBM published a blog about using Node-RED for ETL, it caught a lot of attention and got people talking about its potential in this space. In this guide, we'll walk you through how to use Node-RED for ETL, sharing its strengths and weaknesses along the way. @@ -24,13 +24,13 @@ ETL is essential for data integration and analysis, playing a crucial role in ma ## Node-RED as an ETL tool -Node-RED is specifically used for building various types of IoT applications. During the development of such applications, Node-RED is sometimes used as an ETL tool without even realizing it. For instance, when monitoring sensors across a facility, the process involves extracting data from sensors, transforming (cleaning and formatting) sensor data, and loading it into a database. There are thousands of other such examples. This demonstrates that Node-RED has already been adopted as an ETL tool at certain level. +Node-RED is specifically used for building various types of IoT applications. During the development of such applications, Node-RED is sometimes used as an ETL tool without even realizing it. For instance, when monitoring sensors across a facility, the process involves extracting data from sensors, transforming (cleaning and formatting) sensor data, and loading it into a database. There are thousands of other such examples. This demonstrates that Node-RED has already been adopted as an ETL tool at a certain level. *Note: We have mentioned only a few nodes that can be used in the ETL process, but there are thousands of other nodes that you can explore yourself by visiting the [Node-RED Nodes Library](https://flows.nodered.org/search?type=node)* ### Extracting -Node-RED can extract data from various sources, including APIs, databases, local filesystems, and IoT devices using built-in nodes and community-contributed nodes. For example, the HTTP request node can be used to pull data from web services, while nodes for MySQL, MongoDB, and PostgreSQL can extract data from databases. Nodes for MQTT and Kafka can fetch data from message brokers. Additionally, there are diffrent cloud nodes for cloud platform such as AWS, GCP, and IBM Watson that allow extraction of data from cloud storage services. +Node-RED can extract data from various sources, including APIs, databases, local filesystems, and IoT devices using built-in nodes and community-contributed nodes. For example, the HTTP request node can be used to pull data from web services, while nodes for MySQL, MongoDB, and PostgreSQL can extract data from databases. Nodes for MQTT and Kafka can fetch data from message brokers. Additionally, there are different cloud nodes for cloud platforms such as AWS, GCP, and IBM Watson that allow extraction of data from cloud storage services. ### Transforming @@ -72,7 +72,7 @@ Before proceeding further make sure you have installed the following nodes: 1. Drag an Inject node onto the canvas. 2. Drag an HTTP Request node onto the canvas, double-click on it, and set the URL to `https://api.slingacademy.com/v1/sample-data/files/customers.json`. 3. Drag a Link-out node onto the canvas. -4. Connect the Inject node's output to the input of the HTTP Request node, and the HTTP Request node's output to the input of the Link-out node. +4. Connect the Inject node's output to the input of the HTTP Request node and the HTTP Request node's output to the input of the Link-out node. Now, if you add a Debug node after the HTTP Request node, you will see an array of objects containing customer data in the Debug panel. Each object has properties such as `first_name`, `last_name`, `email`, and others. @@ -88,7 +88,7 @@ In next section, we'll perform a transformation to replace the existing properti 2. Drag a Split node onto the canvas. 3. Drag a Change node onto the canvas and Set `msg.payload.full_name` to `payload.first_name & " " & payload.last_name` as the JSONata expression, this JSONata expression will concat the firstname and lastname properties, then delete unnecessary properties like `first_name` and `last_name`. 4. Drag a Join node onto the canvas. -5. Connect the output of Link-in node to the input of Split node, then split node output to the input of join node. +5. Connect the output of the Link-in node to the input of the Split node, then the Split node output to the input of the Join node. Up to this point, we've established a flow that creates a new property in customer data objects called 'full_name' and subsequently removes any unnecessary properties. In summary, we've cleaned the data according to our needs. @@ -96,7 +96,7 @@ Up to this point, we've established a flow that creates a new property in custom 1. Drag a Change node onto the canvas, and set `msg.data` to `msg.payload` and `msg.payload` to `[]`. 2. Drag a MongoDB4 node onto the canvas, and configure it with your correct details. If you haven't used MongoDB with Node-RED, please refer to the [Using MongoDB with Node-RED](/blog/2024/04/using-mongodb-with-node-red/). Enter `find` into the Operation field. -3. Drag a Function node onto the canvas and insert the following code into it and give it name "Data deplication": +3. Drag a Function node onto the canvas and insert the following code into it and give it the name "Data deduplication": ```javascript // Check if previously stored customer data is present, and ensure it's an array @@ -123,13 +123,13 @@ if (latest_customer_data.length !== 0 && previously_stored_customer_data.length ``` 4. Drag a Link-out node onto the canvas. -5. Connect the output of Join node to the input of change node and output of change node to the input of MongoDB4 node and then MongoDB4 output to the input of function node named "Data deplication" and output of that function node to the input of Link-out node. +5. Connect the output of the Join node to the input of change node and the output of the Change node to the input of the MongoDB4 node and then MongoDB4 output to the input of the function node named "Data deplication" and output of that function node to the input of Link-out node. Now, we have added additional nodes that perform data deduplication. This means we will create a new array containing unique data that is not already stored in the database to avoid data duplications. For filtering that data, we are using JavaScript with a function node. ## Data Processing -1. Drag a Function node onto the canvas and insert the following code into it and name this node "Data processing": +1. Drag a Function node onto the canvas insert the following code into it and name this node "Data processing": ```javascript let data = msg.payload; @@ -211,7 +211,7 @@ Following is the complete flow of the project along with dashboard visualization {% endrenderFlow %} 1. To Deploy the flow, click on the top-right Deploy button -2. To visit the dashboard, Go to Dashboard 2.0 sidebar and click on the top-right "Open dashboard" button. +2. To visit the dashboard, Go to the Dashboard 2.0 sidebar and click on the top-right "Open dashboard" button. !["Screenshot of dashboard visualizing process customer data based on job profile"](./images/etl-with-node-red-chart-based-on-job-profile.png "Screenshot of dashboard visualizing process customer data based on job profile"){data-zoomable} @@ -219,7 +219,7 @@ Following is the complete flow of the project along with dashboard visualization ## What are the limitations of using Node-RED as an ETL tool -While Node-RED is versatile, there are some limitations to consider while using it as ETL tool: +While Node-RED is versatile, there are some limitations to consider while using it as an ETL tool: - **Scalability:** Node-RED might struggle with extremely large datasets compared to dedicated ETL tools. - **Advanced Features:** Some advanced ETL features, like automated schema detection and sophisticated error handling, might require additional customization or external modules. From 395f514a15ce43f230622b32459ed45a46bd98c7 Mon Sep 17 00:00:00 2001 From: "sumit shinde ( Roni )" <110285294+sumitshinde-84@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:12:38 +0530 Subject: [PATCH 09/13] Update using-node-red-as-an-etl-tool.md --- src/blog/2024/06/using-node-red-as-an-etl-tool.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blog/2024/06/using-node-red-as-an-etl-tool.md b/src/blog/2024/06/using-node-red-as-an-etl-tool.md index 3941a5ea2a..b564b168f4 100644 --- a/src/blog/2024/06/using-node-red-as-an-etl-tool.md +++ b/src/blog/2024/06/using-node-red-as-an-etl-tool.md @@ -207,7 +207,7 @@ Now, finally, in this loading phase, we are storing the cleaned, formatted, and Following is the complete flow of the project along with dashboard visualization. {% renderFlow %} -[{"id":"e85cb581eb249115","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["218b698ddba2210b","638eddcd2b5f645e","9773152e6a0f2287","fd68d5c864a0e7c9"],"x":114,"y":159,"w":532,"h":182},{"id":"218b698ddba2210b","type":"http request","z":"977143edb097b685","g":"e85cb581eb249115","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.slingacademy.com/v1/sample-data/files/customers.json","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":430,"y":300,"wires":[["fd68d5c864a0e7c9"]]},{"id":"638eddcd2b5f645e","type":"inject","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extract Data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":230,"y":300,"wires":[["218b698ddba2210b"]]},{"id":"9773152e6a0f2287","type":"comment","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extracting customer data from api","info":"","x":330,"y":200,"wires":[]},{"id":"fd68d5c864a0e7c9","type":"link out","z":"977143edb097b685","g":"e85cb581eb249115","name":"link out 1","mode":"link","links":["0e0129a95e24355c"],"x":605,"y":300,"wires":[]},{"id":"e0adf6e180ec1a7c","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["ace58c34d1566f51","d2a48c9825b224b4","9cd9d88bb507cc49","ef5e8501b76cfec8","d3a842120a526a7f","6f472c26ef54f974","a88a07f39e0e941d","0e0129a95e24355c","c7150b3b68fc34a0","3f3ad8e528f5800b","dd3fb62233d5477e"],"x":104,"y":379,"w":1342,"h":202},{"id":"ace58c34d1566f51","type":"split","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":250,"y":500,"wires":[["d2a48c9825b224b4"]]},{"id":"d2a48c9825b224b4","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","rules":[{"t":"set","p":"payload.full_name","pt":"msg","to":"payload.first_name & \" \" & payload.last_name","tot":"jsonata"},{"t":"delete","p":"payload.first_name","pt":"msg"},{"t":"delete","p":"payload.last_name","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":500,"wires":[["ef5e8501b76cfec8"]]},{"id":"9cd9d88bb507cc49","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"data processing","func":"let data = msg.payload\n\nlet ageRanges = {\n \"0-20\": 0,\n \"21-30\": 0,\n \"31-40\": 0,\n \"41+\": 0\n};\n\nlet genderTotals = {\n male: 0,\n female: 0,\n other: 0 // Add other genders as needed\n};\n\nlet jobStatusTotals = {};\n\n// Iterate through each document to calculate counts\ndata.forEach(doc => {\n // Calculate age range\n let age = parseInt(doc.age);\n let ageRange;\n if (age <= 20) {\n ageRange = \"0-20\";\n } else if (age <= 30) {\n ageRange = \"21-30\";\n } else if (age <= 40) {\n ageRange = \"31-40\";\n } else {\n ageRange = \"41+\";\n }\n // Increment age range count\n ageRanges[ageRange]++;\n\n // Increment gender count\n if (doc.gender === 'male') {\n genderTotals.male++;\n } else if (doc.gender === 'female') {\n genderTotals.female++;\n } else {\n genderTotals.other++;\n }\n\n // Increment job status count\n if (jobStatusTotals[doc.job]) {\n jobStatusTotals[doc.job]++;\n } else {\n jobStatusTotals[doc.job] = 1;\n }\n});\n\n\nmsg.payload = {\n \"ageRanges\": ageRanges,\n \"genderTotals\": genderTotals,\n \"jobStatusTotals\": jobStatusTotals\n}; \n\n// Return the aggregated counts object\nreturn msg","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":980,"y":540,"wires":[["3f3ad8e528f5800b"]]},{"id":"ef5e8501b76cfec8","type":"join","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":690,"y":500,"wires":[["9cd9d88bb507cc49","6f472c26ef54f974"]]},{"id":"d3a842120a526a7f","type":"comment","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Tranforming customer data","info":"","x":330,"y":420,"wires":[]},{"id":"6f472c26ef54f974","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","rules":[{"t":"set","p":"data","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":970,"y":420,"wires":[["a88a07f39e0e941d"]]},{"id":"a88a07f39e0e941d","type":"mongodb4","z":"977143edb097b685","g":"e0adf6e180ec1a7c","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"find","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":1130,"y":420,"wires":[["dd3fb62233d5477e"]]},{"id":"0e0129a95e24355c","type":"link in","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link in 1","links":["fd68d5c864a0e7c9"],"x":145,"y":500,"wires":[["ace58c34d1566f51"]]},{"id":"c7150b3b68fc34a0","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 2","mode":"link","links":["78176aee11393705"],"x":1405,"y":420,"wires":[]},{"id":"3f3ad8e528f5800b","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 3","mode":"link","links":["ecfa23782d33d813"],"x":1115,"y":540,"wires":[]},{"id":"dd3fb62233d5477e","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","func":"let previously_stored_customer_data = Array.isArray(msg.payload) ? msg.payload : (msg.payload ? [msg.payload] : []);\nlet latest_customer_data = Array.isArray(msg.data) ? Array.from(msg.data) : (msg.data ? [msg.data] : []);\n\nif (latest_customer_data.length !== 0 && previously_stored_customer_data.length !== 0) {\n let fullNameArray1 = previously_stored_customer_data.map(customer => customer.full_name);\n let filtered_customer_data = latest_customer_data.filter(customer => !fullNameArray1.includes(customer.full_name));\n msg.payload = [filtered_customer_data];\n return msg\n} else {\n // Case where there's no previously stored data\n msg.payload = [latest_customer_data];\n return msg\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1290,"y":420,"wires":[["c7150b3b68fc34a0"]]},{"id":"a0c7c3410ffb0e89","type":"mongodb4-client","name":"Mongodb configuration","protocol":"mongodb+srv","hostname":"","port":"","dbName":"${DATABASE}","appName":"","authSource":"","authMechanism":"DEFAULT","tls":false,"tlsCAFile":"","tlsCertificateKeyFile":"","tlsInsecure":false,"connectTimeoutMS":"30000","socketTimeoutMS":"0","minPoolSize":"0","maxPoolSize":"100","maxIdleTimeMS":"0","uri":"${HOST}","advanced":"{}","uriTabActive":"tab-uri-advanced"},{"id":"ac5e2cabb6251314","type":"group","z":"977143edb097b685","name":"","style":{"label":true},"nodes":["d6a4a19c23a0f42b","78176aee11393705","ecfa23782d33d813","dab90d6302b1c885","bc4afbc715e3b64d","d781431fed20d650","f19a1157e25b47df"],"x":114,"y":619,"w":592,"h":222},{"id":"d6a4a19c23a0f42b","type":"mongodb4","z":"977143edb097b685","g":"ac5e2cabb6251314","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"insertMany","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":370,"y":720,"wires":[["bc4afbc715e3b64d"]]},{"id":"78176aee11393705","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 2","links":["c7150b3b68fc34a0"],"x":155,"y":720,"wires":[["d6a4a19c23a0f42b"]]},{"id":"ecfa23782d33d813","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 3","links":["3f3ad8e528f5800b"],"x":155,"y":800,"wires":[["dab90d6302b1c885"]]},{"id":"dab90d6302b1c885","type":"file","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"","filename":"./customer_data_analytics","filenameType":"str","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":390,"y":800,"wires":[["d781431fed20d650"]]},{"id":"bc4afbc715e3b64d","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":720,"wires":[]},{"id":"d781431fed20d650","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":600,"y":800,"wires":[]},{"id":"f19a1157e25b47df","type":"comment","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Loading data into file and database","info":"","x":380,"y":660,"wires":[]},{"id":"520f961e35d10da4","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["9b534cdc46dfc52a","52c6d1c11c84571c","ed6fc24b155aef33","af4bc1c2a6e6d020","572c04ca900af9d5","b64ddca6aab82cb2","a135a8ed2c447561"],"x":114,"y":879,"w":1372,"h":142},{"id":"9b534cdc46dfc52a","type":"ui-chart","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"chart","order":2,"chartType":"bar","category":"category","categoryType":"property","xAxisProperty":"","xAxisPropertyType":"msg","xAxisType":"category","yAxisProperty":"value","ymin":"","ymax":"","action":"replace","pointShape":"circle","pointRadius":4,"showLegend":false,"removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"width":"13","height":8,"className":"","x":1410,"y":980,"wires":[[]]},{"id":"52c6d1c11c84571c","type":"function","z":"977143edb097b685","g":"520f961e35d10da4","name":"function 1","func":"let selectedDataForChart = global.get(\"selectedDataForChart\")\n// Assuming msg.payload is an object\nlet data = msg.payload[selectedDataForChart]\nlet result = [];\n\n// Loop through each key in the payload object\nObject.keys(data).forEach(key => {\n result.push({ category: key, value: data[key] });\n});\n\nmsg.payload = result\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1240,"y":980,"wires":[["9b534cdc46dfc52a"]]},{"id":"ed6fc24b155aef33","type":"ui-dropdown","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"Select Option:","tooltip":"","order":1,"width":0,"height":0,"passthru":false,"multiple":false,"options":[{"label":"Based on age group","value":"ageRanges","type":"str"},{"label":"Based on gender group","value":"genderTotals","type":"str"},{"label":"Based on job profile","value":"jobStatusTotals","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":220,"y":980,"wires":[["b64ddca6aab82cb2"]]},{"id":"af4bc1c2a6e6d020","type":"file in","z":"977143edb097b685","g":"520f961e35d10da4","name":"","filename":"./customer_data_analytics","filenameType":"str","format":"lines","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":810,"y":980,"wires":[["572c04ca900af9d5"]]},{"id":"572c04ca900af9d5","type":"json","z":"977143edb097b685","g":"520f961e35d10da4","name":"","property":"payload","action":"","pretty":false,"x":1050,"y":980,"wires":[["52c6d1c11c84571c"]]},{"id":"b64ddca6aab82cb2","type":"change","z":"977143edb097b685","g":"520f961e35d10da4","name":"store selected data in global context","rules":[{"t":"set","p":"selectedDataForChart","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":980,"wires":[["af4bc1c2a6e6d020"]]},{"id":"a135a8ed2c447561","type":"comment","z":"977143edb097b685","g":"520f961e35d10da4","name":"Visualizing data on charts","info":"","x":350,"y":920,"wires":[]},{"id":"1859e113313a5279","type":"ui-group","name":"chart","page":"","width":"13","height":"1","order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false"}] +[{"id":"e85cb581eb249115","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["218b698ddba2210b","638eddcd2b5f645e","9773152e6a0f2287","fd68d5c864a0e7c9"],"x":254,"y":119,"w":532,"h":182},{"id":"218b698ddba2210b","type":"http request","z":"977143edb097b685","g":"e85cb581eb249115","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.slingacademy.com/v1/sample-data/files/customers.json","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":570,"y":260,"wires":[["fd68d5c864a0e7c9"]]},{"id":"638eddcd2b5f645e","type":"inject","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extract Data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":370,"y":260,"wires":[["218b698ddba2210b"]]},{"id":"9773152e6a0f2287","type":"comment","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extracting customer data from api","info":"","x":470,"y":160,"wires":[]},{"id":"fd68d5c864a0e7c9","type":"link out","z":"977143edb097b685","g":"e85cb581eb249115","name":"link out 1","mode":"link","links":["0e0129a95e24355c"],"x":745,"y":260,"wires":[]},{"id":"e0adf6e180ec1a7c","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["ace58c34d1566f51","d2a48c9825b224b4","9cd9d88bb507cc49","ef5e8501b76cfec8","d3a842120a526a7f","6f472c26ef54f974","a88a07f39e0e941d","0e0129a95e24355c","c7150b3b68fc34a0","3f3ad8e528f5800b","dd3fb62233d5477e"],"x":244,"y":339,"w":1342,"h":202},{"id":"ace58c34d1566f51","type":"split","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":390,"y":460,"wires":[["d2a48c9825b224b4"]]},{"id":"d2a48c9825b224b4","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","rules":[{"t":"set","p":"payload.full_name","pt":"msg","to":"payload.first_name & \" \" & payload.last_name","tot":"jsonata"},{"t":"delete","p":"payload.first_name","pt":"msg"},{"t":"delete","p":"payload.last_name","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":460,"wires":[["ef5e8501b76cfec8"]]},{"id":"9cd9d88bb507cc49","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"data processing","func":"let data = msg.payload\n\nlet ageRanges = {\n    \"0-20\": 0,\n    \"21-30\": 0,\n    \"31-40\": 0,\n    \"41+\": 0\n};\n\nlet genderTotals = {\n    male: 0,\n    female: 0,\n    other: 0  // Add other genders as needed\n};\n\nlet jobStatusTotals = {};\n\n// Iterate through each document to calculate counts\ndata.forEach(doc => {\n    // Calculate age range\n    let age = parseInt(doc.age);\n    let ageRange;\n    if (age <= 20) {\n        ageRange = \"0-20\";\n    } else if (age <= 30) {\n        ageRange = \"21-30\";\n    } else if (age <= 40) {\n        ageRange = \"31-40\";\n    } else {\n        ageRange = \"41+\";\n    }\n    // Increment age range count\n    ageRanges[ageRange]++;\n\n    // Increment gender count\n    if (doc.gender === 'male') {\n        genderTotals.male++;\n    } else if (doc.gender === 'female') {\n        genderTotals.female++;\n    } else {\n        genderTotals.other++;\n    }\n\n    // Increment job status count\n    if (jobStatusTotals[doc.job]) {\n        jobStatusTotals[doc.job]++;\n    } else {\n        jobStatusTotals[doc.job] = 1;\n    }\n});\n\n\nmsg.payload = {\n    \"ageRanges\": ageRanges,\n    \"genderTotals\": genderTotals,\n    \"jobStatusTotals\": jobStatusTotals\n}; \n\n// Return the aggregated counts object\nreturn msg","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1120,"y":500,"wires":[["3f3ad8e528f5800b"]]},{"id":"ef5e8501b76cfec8","type":"join","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":830,"y":460,"wires":[["9cd9d88bb507cc49","6f472c26ef54f974"]]},{"id":"d3a842120a526a7f","type":"comment","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Tranforming customer data","info":"","x":470,"y":380,"wires":[]},{"id":"6f472c26ef54f974","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","rules":[{"t":"set","p":"data","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":1110,"y":380,"wires":[["a88a07f39e0e941d"]]},{"id":"a88a07f39e0e941d","type":"mongodb4","z":"977143edb097b685","g":"e0adf6e180ec1a7c","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"find","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":1270,"y":380,"wires":[["dd3fb62233d5477e"]]},{"id":"0e0129a95e24355c","type":"link in","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link in 1","links":["fd68d5c864a0e7c9"],"x":285,"y":460,"wires":[["ace58c34d1566f51"]]},{"id":"c7150b3b68fc34a0","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 2","mode":"link","links":["78176aee11393705"],"x":1545,"y":380,"wires":[]},{"id":"3f3ad8e528f5800b","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 3","mode":"link","links":["ecfa23782d33d813"],"x":1255,"y":500,"wires":[]},{"id":"dd3fb62233d5477e","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","func":"let previously_stored_customer_data = Array.isArray(msg.payload) ? msg.payload : (msg.payload ? [msg.payload] : []);\nlet latest_customer_data = Array.isArray(msg.data) ? Array.from(msg.data) : (msg.data ? [msg.data] : []);\n\nif (latest_customer_data.length !== 0 && previously_stored_customer_data.length !== 0) {\n    let fullNameArray1 = previously_stored_customer_data.map(customer => customer.full_name);\n    let filtered_customer_data = latest_customer_data.filter(customer => !fullNameArray1.includes(customer.full_name));\n    msg.payload = [filtered_customer_data];\n    return msg\n} else {\n    // Case where there's no previously stored data\n    msg.payload = [latest_customer_data];\n    return msg\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1430,"y":380,"wires":[["c7150b3b68fc34a0"]]},{"id":"a0c7c3410ffb0e89","type":"mongodb4-client","name":"MongoDB Config","protocol":"mongodb+srv","hostname":"","port":"","dbName":"${DATABASE}","appName":"","authSource":"","authMechanism":"DEFAULT","tls":false,"tlsCAFile":"","tlsCertificateKeyFile":"","tlsInsecure":false,"connectTimeoutMS":"30000","socketTimeoutMS":"0","minPoolSize":"0","maxPoolSize":"100","maxIdleTimeMS":"0","uri":"${URI}","advanced":"{}","uriTabActive":"tab-uri-advanced"},{"id":"ac5e2cabb6251314","type":"group","z":"977143edb097b685","name":"","style":{"label":true},"nodes":["d6a4a19c23a0f42b","78176aee11393705","ecfa23782d33d813","dab90d6302b1c885","bc4afbc715e3b64d","d781431fed20d650","f19a1157e25b47df"],"x":254,"y":579,"w":592,"h":222},{"id":"d6a4a19c23a0f42b","type":"mongodb4","z":"977143edb097b685","g":"ac5e2cabb6251314","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"insertMany","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":510,"y":680,"wires":[["bc4afbc715e3b64d"]]},{"id":"78176aee11393705","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 2","links":["c7150b3b68fc34a0"],"x":295,"y":680,"wires":[["d6a4a19c23a0f42b"]]},{"id":"ecfa23782d33d813","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 3","links":["3f3ad8e528f5800b"],"x":295,"y":760,"wires":[["dab90d6302b1c885"]]},{"id":"dab90d6302b1c885","type":"file","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"","filename":"./customer_data_analytics","filenameType":"str","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":530,"y":760,"wires":[["d781431fed20d650"]]},{"id":"bc4afbc715e3b64d","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":720,"y":680,"wires":[]},{"id":"d781431fed20d650","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":740,"y":760,"wires":[]},{"id":"f19a1157e25b47df","type":"comment","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Loading data into file and database","info":"","x":520,"y":620,"wires":[]},{"id":"520f961e35d10da4","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["9b534cdc46dfc52a","52c6d1c11c84571c","ed6fc24b155aef33","af4bc1c2a6e6d020","572c04ca900af9d5","b64ddca6aab82cb2","a135a8ed2c447561"],"x":254,"y":839,"w":1372,"h":142},{"id":"9b534cdc46dfc52a","type":"ui-chart","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"chart","order":2,"chartType":"bar","category":"category","categoryType":"property","xAxisProperty":"","xAxisPropertyType":"msg","xAxisType":"category","yAxisProperty":"value","ymin":"","ymax":"","action":"replace","pointShape":"circle","pointRadius":4,"showLegend":false,"removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"width":"13","height":8,"className":"","x":1550,"y":940,"wires":[[]]},{"id":"52c6d1c11c84571c","type":"function","z":"977143edb097b685","g":"520f961e35d10da4","name":"function 1","func":"let selectedDataForChart = global.get(\"selectedDataForChart\")\n// Assuming msg.payload is an object\nlet data = msg.payload[selectedDataForChart]\nlet result = [];\n\n// Loop through each key in the payload object\nObject.keys(data).forEach(key => {\n    result.push({ category: key, value: data[key] });\n});\n\nmsg.payload = result\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1380,"y":940,"wires":[["9b534cdc46dfc52a"]]},{"id":"ed6fc24b155aef33","type":"ui-dropdown","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"Select Option:","tooltip":"","order":1,"width":0,"height":0,"passthru":false,"multiple":false,"options":[{"label":"Based on age group","value":"ageRanges","type":"str"},{"label":"Based on gender group","value":"genderTotals","type":"str"},{"label":"Based on job profile","value":"jobStatusTotals","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":360,"y":940,"wires":[["b64ddca6aab82cb2"]]},{"id":"af4bc1c2a6e6d020","type":"file in","z":"977143edb097b685","g":"520f961e35d10da4","name":"","filename":"./customer_data_analytics","filenameType":"str","format":"lines","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":950,"y":940,"wires":[["572c04ca900af9d5"]]},{"id":"572c04ca900af9d5","type":"json","z":"977143edb097b685","g":"520f961e35d10da4","name":"","property":"payload","action":"","pretty":false,"x":1190,"y":940,"wires":[["52c6d1c11c84571c"]]},{"id":"b64ddca6aab82cb2","type":"change","z":"977143edb097b685","g":"520f961e35d10da4","name":"store selected data in global context","rules":[{"t":"set","p":"selectedDataForChart","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":640,"y":940,"wires":[["af4bc1c2a6e6d020"]]},{"id":"a135a8ed2c447561","type":"comment","z":"977143edb097b685","g":"520f961e35d10da4","name":"Visualizing data on charts","info":"","x":490,"y":880,"wires":[]},{"id":"1859e113313a5279","type":"ui-group","name":"chart","page":"f10b4d0259e43aeb","width":"13","height":"1","order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"f10b4d0259e43aeb","type":"ui-page","name":"home","ui":"cb79bc4520925e32","path":"/","icon":"","layout":"grid","theme":"2c5d702b11de7dd1","order":1,"className":"","visible":true,"disabled":"false"},{"id":"cb79bc4520925e32","type":"ui-base","name":"My UI","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false},{"id":"2c5d702b11de7dd1","type":"ui-theme","name":"Theme Name","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"}}] {% endrenderFlow %} 1. To Deploy the flow, click on the top-right Deploy button From 929249b61e508bbba40ba1f44eaa3d36b674c017 Mon Sep 17 00:00:00 2001 From: "sumit shinde ( Roni )" <110285294+sumitshinde-84@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:44:10 +0530 Subject: [PATCH 10/13] Update using-node-red-as-an-etl-tool.md --- .../2024/06/using-node-red-as-an-etl-tool.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/blog/2024/06/using-node-red-as-an-etl-tool.md b/src/blog/2024/06/using-node-red-as-an-etl-tool.md index b564b168f4..45d61c0e74 100644 --- a/src/blog/2024/06/using-node-red-as-an-etl-tool.md +++ b/src/blog/2024/06/using-node-red-as-an-etl-tool.md @@ -14,7 +14,7 @@ tags: - business intelligence --- -ETL (Extract, Transform, Load) is essential for integrating and analyzing data, helping businesses unlock detailed insights. You might already know Node-RED for its user-friendly approach to creating IoT applications, but did you know it can also be a powerful tool for ETL tasks? When IBM published a blog about using Node-RED for ETL, it caught a lot of attention and got people talking about its potential in this space. In this guide, we'll walk you through how to use Node-RED for ETL, sharing its strengths and weaknesses along the way. +ETL (Extract, Transform, Load) is essential for integrating and analyzing data, helping businesses unlock detailed insights. You already know Node-RED for its user-friendly approach to creating IoT applications, but did you know it can also be a powerful tool for ETL tasks? When IBM published a blog about using Node-RED for ETL, it caught a lot of attention and got people talking about its potential in this space. In this guide, we'll walk you through how to use Node-RED for ETL, sharing its strengths and weaknesses along the way. @@ -24,17 +24,17 @@ ETL (Extract, Transform, Load) is essential for integrating and analyzing data, ## Node-RED as an ETL tool -Node-RED is specifically used for building various types of IoT applications. During the development of such applications, Node-RED is sometimes used as an ETL tool without even realizing it. For instance, when monitoring sensors across a facility, the process involves extracting data from sensors, transforming (cleaning and formatting) sensor data, and loading it into a database. There are thousands of other such examples. This demonstrates that Node-RED has already been adopted as an ETL tool at a certain level. +Node-RED is specifically used for building various types of IoT applications. During the development of such applications, we sometimes used Node-RED as an ETL is tool without even realizing it. For instance, when monitoring sensors across a facility, the process involves extracting data from sensors, transforming (cleaning and formatting) sensor data, and loading it into a database. There are thousands of other such examples. This demonstrates that Node-RED has already been adopted as an ETL tool at a certain level. *Note: We have mentioned only a few nodes that can be used in the ETL process, but there are thousands of other nodes that you can explore yourself by visiting the [Node-RED Nodes Library](https://flows.nodered.org/search?type=node)* ### Extracting -Node-RED can extract data from various sources, including APIs, databases, local filesystems, and IoT devices using built-in nodes and community-contributed nodes. For example, the HTTP request node can be used to pull data from web services, while nodes for MySQL, MongoDB, and PostgreSQL can extract data from databases. Nodes for MQTT and Kafka can fetch data from message brokers. Additionally, there are different cloud nodes for cloud platforms such as AWS, GCP, and IBM Watson that allow extraction of data from cloud storage services. +Node-RED can extract data from various sources, including APIs, databases, local filesystems, and IoT devices using built-in nodes and community-contributed nodes. For example, the HTTP request node can be used to pull data from web services, while nodes for MySQL, MongoDB, and PostgreSQL can extract data from databases. Nodes for MQTT and Kafka can fetch data from message brokers. File nodes enable extraction of data from local filesystems, while different cloud nodes for platforms like AWS, GCP, and IBM Watson allow extraction of data from cloud storage services. Moreover, Node-RED running on edge devices can extract data from sensors connected directly to them. ### Transforming -Transforming data involves cleaning, structuring, and applying business rules. This can be done using function nodes with custom JavaScript, along with nodes like JSON, split, join, change, CSV, and XML for parsing and formatting. +Transforming data involves cleaning, structuring, and applying business rules. This can be done using function nodes with custom JavaScript, along with nodes like JSON, Split, Join, Change, CSV, and XML for parsing and formatting. ### Loading @@ -50,7 +50,7 @@ Node-RED Dashboard 2.0 provides several chart options, and more are expected in 1. **Ease of Use:** Its visual programming interface makes it accessible to non-developers. 2. **Flexibility:** A wide range of nodes and the ability to write custom JavaScript allow for flexible data processing. -3. **Integration:** Strong support for IoT and real-time data processing, making it ideal for integrating diverse data sources. +3. **Integration:** Node-RED excels in integrating IoT devices and handling real-time data, making it well-suited for combining diverse data sources into unified workflows. 4. **Cost-Effective:** Being open-source, Node-RED can be a cost-effective alternative to expensive ETL tools. 5. **Community Support:** A large community provides a wealth of nodes, examples, and support. @@ -71,7 +71,7 @@ Before proceeding further make sure you have installed the following nodes: 1. Drag an Inject node onto the canvas. 2. Drag an HTTP Request node onto the canvas, double-click on it, and set the URL to `https://api.slingacademy.com/v1/sample-data/files/customers.json`. -3. Drag a Link-out node onto the canvas. +3. Drag a Link-out node onto the canvas, I am using Link nodes to separate flow groups for different ETL phases to enhance organization, although you can directly connect nodes or maintain a single flow group. 4. Connect the Inject node's output to the input of the HTTP Request node and the HTTP Request node's output to the input of the Link-out node. Now, if you add a Debug node after the HTTP Request node, you will see an array of objects containing customer data in the Debug panel. Each object has properties such as `first_name`, `last_name`, `email`, and others. @@ -221,9 +221,9 @@ Following is the complete flow of the project along with dashboard visualization While Node-RED is versatile, there are some limitations to consider while using it as an ETL tool: -- **Scalability:** Node-RED might struggle with extremely large datasets compared to dedicated ETL tools. -- **Advanced Features:** Some advanced ETL features, like automated schema detection and sophisticated error handling, might require additional customization or external modules. -- **Data Governance:** Node-RED does not inherently provide robust data governance and lineage tracking which are often essential in enterprise ETL tools. +- Advanced Features: Some advanced ETL features, like automated schema detection and sophisticated error handling, might require additional customization or external modules. +- Data Governance: Node-RED does not inherently provide robust data governance and lineage tracking, which are often essential in enterprise ETL tools. +- Scalability: While Node-RED can handle many tasks effectively, it might not offer the same level of optimization for extremely large datasets compared to dedicated ETL tools. ## Additional resources From fe981fb254156771a56f212efb52cf8acc97d5cc Mon Sep 17 00:00:00 2001 From: "sumit shinde ( Roni )" <110285294+sumitshinde-84@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:47:52 +0530 Subject: [PATCH 11/13] Update using-node-red-as-an-etl-tool.md --- src/blog/2024/06/using-node-red-as-an-etl-tool.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/blog/2024/06/using-node-red-as-an-etl-tool.md b/src/blog/2024/06/using-node-red-as-an-etl-tool.md index 45d61c0e74..d72f602096 100644 --- a/src/blog/2024/06/using-node-red-as-an-etl-tool.md +++ b/src/blog/2024/06/using-node-red-as-an-etl-tool.md @@ -204,7 +204,7 @@ Now, finally, in this loading phase, we are storing the cleaned, formatted, and ## Deploying the flow -Following is the complete flow of the project along with dashboard visualization. +Below is the complete flow of the project, including dashboard visualization. For database configuration, I have utilized environment variables. Please ensure to set the variables with your database configuration before deploying the flow. {% renderFlow %} [{"id":"e85cb581eb249115","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["218b698ddba2210b","638eddcd2b5f645e","9773152e6a0f2287","fd68d5c864a0e7c9"],"x":254,"y":119,"w":532,"h":182},{"id":"218b698ddba2210b","type":"http request","z":"977143edb097b685","g":"e85cb581eb249115","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.slingacademy.com/v1/sample-data/files/customers.json","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":570,"y":260,"wires":[["fd68d5c864a0e7c9"]]},{"id":"638eddcd2b5f645e","type":"inject","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extract Data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":370,"y":260,"wires":[["218b698ddba2210b"]]},{"id":"9773152e6a0f2287","type":"comment","z":"977143edb097b685","g":"e85cb581eb249115","name":"Extracting customer data from api","info":"","x":470,"y":160,"wires":[]},{"id":"fd68d5c864a0e7c9","type":"link out","z":"977143edb097b685","g":"e85cb581eb249115","name":"link out 1","mode":"link","links":["0e0129a95e24355c"],"x":745,"y":260,"wires":[]},{"id":"e0adf6e180ec1a7c","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["ace58c34d1566f51","d2a48c9825b224b4","9cd9d88bb507cc49","ef5e8501b76cfec8","d3a842120a526a7f","6f472c26ef54f974","a88a07f39e0e941d","0e0129a95e24355c","c7150b3b68fc34a0","3f3ad8e528f5800b","dd3fb62233d5477e"],"x":244,"y":339,"w":1342,"h":202},{"id":"ace58c34d1566f51","type":"split","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":390,"y":460,"wires":[["d2a48c9825b224b4"]]},{"id":"d2a48c9825b224b4","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","rules":[{"t":"set","p":"payload.full_name","pt":"msg","to":"payload.first_name & \" \" & payload.last_name","tot":"jsonata"},{"t":"delete","p":"payload.first_name","pt":"msg"},{"t":"delete","p":"payload.last_name","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":460,"wires":[["ef5e8501b76cfec8"]]},{"id":"9cd9d88bb507cc49","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"data processing","func":"let data = msg.payload\n\nlet ageRanges = {\n    \"0-20\": 0,\n    \"21-30\": 0,\n    \"31-40\": 0,\n    \"41+\": 0\n};\n\nlet genderTotals = {\n    male: 0,\n    female: 0,\n    other: 0  // Add other genders as needed\n};\n\nlet jobStatusTotals = {};\n\n// Iterate through each document to calculate counts\ndata.forEach(doc => {\n    // Calculate age range\n    let age = parseInt(doc.age);\n    let ageRange;\n    if (age <= 20) {\n        ageRange = \"0-20\";\n    } else if (age <= 30) {\n        ageRange = \"21-30\";\n    } else if (age <= 40) {\n        ageRange = \"31-40\";\n    } else {\n        ageRange = \"41+\";\n    }\n    // Increment age range count\n    ageRanges[ageRange]++;\n\n    // Increment gender count\n    if (doc.gender === 'male') {\n        genderTotals.male++;\n    } else if (doc.gender === 'female') {\n        genderTotals.female++;\n    } else {\n        genderTotals.other++;\n    }\n\n    // Increment job status count\n    if (jobStatusTotals[doc.job]) {\n        jobStatusTotals[doc.job]++;\n    } else {\n        jobStatusTotals[doc.job] = 1;\n    }\n});\n\n\nmsg.payload = {\n    \"ageRanges\": ageRanges,\n    \"genderTotals\": genderTotals,\n    \"jobStatusTotals\": jobStatusTotals\n}; \n\n// Return the aggregated counts object\nreturn msg","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1120,"y":500,"wires":[["3f3ad8e528f5800b"]]},{"id":"ef5e8501b76cfec8","type":"join","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":830,"y":460,"wires":[["9cd9d88bb507cc49","6f472c26ef54f974"]]},{"id":"d3a842120a526a7f","type":"comment","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"Tranforming customer data","info":"","x":470,"y":380,"wires":[]},{"id":"6f472c26ef54f974","type":"change","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","rules":[{"t":"set","p":"data","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":1110,"y":380,"wires":[["a88a07f39e0e941d"]]},{"id":"a88a07f39e0e941d","type":"mongodb4","z":"977143edb097b685","g":"e0adf6e180ec1a7c","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"find","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":1270,"y":380,"wires":[["dd3fb62233d5477e"]]},{"id":"0e0129a95e24355c","type":"link in","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link in 1","links":["fd68d5c864a0e7c9"],"x":285,"y":460,"wires":[["ace58c34d1566f51"]]},{"id":"c7150b3b68fc34a0","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 2","mode":"link","links":["78176aee11393705"],"x":1545,"y":380,"wires":[]},{"id":"3f3ad8e528f5800b","type":"link out","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"link out 3","mode":"link","links":["ecfa23782d33d813"],"x":1255,"y":500,"wires":[]},{"id":"dd3fb62233d5477e","type":"function","z":"977143edb097b685","g":"e0adf6e180ec1a7c","name":"set payload","func":"let previously_stored_customer_data = Array.isArray(msg.payload) ? msg.payload : (msg.payload ? [msg.payload] : []);\nlet latest_customer_data = Array.isArray(msg.data) ? Array.from(msg.data) : (msg.data ? [msg.data] : []);\n\nif (latest_customer_data.length !== 0 && previously_stored_customer_data.length !== 0) {\n    let fullNameArray1 = previously_stored_customer_data.map(customer => customer.full_name);\n    let filtered_customer_data = latest_customer_data.filter(customer => !fullNameArray1.includes(customer.full_name));\n    msg.payload = [filtered_customer_data];\n    return msg\n} else {\n    // Case where there's no previously stored data\n    msg.payload = [latest_customer_data];\n    return msg\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1430,"y":380,"wires":[["c7150b3b68fc34a0"]]},{"id":"a0c7c3410ffb0e89","type":"mongodb4-client","name":"MongoDB Config","protocol":"mongodb+srv","hostname":"","port":"","dbName":"${DATABASE}","appName":"","authSource":"","authMechanism":"DEFAULT","tls":false,"tlsCAFile":"","tlsCertificateKeyFile":"","tlsInsecure":false,"connectTimeoutMS":"30000","socketTimeoutMS":"0","minPoolSize":"0","maxPoolSize":"100","maxIdleTimeMS":"0","uri":"${URI}","advanced":"{}","uriTabActive":"tab-uri-advanced"},{"id":"ac5e2cabb6251314","type":"group","z":"977143edb097b685","name":"","style":{"label":true},"nodes":["d6a4a19c23a0f42b","78176aee11393705","ecfa23782d33d813","dab90d6302b1c885","bc4afbc715e3b64d","d781431fed20d650","f19a1157e25b47df"],"x":254,"y":579,"w":592,"h":222},{"id":"d6a4a19c23a0f42b","type":"mongodb4","z":"977143edb097b685","g":"ac5e2cabb6251314","clientNode":"a0c7c3410ffb0e89","mode":"collection","collection":"customer_data","operation":"insertMany","output":"toArray","maxTimeMS":"0","handleDocId":false,"name":"","x":510,"y":680,"wires":[["bc4afbc715e3b64d"]]},{"id":"78176aee11393705","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 2","links":["c7150b3b68fc34a0"],"x":295,"y":680,"wires":[["d6a4a19c23a0f42b"]]},{"id":"ecfa23782d33d813","type":"link in","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"link in 3","links":["3f3ad8e528f5800b"],"x":295,"y":760,"wires":[["dab90d6302b1c885"]]},{"id":"dab90d6302b1c885","type":"file","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"","filename":"./customer_data_analytics","filenameType":"str","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":530,"y":760,"wires":[["d781431fed20d650"]]},{"id":"bc4afbc715e3b64d","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":720,"y":680,"wires":[]},{"id":"d781431fed20d650","type":"debug","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":740,"y":760,"wires":[]},{"id":"f19a1157e25b47df","type":"comment","z":"977143edb097b685","g":"ac5e2cabb6251314","name":"Loading data into file and database","info":"","x":520,"y":620,"wires":[]},{"id":"520f961e35d10da4","type":"group","z":"977143edb097b685","style":{"stroke":"#b2b3bd","stroke-opacity":"1","fill":"#f2f3fb","fill-opacity":"0.5","label":true,"label-position":"nw","color":"#32333b"},"nodes":["9b534cdc46dfc52a","52c6d1c11c84571c","ed6fc24b155aef33","af4bc1c2a6e6d020","572c04ca900af9d5","b64ddca6aab82cb2","a135a8ed2c447561"],"x":254,"y":839,"w":1372,"h":142},{"id":"9b534cdc46dfc52a","type":"ui-chart","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"chart","order":2,"chartType":"bar","category":"category","categoryType":"property","xAxisProperty":"","xAxisPropertyType":"msg","xAxisType":"category","yAxisProperty":"value","ymin":"","ymax":"","action":"replace","pointShape":"circle","pointRadius":4,"showLegend":false,"removeOlder":1,"removeOlderUnit":"3600","removeOlderPoints":"","colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"width":"13","height":8,"className":"","x":1550,"y":940,"wires":[[]]},{"id":"52c6d1c11c84571c","type":"function","z":"977143edb097b685","g":"520f961e35d10da4","name":"function 1","func":"let selectedDataForChart = global.get(\"selectedDataForChart\")\n// Assuming msg.payload is an object\nlet data = msg.payload[selectedDataForChart]\nlet result = [];\n\n// Loop through each key in the payload object\nObject.keys(data).forEach(key => {\n    result.push({ category: key, value: data[key] });\n});\n\nmsg.payload = result\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1380,"y":940,"wires":[["9b534cdc46dfc52a"]]},{"id":"ed6fc24b155aef33","type":"ui-dropdown","z":"977143edb097b685","g":"520f961e35d10da4","group":"1859e113313a5279","name":"","label":"Select Option:","tooltip":"","order":1,"width":0,"height":0,"passthru":false,"multiple":false,"options":[{"label":"Based on age group","value":"ageRanges","type":"str"},{"label":"Based on gender group","value":"genderTotals","type":"str"},{"label":"Based on job profile","value":"jobStatusTotals","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":360,"y":940,"wires":[["b64ddca6aab82cb2"]]},{"id":"af4bc1c2a6e6d020","type":"file in","z":"977143edb097b685","g":"520f961e35d10da4","name":"","filename":"./customer_data_analytics","filenameType":"str","format":"lines","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":950,"y":940,"wires":[["572c04ca900af9d5"]]},{"id":"572c04ca900af9d5","type":"json","z":"977143edb097b685","g":"520f961e35d10da4","name":"","property":"payload","action":"","pretty":false,"x":1190,"y":940,"wires":[["52c6d1c11c84571c"]]},{"id":"b64ddca6aab82cb2","type":"change","z":"977143edb097b685","g":"520f961e35d10da4","name":"store selected data in global context","rules":[{"t":"set","p":"selectedDataForChart","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":640,"y":940,"wires":[["af4bc1c2a6e6d020"]]},{"id":"a135a8ed2c447561","type":"comment","z":"977143edb097b685","g":"520f961e35d10da4","name":"Visualizing data on charts","info":"","x":490,"y":880,"wires":[]},{"id":"1859e113313a5279","type":"ui-group","name":"chart","page":"f10b4d0259e43aeb","width":"13","height":"1","order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"f10b4d0259e43aeb","type":"ui-page","name":"home","ui":"cb79bc4520925e32","path":"/","icon":"","layout":"grid","theme":"2c5d702b11de7dd1","order":1,"className":"","visible":true,"disabled":"false"},{"id":"cb79bc4520925e32","type":"ui-base","name":"My UI","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false},{"id":"2c5d702b11de7dd1","type":"ui-theme","name":"Theme Name","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"}}] @@ -223,7 +223,7 @@ While Node-RED is versatile, there are some limitations to consider while using - Advanced Features: Some advanced ETL features, like automated schema detection and sophisticated error handling, might require additional customization or external modules. - Data Governance: Node-RED does not inherently provide robust data governance and lineage tracking, which are often essential in enterprise ETL tools. -- Scalability: While Node-RED can handle many tasks effectively, it might not offer the same level of optimization for extremely large datasets compared to dedicated ETL tools. +- Scalability: While Node-RED can handle many heavy tasks, but it may not offer the same level of optimization for processing extremely large datasets compared to dedicated ETL tools. ## Additional resources From 71ff22da93cda7d3e7c56c06c69b617f54a00d01 Mon Sep 17 00:00:00 2001 From: "sumit shinde ( Roni )" <110285294+sumitshinde-84@users.noreply.github.com> Date: Mon, 17 Jun 2024 11:16:35 +0530 Subject: [PATCH 12/13] Apply suggestions from code review Co-authored-by: Zeger-Jan van de Weg --- src/blog/2024/06/using-node-red-as-an-etl-tool.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/blog/2024/06/using-node-red-as-an-etl-tool.md b/src/blog/2024/06/using-node-red-as-an-etl-tool.md index d72f602096..4ca442585a 100644 --- a/src/blog/2024/06/using-node-red-as-an-etl-tool.md +++ b/src/blog/2024/06/using-node-red-as-an-etl-tool.md @@ -1,7 +1,7 @@ --- -title: Using Node-RED as an ETL Tool. -subtitle: A Step-by-Step Guide on How to Use Node-RED as an ETL Tool. -description: Learn how to utilize Node-RED as an ETL (Extract, Transform, Load) tool, and explore its advantages and disadvantages in this context. +title: Using Node-RED as an ETL Tool +subtitle: A Step-by-Step Guide to use Use Node-RED for your industrial ETL Tool. +description: Learn how to utilize Node-RED as an ETL (Extract, Transform, Load) tool for your data industrial data ops. date: 2024-06-05 authors: ["sumit-shinde"] image: @@ -24,7 +24,7 @@ ETL (Extract, Transform, Load) is essential for integrating and analyzing data, ## Node-RED as an ETL tool -Node-RED is specifically used for building various types of IoT applications. During the development of such applications, we sometimes used Node-RED as an ETL is tool without even realizing it. For instance, when monitoring sensors across a facility, the process involves extracting data from sensors, transforming (cleaning and formatting) sensor data, and loading it into a database. There are thousands of other such examples. This demonstrates that Node-RED has already been adopted as an ETL tool at a certain level. +Node-RED is specifically used for building various types of IoT applications. Data ops workload are part of these use-cases, and are often deployed without thinking of them as DataOps. For instance, when monitoring sensors across a facility, the process involves extracting data from sensors, transforming (cleaning and formatting) sensor data, and loading it into a database. There are thousands of other such examples. *Note: We have mentioned only a few nodes that can be used in the ETL process, but there are thousands of other nodes that you can explore yourself by visiting the [Node-RED Nodes Library](https://flows.nodered.org/search?type=node)* From 75b3f8122102d6bc9f973fe5bad60c6b9a614274 Mon Sep 17 00:00:00 2001 From: "sumit shinde ( Roni )" <110285294+sumitshinde-84@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:40:11 +0530 Subject: [PATCH 13/13] Update using-node-red-as-an-etl-tool.md --- src/blog/2024/06/using-node-red-as-an-etl-tool.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/blog/2024/06/using-node-red-as-an-etl-tool.md b/src/blog/2024/06/using-node-red-as-an-etl-tool.md index 4ca442585a..b6888e58ff 100644 --- a/src/blog/2024/06/using-node-red-as-an-etl-tool.md +++ b/src/blog/2024/06/using-node-red-as-an-etl-tool.md @@ -14,13 +14,15 @@ tags: - business intelligence --- -ETL (Extract, Transform, Load) is essential for integrating and analyzing data, helping businesses unlock detailed insights. You already know Node-RED for its user-friendly approach to creating IoT applications, but did you know it can also be a powerful tool for ETL tasks? When IBM published a blog about using Node-RED for ETL, it caught a lot of attention and got people talking about its potential in this space. In this guide, we'll walk you through how to use Node-RED for ETL, sharing its strengths and weaknesses along the way. +ETL is the process data-driven organizations use to gather data from diverse sources and merge it to support discovery, reporting, analysis, and decision-making. While Node-RED is widely known as a low-code visual programming tool for building IoT applications, it also has significant potential for ETL tasks. This potential was highlighted when IBM published a blog about using Node-RED for ETL that sparked interest and discussion in the community. +In this guide, we'll walk you through how to use Node-RED as an ETL tool for your data industrial data ops, its strengths and weaknesses along the way. + ## What is ETL -[ETL](https://en.wikipedia.org/wiki/Extract,_transform,_load) (Extract, Transform, Load) is a fundamental process in managing data efficiently. It consists of three main stages: extraction, transformation, and loading. In the extraction phase, data is gathered from various sources such as databases, APIs, or files. Then, in the transformation stage, the data is converted into a format that is suitable for analysis by cleaning, filtering, and structuring it. Finally, in the loading stage, the transformed data is stored in a target database or data warehouse for further analysis and decision-making. ETL plays a significant role in ensuring that data is organized, consistent, and readily available for generating insights and making informed decisions in businesses and organizations. +[ETL](https://en.wikipedia.org/wiki/Extract,_transform,_load) (Extract, Transform, Load) is a fundamental process in managing data efficiently. It consists of three main stages: extraction, transformation, and loading. In the extraction phase, data is gathered from various sources such as SCADA systems, IoT devices, industrial sensors, APIs and more. In the transformation stage, the data is converted into a format that is suitable for analysis by cleaning, filtering, and structuring it. For example, this may involve converting raw sensor data into operational metrics. Aggregating time-series data over intervals (e.g., hourly, daily) to analyze trends and patterns in process performance. Filtering and analyzing event logs are for monitoring system performance and identifying potential issues. Finally, in the loading stage, the transformed data is stored in a target database or data warehouse for further analysis and decision-making. ETL plays a significant role in ensuring that data is organized, consistent, and readily available for generating insights and making informed decisions in businesses and organizations. ## Node-RED as an ETL tool @@ -30,11 +32,13 @@ Node-RED is specifically used for building various types of IoT applications. Da ### Extracting -Node-RED can extract data from various sources, including APIs, databases, local filesystems, and IoT devices using built-in nodes and community-contributed nodes. For example, the HTTP request node can be used to pull data from web services, while nodes for MySQL, MongoDB, and PostgreSQL can extract data from databases. Nodes for MQTT and Kafka can fetch data from message brokers. File nodes enable extraction of data from local filesystems, while different cloud nodes for platforms like AWS, GCP, and IBM Watson allow extraction of data from cloud storage services. Moreover, Node-RED running on edge devices can extract data from sensors connected directly to them. +Node-RED can extract data from various sources, including APIs, databases, local filesystems, and IoT devices using built-in nodes and community-contributed nodes. For example, the HTTP request node can be used to pull data from web services, while nodes for MySQL, MongoDB, and PostgreSQL can extract data from databases. Nodes for MQTT and Kafka can fetch data from message brokers. File nodes enable extraction of data from local filesystems, while different cloud nodes for platforms like AWS, GCP, and IBM Watson allow extraction of data from cloud storage services. Nodes for OPC-UA, Modbus, EtherNet/IP can be used to extract data from SCADA systems, PLCs, RTUs, and more. Moreover, Node-RED running on edge devices can extract directly extract data from devices. ### Transforming -Transforming data involves cleaning, structuring, and applying business rules. This can be done using function nodes with custom JavaScript, along with nodes like JSON, Split, Join, Change, CSV, and XML for parsing and formatting. +Transforming data involves cleaning, structuring, and applying business rules. This can be done using various nodes in Node-RED, including function nodes with custom JavaScript, along with nodes like JSON for parsing or stringifying JSON data, CSV for parsing CSV data into JSON or stringifying JSON into CSV, Split for breaking data into parts, Join for combining data and calculating total of data, Switch for conditional routing, Change for mapping and filtering data, Sort for ordering data, and XML for parsing and formatting. + +For example, imagine you have extracted sensor data objects from factory floor devices. Using Node-RED, you can convert that object into JSON using JSON nodes, route it based on device IDs with Switch nodes, filter out irrelevant sensor readings with Change nodes, apply custom business rules with Function nodes, sort it chronologically with Sort nodes and format it into XML with XML nodes for analysis and reporting. ### Loading