简体   繁体   中英

Sequelize Many to Many Query Issue

So, I have an existing MySQL database that I'm trying to connect to with Sequelize in Node that has a products table, a categories table and a categories_products table. What I want to do is return products, with each product containing all of the categories it belongs to. Here's what I've got:

// Declare Product Model
const Product = sequelize.define('products', {
    name: Sequelize.STRING,
    description: Sequelize.STRING,
    single_price: Sequelize.BOOLEAN,
    oz_price: Sequelize.FLOAT,
    half_price: Sequelize.FLOAT,
    quarter_price: Sequelize.FLOAT,
    eigth_price: Sequelize.FLOAT,
    gram_price: Sequelize.FLOAT,
    unit_price: Sequelize.FLOAT
},
{
    underscored: true
});

// Declare Category Model
const Category = sequelize.define('categories', {
    name: Sequelize.STRING,
    parent_id: Sequelize.INTEGER,
    picture_file_name: Sequelize.STRING
},
{
    underscored: true
});

// Join Table
const ProductCategory = sequelize.define('categories_products', {
    product_id: Sequelize.INTEGER,
    category_id: Sequelize.INTEGER,

}, {  
    timestamps: false,
    underscored: true
});

// Do this because there is no id column on ProductCategory table
ProductCategory.removeAttribute('id');

Category.hasMany(Category, { as: 'children', foreignKey: 'parent_id' });

ProductCategory.belongsTo(Product);
ProductCategory.belongsTo(Category);
Product.hasMany(ProductCategory);
Category.hasMany(ProductCategory);

Using this setup, I query as follows:

Product.findAll({
    include: [{
        model: ProductCategory,
        include: [ Category ]
    }],
    where: { active: true },
    limit: 10
}).then(prods => {
    res.send(prods);
}).catch(err => {
    res.status(500).send(err);
});

I get back my products and each one has an array of categories, BUT each product only shows a max of one category. I have products that should have many categories, but it only shows the first.

Am I missing something? Any help would be greatly appreciated.

I think you should use belongsToMany association here.

You can define association like this

Product.belongsToMany(Category, { through: ProductCategory, foreignKey: 'product_id' });
Category.belongsToMany(Product, { through: ProductCategory, foreignKey: 'category_id' });

and the query can be

Product.findAll({
  include: [Category]
}).then((res) => {
  console.log(res);
})

Though the questioner might have gotten the solution but I ran into this composite key table problem and this is the solution with code example. Notice the "through" keyword. That is what solves the association where you want to limit your findings to say a category as AbhinavD asked above. Your category id would go in the literal expression. Applies to findAll too.

const products = await Product.findAndCountAll({
        include: [Category],
        through: { where: { category_id: `${category_id}` } },
        attributes: [
          'product_id',
          'name',

        ],

        limit: limitPage,
        offset: offsett,
      });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM