Extract distinct information from PostgreSQL query output using JavaScript

Working with a PostgreSQL database, I utilize node.js along with the pg module to query data. However, the resulting array in my server-side Javascript code contains duplicate values due to the way the data is returned. The duplicates are a result of multiple INNER JOINS with independent tables. For example, a combination of A and B from one table (qa_layers) with C and D from another table (qa_cases), alongside a shared value E from yet another table (qa_settings) will be represented as:

| settings_name | layer_name | case_name |
| E             | A          | C         |
| E             | A          | D         |
| E             | B          | C         |
| E             | B          | D         |

To filter out unique data for each column as arrays with distinct values (e.g. [A, B] and [C, D] for layer_name and case_name), there are various approaches that could be taken. However, each method presents its own challenges unless there is a specific library or functionality that can simplify the process.

  1. One option is to parse the array from the database in Javascript, which may involve multiple loops but could be more manageable with the help of a suitable library.
  2. Alternatively, adjusting the PostgreSQL query to minimize parsing requirements might be beneficial. By structuring the resulting array with easily parsable objects, the parsing step could be less cumbersome. See the query below for reference.
  3. Another approach involves running multiple queries on the database to obtain the desired data. While this is deemed the least scalable solution, it may reduce overhead compared to parsing an array after executing multiple individual queries.

My PostgreSQL query:

SELECT run.id, settings.name AS settings_name, layer.name AS layer_name, qa_case.name AS case_name FROM qa_runs AS run
    INNER JOIN qa_composites_in_run AS cr
        ON cr.run_id = run.id
    INNER JOIN qa_layers_in_composite AS lc
        ON lc.composite_name = cr.composite_name
    INNER JOIN qa_layers AS layer
        ON layer.name = lc.layer_name
    INNER JOIN qa_cases_in_run AS case_run
        ON case_run.run_id = run.id
    INNER JOIN qa_cases AS qa_case
        ON qa_case.name = case_run.case_name
    INNER JOIN qa_settings AS settings
        ON settings.name = run.settings_name
WHERE run.id IN (27,28,29);

Current JavaScript array output:

[
    {
        "id": 29,
        "settings_name": "Test Default",
        "layer_name": "OpenStreetMapService",
        "case_name": "VisitLondon"
    },
    ...
]

Desired JSON structure:

