What is the best approach for adding variable rows to a Postgres junction table: should you concatenate a query string, utilize multiple queries, or explore alternative methods

Below is the code snippet for handling a variable-length list of tags and inserting data into the database:

// JSON object from req.body  
{
    "title": "title",
    "reference": "1213",
    "noteType": "type_1",
    "tags": [3, 4], 
    "text": "Lorem ipsum dolor sit amet."
}      

// Inserting data into notecards table and retrieving the ID
const response = await db.query(`insert into notecards( 
        title, 
        reference, 
        note_type, 
        main_text
    ) values ( 
        $1, 
        $2, 
        $3, 
        $4 
    ) returning notecard_id;`, [
        title,
        reference,
        noteType,
        text
])
const notecard_id = Number(response.rows[0].notecard_id);

// Adding records to junction table using the ID      
await db.query(`insert into tags_notecard( 
        tag_id, 
        notecard_id
    ) values 
        ( $1, $2 )
        ( $3, $4 );`, 
    [
        tags[0], notecard_id,
        tags[1], notecard_id 
])  

Since tags is dynamic in length, there are two possible approaches mentioned below:

  • Iterating over the tags array and calling separate queries for each record insertion.
  • Concatenating all values into a single query string and sending one parameterized query with multiple sets of values.

The first approach involves making multiple requests by looping through the tags array. This may lead to performance issues if there are constraints on input/output operations:

for (let i = 0; i < tags.length; i++) {
        await db.query(`insert into tags_notecard(tag_id, notecard_id) 
            values ( $1, $2 );`, [tags[i], notecard_id])
    }

Alternatively, the second approach requires constructing a concatenated query string and parameters list for efficient insertions into the junction table:

queryString = "insert into tags_notecard(tag_id, notecard_id) values"
paramsList = []
for (let i = 0, j =1 ; i < tags.length; i++, j+=2) {
     if (i !== tags.length - 1) {
          queryString = queryString + "($" + (j) + ", $" + (j+1)+ "),";
     } else {
         queryString = queryString + "($" + (j) + ", $" + (j+1)+ ");";   
     }
     paramsList.push(tags[i]);
     paramsList.push(notecard_id);
}
await db.query(queryString, paramsList);

Are these strategies efficient for scenarios where there are significant I/O constraints? Are there superior methods that can be employed in such situations?

Answer №1

To efficiently insert data into the database, I would utilize the jsonb data type along with specific functions to execute all the inserts in a single statement:

with input_data as (
  select '{
    "title": "title",
    "reference": "1213",
    "noteType": "type_1",
    "tags": [3, 4], 
    "text": "Lorem ipsum dolor sit amet."
  }'::jsonb as req_body
), insert_notecard as (
  insert into notecards (title, reference, note_type, main_text)
  select req_body->>'title', req_body->>'reference', req_body->>'noteType',
         req_body->>'text'
    from input_data
  returning notecard_id
), insert_tags as (
  insert into tags_notecard (tag_id, notecard_id)
  select t.tag_id::int, n.notecard_id
    from insert_notecard n
         cross join input_data i
         cross join lateral 
           jsonb_array_elements_text(i.req_body->'tags') t(tag_id)
  returning *
)
select * from insert_tags;

Explore working example here

Answer №2

Passing an array value as a parameter and using the unnest function in your query:

await database.query(
  `INSERT INTO tags_notecard(tag_id, notecard_id)
  SELECT unnest($1::int[]), $2;`, 
  [tagValues, cardId]
);  

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

Managing server errors when utilizing Observables

i am currently developing an Angular 2 application and part of it includes a login feature that utilizes this service. import { Http, Response } from '@angular/http'; import {Injectable} from '@angular/core'; import 'rxjs/add/op ...

Transferring pictures between folders

I am currently developing an Angular app that involves working with two images: X.png and Y.png. My goal is to copy these images from the assets folder to a specific location on the C drive (c:\users\images) whose path is received as a variable. ...

Ways to smoothly conclude a loading animation in real-time

I have a unique challenge of creating a loading animation using Adobe After Effects instead of CSS. The main goal is to develop an animation that continuously loops, but when the loading process stops, it ends with a distinct finishing touch. For instance, ...

"Explore the Hong browser designed specifically for enhanced Ajax functionality

