Java生鮮電商平台-推薦系統模塊的設計與架構
業務需求:
對於一個B2B的生鮮電商平台,對於買家而言,他需要更加快速的購買到自己的產品,跟自己的餐飲店不相關的東西,他是不關心的,而且過多無用的東西摻雜在一起,反而不便
於買家下單,用戶體驗也很差,嚴重的會因此丟了客戶。(客戶覺得太難用了。一般都就會放棄使用.)
對於賣家而言,他自己就調整下自己的商品的上架與下架,然后就是調整下自己商品的價格。(蔬菜類的商品會隨着市場的供求關系會有相應的波動.)
業務分析:
推薦系統:根據買家的行為習慣以及購買行為來推薦些他可能需要的東西的一套算法系統。
對於買家而言,數量來源於以下三個維度:
1. 購買記錄。-----買家實際下的訂單。
2. 收藏夾。 -----對於買家而言,收藏了某個商品,但是並沒購買的,我們認為他也會購買,屬於需要推送的數據之一。
3. 常用清單。----用戶最近一段時間購買的記錄,我們業務分析認為他一定會再次購買,因為相對一個餐館而言,它所做的菜從某種程度來說是一定的,所以購買的食材,也相對而言也是類似的。也就是說昨天買的,今天可能也會再次夠買,只是數量有所變化而言。
4. 同類推薦。 ----對於一個餐館而言,比如說小炒類似的餐館,那么很多類似小炒的餐館的所有菜應該也是類似的,也許存在不需要的,但是也存在可能需要的情況,也屬於我們的推薦系統中的。
5. 系統推薦。 ----對於一個剛注冊的買家而言,我們希望給他更好的業務體驗,那么在注冊的時候,他就會一定選擇一個所屬類別,根據類別,我們會把相應的類別的系統清單推薦出來,讓客戶一進來就感覺到這些他所需要的菜都好像是系統跟他量身定做的一樣。
根據以上的業務分析,我們理清楚了上述的所有維度,以下是數據庫的設計與思路:
1. 購買記錄。來源於訂單明細記錄表:
CREATE TABLE `order_item` ( `item_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵', `order_id` bigint(20) DEFAULT NULL COMMENT '訂單主表id,order_info表的order_id', `order_number` varchar(32) DEFAULT NULL COMMENT '唯一訂單號', `order_status` tinyint(4) DEFAULT NULL COMMENT '訂單項狀態,1為已提交訂單,2為取消訂單', `format_id` bigint(20) DEFAULT NULL COMMENT '商品規格的ID', `buyer_id` bigint(20) unsigned DEFAULT '0' COMMENT '買家ID', `seller_id` bigint(20) DEFAULT NULL COMMENT '所屬賣家ID', `delivery_type` tinyint(2) DEFAULT '1' COMMENT '配送類型,1為平台送,2.賣家自己送', `delivery_status` tinyint(2) DEFAULT '0' COMMENT '配送狀態,0 表示未收貨,1表示已收貨,送貨中,2表示已收貨,已送貨', `seller_status` tinyint(4) DEFAULT '0' COMMENT '賣家備貨狀態,0為備貨中,1為備貨完成,2為缺貨', `buyer_status` tinyint(2) unsigned DEFAULT '0' COMMENT '買家狀態,0待收貨,1為已收貨,2為換貨,3為退貨', `remark` varchar(255) DEFAULT NULL COMMENT '訂單項備注,由用戶提交訂單前填寫', `goods_number_old` decimal(12,2) DEFAULT NULL COMMENT '訂單初始商品數量', `goods_number` decimal(12,2) DEFAULT NULL COMMENT '商品的數量', `goods_price` decimal(12,2) DEFAULT NULL COMMENT '商品的單價', `goods_amount` decimal(12,2) DEFAULT NULL COMMENT '單項總金額', `delivery_money` decimal(12,2) DEFAULT '0.00' COMMENT '配送費用', `create_time` datetime DEFAULT NULL COMMENT '訂單創建時間', `delivery_receive_time` datetime DEFAULT NULL COMMENT '配送人員收貨時間', `delivery_finish_time` datetime DEFAULT NULL COMMENT '配送人員完成時間', `seller_finish_time` datetime DEFAULT NULL COMMENT '賣家完成時間', `buyer_finish_time` datetime DEFAULT NULL COMMENT '買家完成時間', `method_id` bigint(20) DEFAULT NULL COMMENT '加工方式ID', `delivery_id` bigint(20) DEFAULT NULL, PRIMARY KEY (`item_id`) ) ENGINE=InnoDB AUTO_INCREMENT=3424 DEFAULT CHARSET=utf8 COMMENT='訂單的子項目';
2. 收藏夾系統數據庫表:

說明:收藏夾比較簡單,某個商品ID,那個買家,什么時候收藏的。
3. 常用清單

說明:常用清單,維度也是對於商品而言,不是針對某一個店鋪,因為我們市場反饋給出的結論是買家關注的商品本身,而不是那個賣家。
4. 同類分析。
說明:數據來源於類似的餐館點。我們把餐館店分為幾種類型,在地推團隊來銷售產品的時候,其實是知道那個餐館的所屬類別的。
(客戶的類型,1為火鍋店,2為小餐館,3為中餐館,4,為燒烤)
5. 系統推薦。

說明:系統推薦,跟收藏夾,買家常用清單功能都很類似,不同點就在於業務的范圍與范疇。
剛注冊的用戶的常用清單的數據就來源於系統推薦的數據。
相關業務核心代碼如下:
1.注冊代碼中添加
/**
* 買家注冊,第二步完善資料
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/register/second/step", method = { RequestMethod.GET, RequestMethod.POST })
public JsonResult secondStepRegister(HttpServletRequest request, HttpServletResponse response,@RequestBody Buyer buyer)
{
logger.info("UsersController.secondStepRegister.seller:新增買家:" + buyer);
if (buyer == null)
{
return new JsonResult(JsonResultCode.FAILURE, "參數異常", "");
}
try
{
buyerService.updateBuyer(buyer);
//添加買家默認的常用清單
buyerService.insertBuyerCommon(buyer.getBuyerId(), buyer.getBuyerType(), buyer.getRegionId());
return new JsonResult(JsonResultCode.SUCCESS, "完善買家信息成功",buyer);
} catch (Exception e) {
logger.error("[UsersController][secondStepRegister] exception :", e);
return new JsonResult(JsonResultCode.FAILURE, "系統錯誤,請稍后重試", "");
}
}
2.常用清單方面
/**
* 我的常用清單
*/
@RequestMapping(value = "/my/commonList", method = { RequestMethod.GET, RequestMethod.POST })
public JsonResult commonList(HttpServletRequest request, HttpServletResponse response, Long userId) {
try {
List<CommonListVo> list = buyerService.getCommonList(userId);
return new JsonResult(JsonResultCode.SUCCESS, "查詢信息成功", list);
} catch (Exception ex) {
logger.error("[MyController][commonList] exception :", ex);
return new JsonResult(JsonResultCode.FAILURE, "系統錯誤,請稍后重試", "");
}
}
3。系統常用清單
說明:系統常用清單來源於后台管理人員人工添加
相應代碼如下;
/**
* 到新增頁面;
*/
@RequestMapping(value = "/toAdd", method = { RequestMethod.GET, RequestMethod.POST })
public String toAdd(HttpServletRequest request, HttpServletResponse response, Model model, SysCommonVo sysCommonVo,@ModelAttribute SearchGoodsVo sgv) {
// 獲取分頁當前的頁碼
int currentPageNum = this.getPageNum(request);
// 獲取分頁的大小
int currentPageSize = this.getPageSize(request);
//區域ID
Long areaId = sysCommonVo.getAreaId();
sgv.setAreaId(areaId);
sgv.setSearchStatus((short) 1);
sgv.setFormatStatus((short)1);
sgv.setSellerStatus((short)3);
List<SysCommonVo> sysCommon = sysCommonService.getSysCommon(sysCommonVo);
StringBuffer sb = new StringBuffer();
if(sysCommon.size()>0){
for (int i = 0; i < sysCommon.size(); i++) {
if(i != sysCommon.size()-1){
SysCommonVo sc = sysCommon.get(i);
sb.append(sc.getGoodsId());
sb.append(",");
}else {
SysCommonVo sc = sysCommon.get(i);
sb.append(sc.getGoodsId());
}
}
}
sgv.setGoodIds(new String(sb));
PageUtil paginator = goodsService.getPageResultByCommon(sgv, currentPageNum, currentPageSize);
model.addAttribute("paginator", paginator);
model.addAttribute("sgv", sgv);
model.addAttribute("sysCommonVo", sysCommonVo);
return "sys/common/addFrom";
}
說明:相對而言,這個代碼都是強依賴於數據庫,畢竟不可能很多時間都有人同時買菜與注冊。很多時候都是聯表查詢即可完成數據的分析與統計。
5.定時器代碼。(數據的系統推薦與個性化推薦都是系統采用定時器進行處理的。spring task)
相關代碼如下;

總結:所有的推薦系統的模型都類似我上面來的幾個維度的思考,需要根據自己的業務實際情況,自己分析與總結,至於是同步還是異步,還是定時器等等都是處理手段,
我這邊就采用了,同步與異步,包括定時器同時計算的過程,最終達到用戶的推薦效果。
Java開源生鮮電商平台-推薦系統模塊的設計與架構(源碼可下載),如果需要下載的話,可以在我的github下面進行下載。
相應的業務實際運行圖如下:






