Condense items into objects and arrays when the Express query yields multiple objects in a many-to-many query

I have a situation where my SQL queries are returning multiple objects due to a many-to-many mapping in express. I am in search of a tool that can help me simplify these common objects by nesting arrays of objects within them.

SELECT *
FROM User
LEFT JOIN UserAddress ON UserAddress.user_id = User.user_id
LEFT JOIN Address ON Address.address_id = UserAddress.address_id;

When we execute this query, the response looks something like:

[
  {
    "user_id": 1,
    "name": "test name",
    "address_id": 1,
    "address": "1234 address way"
  },
  {
    "user_id": 1,
    "name": "test name",
    "address_id": 2,
    "address": "5678 new address"
  },
  {
    "user_id": 2,
    "name": "diff name",
    "address_id": 1,
    "address": "1234 address way"
  }
]

What I am aiming for is to transform this array using a JavaScript tool so it resembles the following structure:

[
  {
    "user_id": 1,
    "name": "test name",
    "address": [
      {
        "address_id": 1,
        "address": "1234 address way"
      },
      {
        "address_id": 2,
        "address": "5678 new address"
      }
    ]
  },
  {
    "user_id": 2,
    "name": "diff name",
    "address_id": 1,
    "address": "1234 address way"
  }
]

However, I am uncertain about what this transformation process is formally called or if there exists a specific tool that can facilitate this operation?

Answer №1

Here is a versatile solution that allows you to specify the data you want to collate and how you want it structured. This function utilizes a Map object to assist in organizing the data based on a specified key (user_id in this case):

function collateData(sourceArray, keyName, collectionName, collectionFields) {
    let collection = new Map();
    for (let item of sourceArray) {
        let targetObj = collection.get(item[keyName]);
        if (!targetObj) {
            targetObj = Object.assign({}, item);
            // Remove the properties being collected
            for (let field of collectionFields) {
                delete targetObj[field];
            }
            targetObj[collectionName] = [];
            collection.set(item[keyName], targetObj);
        }
        
        let collectedObj = {};
        // Copy over the fields being collected
        for (let field of collectionFields) {
            collectedObj[field] = item[field];
        }
        
        targetObj[collectionName].push(collectedObj);
    }
    
    // Convert Map to final array
    return Array.from(collection.values());
}

This approach always stores address fields in an array format for consistency, even when there's only one address (resulting in an array of length 1). This simplifies data handling for users as they can reliably access the address information without complex logic to handle differing formats.

An example usage scenario with sample data:

let data = [
  {
    "user_id": 1,
    "name": "test name",
    "address_id": 1,
    "address": "1234 address way"
  },
  {
    "user_id": 1,
    "name": "test name",
    "address_id": 2,
    "address": "5678 new address"
  },
  {
    "user_id": 2,
    "name": "diff name",
    "address_id": 1,
    "address": "1234 address way"
  }
];

let result = collateData(data, "user_id", "address", ["address", "address_id"]);
console.log(result);

If you prefer not to have single-element arrays, you can perform post-processing to extract individual elements:

// Function remains the same, only slight adjustment at the end for post-processing

let result = collateData(data, "user_id", "address", ["address", "address_id"]);

// Post-processing to remove single-element arrays
for (let item of result) {
    let array = item["address"];
    if (array.length === 1) {
        delete item["address"]; // Remove array
        Object.assign(item, array[0]); // Copy fields back to main object
    }
}

console.log(result);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What could be causing the malfunction of this particular express middleware error handling system?

Currently, I am working on implementing error handling for Express globally and I encountered an issue while following the documentation provided in this link. The example code snippet given is as follows: app.use((err, req, res, next) => { console.l ...

Is there a method to prevent the json file from being constantly overwritten?

After running this code, I noticed that even when inputting a different userId, it still ends up overwriting the existing user instead of adding a new one as intended. const user = userId; const userObj = {[user]:valueX}; words.users = userObj; f ...

Creating a mesh parallel to the xy-plane in Three.js

Looking to brush up on my CG fundamentals. How can I create a mesh (such as a circle) that is perfectly parallel to the xy-plane in the direction the camera is facing? For instance, I want it to be normal to the direction the camera is facing and not tilt ...

Retrieving text from Node.js with the help of regular expressions

I need to extract testcase ids from a list of testcases with titles. Each title includes an id and a description. I want to extract only the id. Here are some examples: TC-ABC-98.1.010_1-Verify the layout credit page TC-RegPMP-1.1.001_2-Verify the [MangerD ...

When executing a Javascript POST request to a PHP script, it succeeds when running on

I have a simple code that works fine on my website when the PHP file is linked as "/phpcode.php", but it fails to retrieve data when I place the JavaScript request on another site and use the full link. I am currently using GoDaddy as my hosting provider. ...

Ionic utilized the $http service and was unexpectedly triggered two times

$scope.login = function(email,password){ $http({ method: 'POST', url: 'http://example.com/login', headers: { 'owner': $rootScope.secret }, data: {email:email, password:password } }).then(function successCallback(response) { co ...

Validating alpha-numeric passwords with JavaScript

I created a JavaScript function to validate if a password is alphanumeric. However, I am facing an issue where the alert message is not being displayed when the password is not alphanumeric. Below is my code snippet: if (!input_string.match(/^[0-9a-z]+$ ...

retrieve the timestamp when a user initiates a keystroke

Seeking assistance from the community as I have been struggling with a problem for days now. Despite searching on Google and Stack Overflow, I haven't found a solution that works for me. My web application features an analog clock, and I need to capt ...

What is the best way to display all mysql rows in Node.js using handlebars templating?

Here is the code snippet I used to share only the first row (jack) from MySQL: node: const express = require("express"); const app = express(); app.set("view engine","hbs") const mysql = require("mysql") const db = m ...

Ensure that the GraphQL field "x" with type "[User]" includes a selection of subfields. Perhaps you intended to specify "x{ ... }" instead

I am encountering an issue while attempting to execute the following simple query: {duel{id, players}} Instead, I received the following error message: Field "players" of type "[User]" must have a selection of subfields. Did you mean & ...

How to show line breaks in MySQL text type when rendering in EJS

In my MySQL table, I have a column called PROJ_ABOUT with the type TEXT. I have inserted several rows into this column and now I am trying to display this information in my Express.js app using the ejs engine. <h2>About project</h2> <p> ...

Integrating objects into the <select> element through the combination of C#, JavaScript, and HTML connected to a SQL

Can someone assist me in resolving this issue? I am trying to populate an HTML element with database fields using C# and JavaScript, but so far my code is not producing any output. I have also attempted to include a button that calls the "loadGrp" function ...

A comprehensive guide on verifying user authentication and confirming sessionID creation using ReactJs and ExpressJs

I've successfully implemented a Nodejs application that generates a session upon user authentication. I have noticed that Expressjs stores the sessionID in an HttpOnly cookie, while the actual session information is stored server-side. My question no ...

Sending a JWT token to a middleware with a GET request in Express Node.js - the proper way

Struggling with Js and web development, I've scoured the web for a solution to no avail... After completing a project for a small lab, my current challenge is creating a login page and generating a web token using JWT... I successfully created a use ...

Issue with querying and ordering products in Django using Python when passing values through the GET request

I have been working on a project where I need to filter products and sort them by price in ascending and descending order. Here is the code snippet from my view: def is_valid_queryparam(param): return param != '' and param is not None def f ...

Issues with fetching data using Axios API in an Express.js Node.js environment

client const { response } = await axios.create({ baseURL: `http://127.0.0.1:5000/api` }).post( "/seller/login", { sellerMobile, sellerEmail, password }, headers: { 'Content-type': 'application/json&apo ...

The system cannot locate the module: Unable to find '@reactchartjs/react-chart-2.js'

I've been working on implementing this chart using the npm module called react-chartjs-2. I followed these steps to install the module: Ran the command: npm install --save react-chartjs-2 chart.js As a result, my package.json file now looks like th ...

Maintain the property characteristics (writable, configurable) following the execution of JSON.parse()

Imagine a scenario where an object is created elsewhere and passed to my module. It could have been generated on the server in node.js, or perhaps in a different module where it was then serialized using JSON.stringify() for transmission (especially if it ...

Storing the return value of a function call in a variable in node.js

I am currently working on developing a node.js application that is able to take a URL as an input and then provide the correct database connection string. Here you can see my genericServer.js file where I have implemented this functionality. Additionally, ...

Updating Values in Nested Forms with Angular Reactive Form

I have been grappling with a form setup that looks something like this: itemEntities: [ {customisable: [{food: {..}, quantity: 1}, {food: {..}, quantity: 5}]}, {customisable: [{food: {..}, quantity: 0}]}, ] My challenge lies in trying to u ...