[
    {
        "id": 27,
        "settings_name": "QA Default",
        "layer_names": [
            {
                "layer_name": "OpenStreetMapService"
            },
            ...
]

Answer №1

One effective approach would be to handle this manipulation within PostgreSQL itself, where you can construct and return a JSON object containing your nested data instead of relying on a join relation.

This task can be accomplished quite smoothly using the JSON support available in versions 9.3 and above. While I cannot provide a specific query conversion without access to sample data and schema, I recommend starting with functions like json_agg and row_to_json. Additionally, exploring related questions that mention these functions could be beneficial for your implementation.

For instance, consider the following basic example:

CREATE TABLE parent(
    id integer primary key,
    parentdata text
);

CREATE TABLE child(
    id integer primary key,
    parent_id integer not null references parent(id),
    childdata text
);

INSERT INTO parent(id, parentdata) VALUES 
(1, 'p1'), (2, 'p2'), (3, 'p3');

INSERT INTO child(id, parent_id, childdata)
VALUES
(10, 1, 'c1_10'),
(20, 2, 'c2_20'),
(21, 2, 'c2_21');

SELECT row_to_json(toplevel, true)
FROM (
  SELECT p.id, p.parentdata, json_agg(c) AS children 
  FROM parent p 
  LEFT OUTER JOIN child c ON (p.id = c.parent_id) GROUP BY p.id
) toplevel;

The output from this example would resemble the following format:

{"id":1,
 "parentdata":"p1",
 "child":[{"id":10,"parent_id":1,"childdata":"c1_10"}]}
{"id":2,
 "parentdata":"p2",
 "child":[{"id":20,"parent_id":2,"childdata":"c2_20"}, 
 {"id":21,"parent_id":2,"childdata":"c2_21"}]}
{"id":3,
 "parentdata":"p3",
 "children":[null]}

In cases where de-duplication is necessary, ensure thorough specification of the ORDER BY clause in your SQL query so that rows are ordered correctly. This will facilitate processing the results sequentially in JavaScript, allowing you to eliminate duplicate entries based on entity IDs. Although this method requires PostgreSQL to sort the result set, the implementation is relatively straightforward and efficient.

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

Show side by side using javascript

My dilemma lies in having a set of cards that are meant to be displayed inline, but I have to initially hide them using "display: none". When a specific button is clicked, I aim to reveal these cards; however, upon doing so, each card seems to occupy its o ...

Setting a variable at an inappropriate time

function generateEnemyStats(enemy) { //javascript:alert(en[0]+'\n'+generateEnemyStats(en[0])+'\n'+en[0]) with (Math) { enemy[1]=round(enemy[1]*(.5+random())) enemy[2]=round(enemy[2]*(1+random())) for (var stat=0; stat& ...

Eliminating ^M characters from the output before adding it to a file using nodejs

I'm currently working on a node.js script where I capture console output and append it to a file. Take a look at the sample code snippet below: var appendToFile = function (output) { fs.appendFile('file.txt', output, 'utf8'); ...

Discover similar items within an array by utilizing async/await and promise.all

The value of filterdList.length always equals the total number of elements with the code provided below. As a result, this method consistently returns false because there is only one item in the table that matches the given name. async itemExists(name) : ...

Catalog of items in Mustache

I am currently working on generating HTML content using the mustache template engine. However, I have encountered an issue when trying to render a list of objects. Below is an example of my object: var Prod={ "Object1": { "name": "name1", "cat ...

Tips on utilizing createBrowserRouter within react along with react router-dom

Within my application, I am utilizing the BrowserRouter component to handle the rendering of routes and components. However, I am interested in incorporating a loader functionality, which is proving challenging with my current approach. <BrowserRouter&g ...

Passing an array from JavaScript to PHP and then storing it as a .json file

Query I am trying to pass an array to PHP and save it in a data.json file. However, the data.json file is being created but showing Null as output. I have spent about 2 hours on this code, checked numerous solutions on SO, but nothing seems to work. As I ...

Varying heights based on the screen size

Currently, I am in the process of designing my website and incorporating some wave elements to enhance the background. However, I've encountered some issues when resizing the screen. Specifically, the waves seem to shift with a space between them as t ...

How can I replace any non-alphanumeric characters in a string with an underscore using JavaScript or TypeScript?

There is a unique string generated from an external data source that I cannot manage. The system above me necessitates the IDs to adhere to this rule: "Field names should start with a letter and can solely consist of letters, numbers, or underscores (&apos ...

Learn how to effortlessly transfer a massive 1GB file using node and express

Encountering an issue when attempting to upload a large file to a node js instance using express, resulting in failure for files of significant size. The error message received is as follows: Error: Request aborted at IncomingMessage.<anonymous> (/s ...

Can Node.js Utilize AJAX, and if So, How?

Coming from a background in browser-based JavaScript, I am looking to dive into learning about node.js. From my current understanding, node.js utilizes the V8 engine as its foundation and offers server-side JavaScript capabilities along with pre-installed ...

Is it permissible to use Aloha editor GPL v.2 on a business website?

While researching the licensing of Aloha Editor, I came across some confusing information. I found a reference to another editor under LGPL: However, I couldn't find a clear answer on whether I can use Aloha JS code on a commercial website with GPL v ...

Clearing the ng-model value in a controller following an ng-change event

Is there a way to reset the ng-model value in the controller after an ngChange event without needing to use a directive? <div ng-repeat="i in items"> <!-- Some DOM comes here --> <select ng-model="i.avail" ng-change="changeAvail(i. ...

How can we show a varying number of textfields based on user selection using hooks and updating values dynamically through onChange events?

Currently, I am in the process of setting up a form that includes a Material UI select field ranging from 1 to 50. My challenge is how to dynamically display multiple textfields for "First Name and Last Name" using Hooks each time the user selects a number ...

Extract a selection from a dropdown menu in ReactJS

I have multiple cards displayed on my screen, each showing either "Popular", "Latest", or "Old". These values are retrieved from the backend. I have successfully implemented a filter option to sort these cards based on popularity, age, etc. However, I am u ...

Does the webworker function as a multi-thread?

For example: worker.postMessage(data1); worker.postMessage(data2); If there are multiple issues to be dealt with inside the web worker, would worker.postMessage(data2) block before completing data1? ...

"Upon subscribing, the object fails to appear on the screen

Why is the subscription object not displaying? Did I make a mistake? this.service.submitGbtForm(formValue) .subscribe((status) => { let a = status; // a = {submitGbtFrom: 'success'} console.log(a, 'SINGLE ...

Even when hovering out, jQuery maintains its hover styles

I have a jQuery script that displays a content box when hovering over a button, with the button's hover class activated. The goal is to maintain the hover styles on the button even when the mouse hovers inside the displayed content box. However, if th ...

Execute the script on the server, rather than in the browser

I have a script named "script.php" that automates the renewal process for user orders. To streamline this process, I created a button that, when clicked, triggers the execution of the script. Here's the button code: <?php echo Html::anchor('. ...

Navigating through different databases in PostgreSQL using SQL queries

Currently transitioning from SQL Server to Postgres, I am facing some syntax challenges while trying to create a query. My objective is to access two different databases on separate servers and join the datasets. In essence, one database contains user logi ...