nodejs sequelize 多表分頁查詢,返回結果包含兩表字段


goods和goodsSkus表

實現 兩表聯表查詢,並分頁。查詢結果中包含兩表中的字段,重點在於子表中返回字段 要寫在include中的attributes中,否則生成的sql無法執行

let queryParams={
  name: {
    [sequelize.Op.like]: `%$測試%`
  }
}

let skuQueryParams = {
  name: {
    [sequelize.Op.like]: `%$x%`
  }
}

 

daGoodsModel.hasMany(daGoodsSkuModel, {foreignKey: 'goods_id'});
 
var results = await daGoodsModel.findAll({
    order:      [['id','asc']],
    where:      queryParams,
    raw:        true,
    include:  [
        {
            model: daGoodsSkuModel, 
            attributes:[ 
                [sequelize.col('id'), 'sku_id'],
                [sequelize.col('name'), 'sku_name']
            ],
            where: skuQueryParams,
            require: true
        }
    ],
    attributes:  [
        'id','name'
    ],
    limit:  pageSize,
    offset: (pageIndex - 1) * pageSize
});

sku表返回字段放到include.attributes中生成的sql

SELECT `da_goods`.*, `da_goods_skus`.`id` AS `da_goods_skus.sku_id`, `da_goods_skus`.`name` AS `da_goods_skus.sku_name`
FROM (
	SELECT `da_goods`.`id`, `da_goods`.`name`
	FROM `da_goods` `da_goods`
	WHERE ((`da_goods`.`name` LIKE '%測試%'
			OR `da_goods`.`subtitle` LIKE '%測試%')
		AND `da_goods`.`deleted` = false
		AND (
			SELECT `goods_id`
			FROM `da_goods_sku` `da_goods_skus`
			WHERE `da_goods_skus`.`deleted` = false
				AND `da_goods_skus`.`name` LIKE '%x%'
				AND `da_goods_skus`.`goods_id` = `da_goods`.`id`
			LIMIT 1
		) IS NOT NULL)
	ORDER BY `da_goods`.`id` ASC
	LIMIT 0, 10
) `da_goods`
	INNER JOIN `da_goods_sku` `da_goods_skus`
	ON (`da_goods`.`id` = `da_goods_skus`.`goods_id`
		AND `da_goods_skus`.`deleted` = false
		AND `da_goods_skus`.`name` LIKE '%x%')
ORDER BY `da_goods`.`id` ASC;

 

sku返回字段放到attributes中

var results = await daGoodsModel.findAll({
	order:      [['id','asc']],
	where:      queryParams,
	raw:        true,
	include:  [
		{
		    model: daGoodsSkuModel, 
		    attributes:[],
		    where: skuQueryParams,
		    require: true
		}
	],
	attributes:  [
            'id','name',
            [sequelize.col('da_goods_skus.id'), 'sku_id'],
            [sequelize.col('da_goods_skus.name'), 'sku_name']
	],
	limit:  pageSize,
	offset: (pageIndex - 1) * pageSize
});

 生成的sql語句,如下語句執行失敗,會報 "Unknown column 'da_goods_skus.id' in 'field list'",因為標紅部分查詢不到

SELECT `da_goods`.*
FROM (
    SELECT `da_goods`.`id`, `da_goods`.`name`, `da_goods_skus`.`id` AS `sku_id`, `da_goods_skus`.`name` AS `sku_name`
    FROM `da_goods` `da_goods`
    WHERE ((`da_goods`.`name` LIKE '%測試%'
            OR `da_goods`.`subtitle` LIKE '%測試%')
        AND `da_goods`.`deleted` = false
        AND (
            SELECT `goods_id`
            FROM `da_goods_sku` `da_goods_skus`
            WHERE `da_goods_skus`.`deleted` = false
                AND `da_goods_skus`.`name` LIKE '%x%'
                AND `da_goods_skus`.`goods_id` = `da_goods`.`id`
            LIMIT 1
        ) IS NOT NULL)
    ORDER BY `da_goods`.`id` ASC
    LIMIT 0, 10
) `da_goods`
    INNER JOIN `da_goods_sku` `da_goods_skus`
    ON (`da_goods`.`id` = `da_goods_skus`.`goods_id`
        AND `da_goods_skus`.`deleted` = false
        AND `da_goods_skus`.`name` LIKE '%x%')
ORDER BY `da_goods`.`id` ASC;

 

 

正確返回結果 ,需要對返回字段進行處理,去掉 da_goods_skus

[
	{
		"id": 334,
		"name": "測試商品",
		"da_goods_skus.sku_id": 506,
		"da_goods_skus.sku_name": "xl"
	},
	{
		"id": 334,
		"name": "測試商品",
		"da_goods_skus.sku_id": 507,
		"da_goods_skus.sku_name": "x"
	}
]

 

但是上面node生成sql兩層嵌套,總感覺有問題,並且分頁查詢時如果與goods對應的sku表有多條數據,會返回所有sku,經查是sequelize對sql進行了優化,添加 subQuery:false,即可

代碼

var results = await daGoodsModel.findAll({
    order:      [['id','asc']],
    subQuery: false,
    where:      queryParams,
    include:  [
        {
            model: daGoodsSkuModel, 
            attributes:[],
            where: skuQueryParams
        }
    ],
    attributes:  [
        'id','name',
        [sequelize.col('da_goods_skus.id'), 'sku_id'],
        [sequelize.col('da_goods_skus.name'), 'sku_name'],
    ],
    limit:  pageSize,
    offset: (pageIndex - 1) * pageSize
});

 

生成SQL

SELECT `da_goods`.`id`, `da_goods`.`name`, `da_goods_skus`.`id` AS `sku_id`, `da_goods_skus`.`name` AS `sku_name`
FROM `da_goods` `da_goods`
    INNER JOIN `da_goods_sku` `da_goods_skus`
    ON `da_goods`.`id` = `da_goods_skus`.`goods_id`
        AND `da_goods_skus`.`deleted` = false
WHERE `da_goods`.`deleted` = false
ORDER BY `da_goods`.`id` ASC
LIMIT 0, 1;

 

 但是這樣返回的sku永遠只有一條,也就是goods有幾條,返回幾條記錄,對應的sku只返回一條

[{
    "id": 334,
    "name": "測試商品",
    "sku_id": 506,
    "sku_name": "xl",
},
{
    "id": 335,
    "name": "測試1",
    "sku_id": 508,
    "sku_name": "aaa",
}]

還是有問題

將sku返回字段放到include.attributes 解決問題

var results = await daGoodsModel.findAndCountAll({
    order:      [['id','asc'],[sequelize.col('da_goods_skus.id'),'asc']],
    subQuery:   false,
    where:      queryParams,
    include:  [
        {
            model: daGoodsSkuModel, 
            attributes:[                        
              [sequelize.col('id'), 'sku_id'],
                [sequelize.col('name'), 'sku_name']
            ],
            where: skuQueryParams
        }
    ],
    attributes:  [
        'id','name'
    ],
    limit:  pageSize,
    offset: (pageIndex - 1) * pageSize
});

 

返回結果

[{
    "id": 334,
    "name": "測試商品",
    "da_goods_skus": [
        {
            "sku_id": 506,
            "sku_name": "xl"
        },
        {
            "sku_id": 507,
            "sku_name": "x"
        }
    ],
},
{
    "id": 335,
    "name": "測試1",
    "da_goods_skus": [
        {
            "sku_id": 508,
            "sku_name": "aaa" } ]
}]

 

https://blog.zeromake.com/pages/sequelize-trap/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM