Modifying the nested data organization in Sequelize

I'm looking to adjust the data structure retrieved from an ORM query involving four tables. The product and category tables have a many-to-many relationship, with the product_category table serving as a bridge. Additionally, there's a fourth table called department. Here is how the associations are set up:

// product
product.belongsToMany(models.category, {
      through: 'product_category',
      foreignKey: 'product_id'
});

// product_category
product_category.belongsTo(models.product, {
      foreignKey: 'product_id'
});
product_category.belongsTo(models.category, {
      foreignKey: 'category_id'
});

// category
category.belongsToMany(models.product, {
      through: 'product_category',
      foreignKey: 'category_id'
});
category.belongsTo(models.department, {
      foreignKey: 'department_id'
});

// department
department.hasMany(models.category, {
      foreignKey: 'department_id'
});

Using this table structure, an ORM query like the following can be used to retrieve products corresponding to a specific department_id:

const query = await product.findOne({
   where: { product_id: id },
   include: {
     model: category,
     attributes: ['category_id', ['name', 'category_name']],
     include: {
       model: department,
       attributes: ['department_id', ['name', 'department_name']]
     }
   },
   attributes: []
});

const data = query.categories;

The resulting JSON data looks like this:

"data": [
    {
        "category_id": 1,
        "category_name": "French",
        "department": {
            "department_id": 1,
            "department_name": "Regional"
        },
        "product_category": {
            "product_id": 1,
            "category_id": 1
        }
    }
]

My goal is to transform the above data to look like this:

"data": [
    {
         "category_id": 1,
         "category_name": "French",
         "department_id": 1,
         "department_name": "Regional"
    }
]

In order to achieve this transformation, I've explored two methods - modifying the SQL-based ORM query or manipulating the product value in JavaScript. While I wasn't familiar with the first method due to my SQL learning background, I attempted the second method.


First Attempt

I made two attempts, taking into account that the framework utilizes Koa.js. The first attempt looked like this:

const query = await product.findOne({
  where: { product_id: id },
  include: {
    model: category,
    attributes: ['category_id', ['name', 'category_name']],
    include: {
      model: department,
      attributes: ['department_id', ['name', 'department_name']]
    }
  },
  attributes: []
});

const data = query.categories.map(
      ({ category_id, category_name, department }) => ({
        category_id,
        category_name,
        department_id: department.department_id,
        department_name: department.department_name
      })
    );

ctx.body = data;

The resulting output was:

"data": [
    {
        "category_id": 1,
        "department_id": 1
    }
]

After observing some discrepancies, I slightly adjusted the return values which resulted in:

({ category_id, category_name, department }) => ({
        // category_id,
        // category_name,
        department_id: department.department_id,
        department_name: department.department_name
      })

This led to the following JSON response:

"data": [
    {
        "department_id": 1
    }
]

Alternatively, by omitting department_id and department_name:

({ category_id, category_name, department }) => ({
        category_id,
        category_name,
        // department_id: department.department_id,
        // department_name: department.department_name
      })

The JSON output was:

"data": [
    {
        "category_id": 1
    }
]

I couldn't find another way to manipulate the data.

Second Attempt

await product
.findOne({
  where: { product_id: id },
  include: {
    model: category,
    attributes: ['category_id', ['name', 'category_name']],
    include: {
      model: department,
      attributes: ['department_id', ['name', 'department_name']]
    }
  },
  attributes: []
})
.then(query => {
  const data = query.categories.map(
    ({ category_id, category_name, department }) => ({
      category_id,
      category_name,
      department_id: department.department_id,
      department_name: department.department_name
    })
  );

  ctx.body = data;
});

Both approaches yielded similar results, leaving me uncertain on how to proceed.


I tried mapping variables within nested arrays containing JSON data, which produced the desired outcome:

const data = {
  categories: [
    {
      category_id: 1,
      category_name: 'French',
      department: { department_id: 1, department_name: 'Regional' },
      product_category: { product_id: 1, category_id: 1 }
    }
  ]
};

const product = data.categories.map(
  ({ category_id, category_name, department }) => ({
    category_id,
    category_name,
    department_id: department.department_id,
    department_name: department.department_name
  })
);

console.log(product);

// [ { category_id: 1,
//    category_name: 'French',
//    department_id: 1,
//    department_name: 'Regional' } ]

Despite these efforts, I felt perplexed. How should I handle data obtained from a Sequelize query? Your guidance would be greatly appreciated.

Please inform me if my problem-solving approach is flawed or if you require further details on the model schema.

Answer №1

I approached this problem in a straightforward manner, resulting in a comprehensive solution. However, I believe there is room for improvement and welcome suggestions on the Best Way to enhance it.

const getProduct = () => {
  const a = query.categories[0];
  const b = a.get({ plain: true });
  const { category_id, category_name } = b;
  const { department_id, department_name } = b.department;

  return {
    category_id,
    category_name,
    department_id,
    department_name
  };
};

ctx.body = getProduct();

Here is the JSON data output:

"product": {
    "category_id": 1,
    "category_name": "French",
    "department_id": 1,
    "department_name": "Regional"
}