I made the decision to revamp my new job by incorporating Ajax into the mix. Here is the code snippet I used to load pages: html <html> <head> <meta charset="utf-8"> <title>Untitled Document</title> <link rel="stylesheet" ...

Angucomplete-alt fails to display dropdown menu

On my website, there is a textarea where users need to input the name of a group project. The goal is to implement autocomplete functionality, so as users type in the project name, a dropdown menu will appear with suggestions of existing projects to assist ...

Processing data from a Buffer object using the .map() method and sending it as props to a component

As I work on my application, I encounter a challenge when dealing with a Buffer object that contains data from a file. My intention is to render the component Bar for each byte in this buffer and pass the byte as a prop. However, I am facing an issue with ...

Utilizing the power of Typescript in Express 4.x

I'm currently working on building an express app using TypeScript and here is what my code looks like at the moment: //<reference path="./server/types/node.d.ts"/> //<reference path="./server/types/express.d.ts"/> import express = requir ...

Tips on displaying a particular JSON attribute?

After starting with a JSON string, attempting to convert it into a JSON object and then trying to print a specific field (such as firstName), I am getting undefined. What could be the issue here? Thank you for your help! var string = '{"firstName ...

How can I remove a dynamically added <tr> element using jQuery?

I insert the <tr> into the <tbody> for (var i = 0 ;i < 12 ;i++){ $(`<tr><td>test</td></tr>`).appendTo('#songsTbody'); } within this HTML structure. <tbody id="songsTbody"> </tbody> ...

Converting a JSON array to C# and vice versa in Xamarin Forms

I've been struggling to send a C# object as JSON array to an API endpoint. I feel like I'm going crazy trying to solve these issues. Here's a sample of the JSON data: Array ( [user_id] => 0002323445635 [order] => {"order":{" ...

Disable the smooth scroll animation when transitioning between pages using the Link component in NextJS

Not sure if this is a new feature of Next.js, as I didn't encounter this issue in my previous Next.js project. When I reach the bottom of a page and try to navigate to another page, a scroll-to-top animation appears on the destination page. I want to ...

Using Node and Express to Serve Multiple Rendered Views in a Single Response

I'm making an AJAX request and I want to receive a JSON response containing multiple partial views that I can use to update different sections of my page. For example: { "searchResults": "<div>Some HTML string</div>", "paginationB ...

Pass information from a child component to a parent component within a React.js application

Using the Semantic-UI CSS Framework, I have implemented a dropdown menu and want to be able to select an item from it and identify which item has been selected. While I can determine the selected item within the child component and set its state, I am faci ...

Tips for invoking or triggering the Ajax change function when there is only a single option available

<select class="custom-select custom-select-sm mb-3" required="true" id="sel_block"> <option value="0">Select Block From Here</option> <?php // Fetch Blocks $sql_block = "SELECT * FROM blocks WHER ...

When accessing a method exposed in Angular2 from an external application, the binding changes are lost

In my code, I have a method that is made public and accessible through the window object. This method interacts with a Component and updates a variable in the template. However, even after changing the value of the variable, the *ngIf() directive does not ...

What is the best way to deal with a "Access to restricted URI denied" error in JavaScript while utilizing XMLHttpRequest?

Here is some code I am working with: var req = new XMLHttpRequest(); req.onload = function(){ if (req.status === "200"){ doSomethingWithTheReceivedData(); } else { alert("Error msg"); } }; When running index.html directly ...

JavaScript code for opening and closing buttons

I created a button that successfully opens, but I am struggling to figure out how to close it. Can someone assist me with this? Additionally, I have one more query: How can I remove the border when the button is clicked? document.getElementById("arrowb ...

Building interactive web forms with real-time validation using CodeIgniter

I'm looking for a way to use ajax (jquery library) to validate my forms. Specifically, I have a form that requires a minimum password length of 6 characters. Currently, I have implemented the validation rule as follows, $this->form_validation-> ...

What is preventing my boolean from being altered?

Creating a basic calculator that can handle single-digit arithmetic. The current code is incomplete and redundant, so please avoid commenting on that. <!doctype html> <html> <head> <title>JavaScript Learning Zone</title> ...

Retrieving data using a class in an AJAX form submission

I am attempting to use AJAX to submit an HTML form. Here is my HTML: <form class="lyrics"> <input type="text" value="" id="song" name="song"> <button type="submit" class="btn btn-info lirik">lyrics</button> </form> ...