數(shù)據(jù)庫結構
商品相關的表比較多,而且都是多對多關聯(lián)
列表查詢
先看下界面棕硫,可以通過商品名稱髓涯、商品編碼、商品分類哈扮、商品的上下架狀態(tài)和售罄狀態(tài)查詢
這些屬性涉及兩個表纬纪,其中yoshop_goods 包含查詢商品的基本屬性,但商品和分類分類是多對多關系滑肉,要通過 yoshop_goods_category_rel 這個關聯(lián)表查詢
增加一個sqlbuilder節(jié)點包各,根據(jù)前端查詢的參數(shù)組裝對應sql
(function(query) {
var {listType = 'all', goodsName='', goodsNo='', categoryId=''} = msg.req.query
var q = query.from("yoshop_goods").where({
"store_id": msg.store_id,
"is_delete": 0
})
if (goodsName) q.where("goods_name", 'like', `%${goodsName}%`)
if (goodsNo) q.where("goods_no", 'like', `%${goodsNo}%`)
if (listType == 'sold_out') q.where("stock_total", 0)
if (listType == 'on_sale') q.where("status", 10)
if (listType == 'off_sale') q.where("status", 20)
if (parseInt(categoryId)) {
q.whereExists(function() {
this.from('yoshop_goods_category_rel')
.whereRaw('yoshop_goods_category_rel.goods_id = yoshop_goods.goods_id')
.where("category_id", categoryId)
})
}
return q
})(query)
因為需要根據(jù)每個篩選條件是否傳值來拼sql,這里用閉包的方式處理
在處理根據(jù)商品分類查詢時赦邻,用到了exists子查詢
保存代碼并部署髓棋,在界面根據(jù)不同條件查詢,可以看到后臺打印的調試sql和接口返回的數(shù)據(jù)
但實際上前端代碼會報錯惶洲,因為只返回了列表數(shù)據(jù)按声,缺少分頁的信息
分頁查詢
涉及到分頁的table,前端需要的數(shù)據(jù)結構大概是這樣的
{
"code": 0,
"message": "success",
"data": {
"list": {
"current_page": 1,
"last_page": 1,
"per_page": 15,
"total": 1,
"data": [
{
"goods_id": 3
"...": "..."
}
]
}
}
}
系統(tǒng)中大量頁面都用到了分頁查詢恬吕,我們先建立一個分頁查詢的子流程
思路很簡單
1签则、先根據(jù)查詢的sql,把 SELECT 和 FROM 之間的內容替換為 COUNT(*)铐料, 查詢出該查詢語句命中的總行數(shù)
PS:只處理最普遍的情況渐裂,沒有對性能進行優(yōu)化,比如去掉 sql 里的 ORDER BY 語句等
msg.topic = msg.topic.trim().replace(/(select)\s+(.*?)\s+(from\s+)(.*)/img, "$1 COUNT(*) AS _count $3 $4")
2钠惩、根據(jù)記錄總數(shù)柒凉,和每頁的查詢行數(shù),計算總頁數(shù)
這里的 msg.paginate 是按前端需要的結構組裝的
const {page=1, pagesize = 15} = msg.req.query
const per_page = parseInt(pagesize) || 10
const total = msg.payload[0]._count
msg.paginate = {
current_page: parseInt(page) || 1,
last_page: Math.ceil(total / per_page),
per_page,
total
}
return msg;
3篓跛、根據(jù)前端傳遞的page和per_page參數(shù)膝捞,計算本次查詢的數(shù)據(jù),起始位置愧沟,拼到查詢sql后
const {current_page, per_page} = msg.paginate
const offset = (current_page - 1) * per_page
msg.topic = msg.sql + ` LIMIT ${offset}, ${per_page}`
return msg;
4蔬咬、最后組裝返回的數(shù)據(jù)
商品明細查詢
商品明細涉及的表很多鲤遥,參考最上面示意的er圖……
接口返回的結構參考下面截圖,基本上和商品關聯(lián)的信息都需要查詢出來了
下面拆解下接口的處理流程
1林艘、首先根據(jù)id查詢商品信息
2盖奈、查詢到商品后,就是分別查詢關聯(lián)的圖片狐援、分類钢坦、服務承諾、規(guī)格啥酱、sku等數(shù)據(jù)场钉,并組裝到一起返回前端
這里的每個查詢都很簡單,但每個查詢之間沒有太大關聯(lián)懈涛,如果按串行的方式,把一大坨拼湊到一起就會很難看泳猬。
出于審美批钠,到市場找了個join-wait的插件,該插件每次接收到消息后得封,會判斷是否在等待列表中埋心,如果等待的消息全部到達后,把消息進行合并處理忙上,并發(fā)送到下游節(jié)點
PS:支持指定消息到達的順序拷呆,支持超時
編排完的流程長這樣
小結
1、有一說一疫粥,knex還是偏底層茬斧,處理復雜的關聯(lián)查詢能力比較弱。類似的場景梗逮,截一段用laravel實現(xiàn)的代碼项秉,可以直觀看到兩種方式的差別
后面等有時間了把 knex 換成 Prisma 和 Sequelize 試下
2、從流程編排角度看慷彤,node-red某種程度實現(xiàn)了邏輯的所見即所得娄蔼,至少不需要額外寫注釋了