When running console.log(), the sequelize query will be displayed as dataValues: {}, (...). To effectively process the data, it is crucial to utilize the following method after storing the query in a variable:

data.get ({plain: true})

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 is the best way to incorporate a popover into a fullcalendar event displayed on a resource timeline in Vue while utilizing BootstrapVue?

I need help adding a popover to an event in a resource timeline using fullcalendar/vue ^5.3.1 in Vue ^2.6.11 with ^2.1.0 of bootstrap-vue. Although I found some guidance on Stack Overflow, the solution involving propsData and .$mount() doesn't feel l ...

Defining the signature of an unnamed function in TypeScript

Within my Express code, I have an anonymous function set up like this: app.use((err, req, res, next) => { // ... }); I am looking to specify the type of the function as ErrorRequestHandler (not the return type). One way to achieve this is by defining ...

Guide to retrieving data from a URL and storing it in a string variable with JavaScript

Attempting to retrieve the JSON data from a specific URL and store it in a variable. The code snippet below successfully loads the JSON into a div element: $("#siteloader").html('<object data="MYURL">'); However, the goal is to extract t ...

express.js does not properly support the app.get functionality

app.get('/:id', function (req, res){ UserModel.find({ user: req.params.id}, function (err, user){ if (err) throw err; console.log(user + '\n\n'); res.render('profile.ejs', { ...

JavaScript has thrown an error stating that the function in my jQuery script is undefined

I encountered an issue Uncaught TypeError: undefined is not a function in my jQuery script. Here is the code snippet: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link re ...

Assigning an array of objects within an AJAX request

I have a MediaObject object that includes: a Media object an array and a function called getMedia() When attempting to create a Media object and push it into the array inside the getMedia function after making an AJAX call, I encountered issues referenc ...

Is there a way to include multiple TinyMCE editors with unique configurations for each one?

Is it possible to incorporate multiple TinyMCE editors on a single page, each with its own distinct configuration settings? If so, how can this be achieved? ...

Can you specify the third argument sent to the listener?

Recently I delved into exploring the capabilities of the d3 framework. One thing that caught my attention was the presence of a third parameter in the event listener for v3. Despite always being 0, I couldn't find any explanation on its intended purpo ...

socket.io, along with their supporting servers

Can socket.io function separately from being the webserver? I prefer to utilize an external webserver, but in order for it to function properly I require /socket.io/socket.io.js. Is there a method other than duplicating[1] this file? I want to avoid comp ...

Struggling with adding headers in React application

When I try to include an h1 heading, either the heading doesn't show up if I comment out the buttons, or if I comment out the heading, then the buttons don't display. But when both are included, nothing is displayed. Any suggestions on how to fix ...

Customizing the Header Navigation in Vue App.vue Across Various Views

Struggling to find the best approach for managing a header navigation in Vue 2 using Vuex with VueRouter. The main issue is creating a dynamic 'header' type navigation in App.vue. <div id="nav"> <!--Trying to create a dynamic ...

`How to Merge Angular Route Parameters?`

In the Angular Material Docs application, path parameters are combined in the following manner: // Combine params from all of the path into a single object. this.params = combineLatest( this._route.pathFromRoot.map(route => route.params) ...

Develop an HTML table using either JSON or jQuery in Javascript

JavaScript is a bit of a mystery to me right now - I could really use some assistance in overcoming this obstacle that has me pulling my hair out! I'm struggling with constructing HTML code using JSON data. It's just not clicking for me at the m ...

Inspect the json data to find a specific value and then determine the corresponding key associated with

I am currently working with JSON data retrieved from which I am storing in a variable. Despite my limited experience with JSON/JS, I have been unable to find a solution through online searches. Here is the code snippet: function checkMojang() { var moj ...

Use a function on values that have corresponding keys in a separate array

I am working with a form.value object that looks like this: form.value = { "to_date": "2019-03-21T05:00:00.000Z", "from_date": "2019-03-13T05:00:00.000Z", "is_form": "" "errors":"" } Additionally, I have an array called filterArray: filterArray ...

Using Javascript to multiply strings

While working on the leetcode problem related to multiplication, I encountered an interesting issue. Given two non-negative integers num1 and num2 represented as strings, the task is to return the product of these two numbers, also in string form. However ...

Preventing Event Loop Blocking in Node.js: The Key to Streamlining Performance

I am currently working on developing two APIs using Express.js. The tasks for both APIs are quite straightforward. The first API involves running a for loop from 1 to 3,000,000, while the second API simply prints a string in the console. All the necessary ...

The save feature becomes dysfunctional after switching to the Material-UI dependency in a React project

After integrating the Material-UI dependency into my ReactJS code, I encountered an issue where the "save" functionality no longer works properly. Previously, when editing a task in my simple Todo list app, the new name would be saved successfully. However ...

Ways to prevent horizontal scrolling in an image

Currently, I am working on a scrolling animation page that is optimized for mobile devices. One issue I am encountering is when an element is larger than the screen size, such as when an image is wider than the mobile device. In this scenario, the user can ...

jQuery fails to recognize response

Can anyone figure out why my alert isn't functioning correctly? <script type="text/javascript"> function SubmitForm(method) { var login = document.form.login.value; var password = document.form.password.value; ...