电商推荐与风控 Demo 使用教程
交流图数据库技术?加入 Nebula 交流群请先填写下「你的 Nebula 名片」,Nebula 小助手会拉你进群~~
⚠️本文档中的图模型(点、边及属性)主要为演示图数据库在电商场景下的表达能力而设计,实际业务中可根据数据规模与查询需求按需简化或扩展。请勿直接照搬上述 Schema 作为生产环境定义,建议结合实际业务与数据量进行合理设计~
背景
在电商业务中,用户获取信息的成本越来越高,传统的基于热门商品或单一维度的推荐系统难以捕捉用户深层的购物偏好和商品之间的复杂关联。同时,刷单、薅羊毛等欺诈行为也呈现团伙化、隐蔽化的特点,传统规则引擎难以发现隐藏在复杂交易网络中的风险。
图数据库能够将用户、商品、店铺、订单、设备、IP 等实体以及它们之间的购买、浏览、物流、登录等关系构建成一个多维关联网络,并通过图遍历算法挖掘潜在购买意图、识别风险交易路径。
本 Demo 以电商智能推荐与风控为场景,建立包含用户、商品、订单、设备、IP 等实体的电商关联网络,并演示多种图查询,帮助产品和算法人员快速构建推荐逻辑和风控策略。
图模型设计
💡 在实际使用场景中,可对 Schema 进行相应修改与管理,为便于在线体验本 Demo 暂不支持。
首先创建图类型与图空间,并执行以下语句定义节点、边结构及属性:
CREATE GRAPH TYPE `ecommerce` AS {
-- 1. 核心交易实体
NODE `user` (:`user` {
`user_id` STRING PRIMARY KEY,
`user_name` STRING,
`city` STRING,
`level` STRING,
`register_time` ZONED DATETIME
}),
NODE `product` (:`product` {
`product_id` STRING PRIMARY KEY,
`product_name` STRING,
`category` STRING,
`brand` STRING,
`price` DOUBLE,
`color` STRING,
`specs` STRING
}),
NODE `shop` (:`shop` {
`shop_id` STRING PRIMARY KEY,
`shop_name` STRING,
`location` STRING,
`rating` DOUBLE
}),
NODE `order` (:`order` {
`order_id` STRING PRIMARY KEY,
`total_amount` DOUBLE,
`status` STRING,
`create_time` ZONED DATETIME
}),
-- 2. 风控实体
NODE `ip` (:`ip` {
`ip_address` STRING PRIMARY KEY,
`network_type` STRING,
`city` STRING
}),
NODE `device` (:`device` {
`device_id` STRING PRIMARY KEY,
`device_type` STRING,
`os` STRING
}),
NODE `address` (:`address` {
`address_hash` STRING PRIMARY KEY,
`full_text` STRING
}),
-- 3. 物流实体
NODE `logistics_station` (:`logistics_station` {
`station_id` STRING PRIMARY KEY,
`name` STRING,
`type` STRING
}),
NODE `logistics_event` (:`logistics_event` {
`event_id` STRING PRIMARY KEY,
`status_desc` STRING,
`occur_time` ZONED DATETIME
}),
-- 关系边定义
EDGE `sold_by` (`product`)-[:`sold_by`]->(`shop`),
EDGE `placed_order` (`user`)-[:`placed_order`{`pay_time` ZONED DATETIME}]->(`order`),
EDGE `contains` (`order`)-[:`contains`{`quantity` INT64, `unit_price` DOUBLE}]->(`product`),
EDGE `ship_to` (`order`)-[:`ship_to`]->(`address`),
EDGE `user_owned_by` (`user`)-[:`user_owned_by`{`is_default` BOOLEAN}]->(`address`),
EDGE `shop_owned_by` (`shop`)-[:`shop_owned_by`]->(`address`),
EDGE `generates_event` (`order`)-[:`generates_event`]->(`logistics_event`),
EDGE `at_station` (`logistics_event`)-[:`at_station`]->(`logistics_station`),
EDGE `bought_together` (`product`)-[:`bought_together`{`score` DOUBLE}]->(`product`),
EDGE `similar_to` (`product`)-[:`similar_to`{`similarity_score` DOUBLE, `model_version` STRING}]->(`product`),
EDGE `user_logged_from` (`user`)-[:`user_logged_from`{`login_time` ZONED DATETIME}]->(`ip`),
EDGE `user_used_device` (`user`)-[:`user_used_device`{`first_use_time` ZONED DATETIME, `last_use_time` ZONED DATETIME}]->(`device`),
EDGE `shop_logged_from` (`shop`)-[:`shop_logged_from`{`login_time` ZONED DATETIME}]->(`ip`),
EDGE `shop_used_device` (`shop`)-[:`shop_used_device`{`first_use_time` ZONED DATETIME}]->(`device`),
EDGE `viewed` (`user`)-[:`viewed`{`view_time` ZONED DATETIME, `duration_sec` INT64}]->(`product`),
EDGE `added_cart` (`user`)-[:`added_cart`{`add_time` ZONED DATETIME, `quantity` INT64}]->(`product`),
EDGE `favorited` (`user`)-[:`favorited`{`favor_time` ZONED DATETIME}]->(`product`),
EDGE `placed_from` (`order`)-[:`placed_from`{`order_time` ZONED DATETIME}]->(`ip`),
EDGE `placed_with` (`order`)-[:`placed_with`{`order_time` ZONED DATETIME}]->(`device`)
}
1. 节点类型
| 节点类型 | 标签 | 核心属性 |
|---|---|---|
| 用户 | user |
user_id (唯一标识), user_name (昵称), city (所在城市), level (会员等级), register_time (注册时间) |
| 商品 | product |
product_id (唯一标识), product_name (商品名称), category (类目), brand (品牌), price (售价), color (颜色), specs (规格参数) |
| 店铺 | shop |
shop_id (唯一标识), shop_name (店铺名称), location (经营地址), rating (店铺评分) |
| 订单 | order |
order_id (唯一标识), total_amount (订单总金额), status (订单状态), create_time (下单时间) |
| IP地址 | ip |
ip_address (IP值), network_type (网络类型: 住宅/机房/移动), city (IP归属地) |
| 设备 | device |
device_id (设备唯一标识), device_type (设备形态: 手机/PC/平板), os (操作系统) |
| 收货地址 | address |
address_hash (标准化地址哈希值), full_text (原始地址文本) |
| 物流站点 | logistics_station |
station_id (唯一标识), name (站点名称), type (类型: 仓库/分拨中心) |
| 物流事件 | logistics_event |
event_id (唯一标识), status_desc (状态描述), occur_time (事件发生时间) |
2. 边类型
| 边类型 | 起点 → 终点 | 说明 | 关键属性 |
|---|---|---|---|
sold_by |
product → shop |
商品所属店铺 | - |
placed_order |
user → order |
用户下单 | pay_time (支付时间) |
contains |
order → product |
订单包含商品 | quantity (购买数量), unit_price (成交单价) |
ship_to |
order → address |
订单配送地址 | - |
user_owned_by |
user → address |
用户拥有的收货地址 | is_default (是否默认地址) |
shop_owned_by |
shop → address |
店铺经营地址 | - |
generates_event |
order → logistics_event |
订单产生物流事件 | - |
at_station |
logistics_event → logistics_station |
事件发生的物流站点 | - |
bought_together |
product → product |
经常一起购买的商品 | score (共购置信度) |
similar_to |
product → product |
相似商品 | similarity_score (相似度分值), model_version (模型版本) |
user_logged_from |
user → ip |
用户登录IP | login_time (登录时间) |
user_used_device |
user → device |
用户使用过的设备 | first_use_time (首次使用时间), last_use_time (最后使用时间) |
shop_logged_from |
shop → ip |
店铺登录IP | login_time (登录时间) |
shop_used_device |
shop → device |
店铺使用过的设备 | first_use_time (首次使用时间) |
viewed |
user → product |
浏览商品 | view_time (浏览时间), duration_sec (停留时长) |
added_cart |
user → product |
加入购物车 | add_time (加购时间), quantity (加购数量) |
favorited |
user → product |
收藏商品 | favor_time (收藏时间) |
placed_from |
order → ip |
订单下单IP | order_time (下单时间) |
placed_with |
order → device |
订单下单设备 | order_time (下单时间) |
数据导入
💡 本 Demo 仅预置约 20 名用户、20 个商品、10 个店铺、30 个订单及数千条关联关系,实际导入时,数据量可达亿级。
以下为部分示例数据导入语句:
-- 导入用户节点(示例)
TABLE `t_user` { `user_id`, `user_name`, `city`, `level`, `register_time` } =
("u001", "ZhangWei", "Beijing", "gold", "2024-01-10T09:00:00 +0800"),
("u002", "LiNa", "Shanghai", "silver", "2024-01-15T10:30:00 +0800"),
...(此处省略其余 18 个用户数据)
USE `ecommerce`
FOR re IN `t_user`
INSERT (@`user` {`user_id`: re.`user_id`, `user_name`: re.`user_name`, `city`: re.`city`, `level`: re.`level`, `register_time`: CAST(re.`register_time` AS ZONED DATETIME)})
-- 导入商品节点(示例)
TABLE `t_product` { `product_id`, `product_name`, `category`, `brand`, `price`, `color`, `specs` } =
("p001", "iPhone 15 Pro", "Electronics", "Apple", 8999.0, "Black", "256GB"),
("p002", "MacBook Air M3", "Electronics", "Apple", 10999.0, "Silver", "16GB+512GB"),
...(此处省略其余 18 个商品数据)
USE `ecommerce`
FOR re IN `t_product`
INSERT (@`product` {`product_id`: re.`product_id`, `product_name`: re.`product_name`, `category`: re.`category`, `brand`: re.`brand`, `price`: re.`price`, `color`: re.`color`, `specs`: re.`specs`})
-- 导入店铺节点、订单节点、IP 节点、设备节点、地址节点、物流站点节点、物流事件节点
-- 以及各类关系边数据(sold_by、placed_order、contains、ship_to、user_owned_by、shop_owned_by、
-- generates_event、at_station、bought_together、similar_to、user_logged_from、user_used_device、
-- shop_logged_from、shop_used_device、viewed、added_cart、favorited、placed_from、placed_with)
-- 此处省略具体数据,结构与上述类似

关键查询示例
场景一:店内商品推荐(提升客单价)
目的:根据用户历史购买记录,推荐同一商家的其他商品,提升店内转化率与客单价。
USE `ecommerce`
MATCH pth1=(u@`user`{`user_id`:"u001"})-[@`placed_order`]-(o@`order`)-[@`contains`]-(p1@`product`)-[@`sold_by`]-(s@`shop`)-[@`sold_by`]-(p2@`product`)
WHERE p1.`product_id` <> p2.`product_id`
RETURN pth1

基于图的解释:该查询从用户 u001 节点出发,沿着 placed_order 边找到其订单,再通过 contains 边找到购买过的商品,然后沿着 sold_by 边找到商品所属店铺,最后反向找到该店铺销售的其他商品。图中展示了“用户→订单→商品→店铺→其他商品”的完整关联路径,实现了基于店铺的跨商品推荐。
场景二:相似商品推荐
目的:根据用户买过的商品,推荐离线计算好的相似商品,提升推荐多样性。
USE `ecommerce`
MATCH pth2=(u@`user`{`user_id`:"u001"})-[@`placed_order`]-(o@`order`)-[@`contains`]-(p1@`product`)-[@`similar_to`]-(p2@`product`)
RETURN pth2

基于图的解释:该查询从用户 u001 出发,找到其购买过的商品,再通过 similar_to 边直接跳转到相似商品节点。图中展示了“用户→商品→相似商品”的简洁路径,利用离线算法预计算的相似关系,实现毫秒级响应。
场景三:搭配购推荐
目的:根据用户买过的商品,推荐经常一起购买的商品,提升关联销售。
USE `ecommerce`
MATCH pth3=(u@`user`{`user_id`:"u001"})-[@`placed_order`]-(o@`order`)-[@`contains`]-(p1@`product`)-[@`bought_together`]-(p2@`product`)
RETURN pth3

基于图的解释:该查询从用户 u001 出发,找到其购买过的商品,再通过 bought_together 边跳转到经常与之搭配购买的商品节点。图中清晰展示了共现商品的关联关系,可用于“买了A的人也买了B”的场景。
场景四:基于浏览行为的推荐
目的:根据用户浏览行为,推荐相似或关联商品,覆盖未成交用户。
USE `ecommerce`
MATCH pth4=(u@`user`{`user_id`:"u005"})-[@`viewed`]-(p1@`product`)-[@`bought_together`]-(p2@`product`)
RETURN pth4

基于图的解释:该查询从用户 u005 出发,通过 viewed 边找到其浏览过的商品,再通过 bought_together 边推荐搭配购买的商品。图中将用户的前端行为信号引入推荐链路,适用于新用户或未下单用户的冷启动推荐。
场景五:协同过滤推荐
目的:根据用户加购行为,推荐“看过/加购此商品的人最终还买了什么”。
USE `ecommerce`
MATCH pth5=(u@`user`{`user_id`:"u001"})-[@`added_cart`]-(p1@`product`)-[@`contains`]-(o@`order`)-[@`placed_order`]-(u2@`user`)-[@`placed_order`]-(o2@`order`)-[@`contains`]-(p2@`product`)
WHERE u.`user_id` <> u2.`user_id` AND p1.`product_id` <> p2.`product_id`
RETURN pth5

基于图的解释:该查询从用户 u001 出发,找到其加购的商品,再找到购买过该商品的其他用户,最后找到这些用户购买的其他商品。图中展示了“用户→商品→其他用户→其他商品”的协同过滤路径,实现了基于用户行为相似度的推荐。
场景六:物流异常监控
目的:查看中转站涉及的所有订单及物流事件全貌,快速定位故障站点影响面。
USE `ecommerce`
MATCH pth6=(s@`logistics_station`{`station_id`:"ls001"})<-[@`at_station`]-(e@`logistics_event`)<-[@`generates_event`]-(o@`order`)-[@`generates_event`]->(e_all@`logistics_event`)
RETURN pth6

基于图的解释:该查询从物流站点 ls001 出发,反向找到经过该站点的所有物流事件,再找到产生这些事件的订单,最后展开订单的完整物流轨迹。图中展示了站点、事件、订单之间的双向关联,帮助运营人员快速评估故障站点的影响范围。
场景七:店铺自买自卖检测(刷单识别)
目的:检测商家与订单使用相同IP,疑似店铺自买自卖刷单。
USE `ecommerce`
MATCH pth7=(s@`shop`)-[@`shop_logged_from`]-(i@`ip`)-[@`placed_from`]-(o@`order`)-[@`contains`]-(p@`product`)-[@`sold_by`]-(s)
RETURN pth7

基于图的解释:该查询从店铺节点出发,找到店铺登录过的 IP,再找到通过该IP下单的订单,然后找到订单中的商品,最后确认商品是否属于该店铺。图中形成了一个“店铺→IP→订单→商品→店铺”的环状路径,清晰暴露了店铺自买自卖的刷单行为。
场景八:相同设备刷单检测
目的:检测商家与订单使用相同设备,疑似刷单。
USE `ecommerce`
MATCH pth8=(s@`shop`)-[@`shop_used_device`]-(d@`device`)-[@`placed_with`]-(o@`order`)-[@`contains`]-(p@`product`)-[@`sold_by`]-(s)
RETURN pth8

基于图的解释:该查询从店铺出发,找到店铺使用过的设备,再找到通过该设备下单的订单,最终确认订单商品是否属于该店铺,形成“店铺→设备→订单→商品→店铺”的环状路径,用于识别设备维度的刷单行为。
场景九:相同地址刷单检测
目的:检测商家与订单使用相同收货地址,疑似刷单。
USE `ecommerce`
MATCH pth9=(s@`shop`)-[@`shop_owned_by`]-(a@`address`)-[@`ship_to`]-(o@`order`)-[@`contains`]-(p@`product`)-[@`sold_by`]-(s)
RETURN pth9

基于图的解释:该查询从店铺出发,找到店铺的经营地址,再找到使用该地址作为收货地址的订单,最后确认订单商品是否属于该店铺。图中展示了地址维度的异常关联,用于识别商家通过相同地址伪造交易的刷单行为。
场景十:多订单共享 IP 检测(薅羊毛识别)
目的:检测多订单共享相同 IP 和设备,疑似薅羊毛、机器批量注册下单。
USE `ecommerce`
MATCH pth10=(o1@`order`)-[@`placed_from`]-(i@`ip`)-[@`placed_from`]-(o2@`order`)-[@`placed_with`]-(d@`device`)-[@`placed_with`]-(o1)
WHERE o1.`order_id` <> o2.`order_id`
RETURN pth10

基于图的解释:该查询从订单 o1 出发,找到其下单 IP,再找到使用同一 IP 的其他订单 o2,然后找到 o2 使用的设备,最后确认 o1 也使用了同一设备,形成“订单→IP→订单→设备→订单”的闭环路径。图中展示了多订单共享相同环境实体的异常聚集模式,用于识别批量机器操作。
场景十一:简化版多订单共享 IP 检测
目的:简化版检测多订单共享相同 IP,作为薅羊毛初筛。
USE `ecommerce`
MATCH pth11=(o1@`order`)-[@`placed_from`]-(i@`ip`)-[@`placed_from`]-(o2@`order`)
WHERE o1.`order_id` <> o2.`order_id`
RETURN pth11

基于图的解释:该查询直接从订单 o1 通过 IP 跳转到订单 o2,展示了共享同一 IP 的多个订单之间的关联关系。图中清晰地暴露了多个订单共用同一网络环境的异常情况,是风控系统中快速初筛薅羊毛行为的高效查询。
总结
通过 NebulaGraph 构建的电商关联网络,推荐与风控人员可以:
实现多场景智能推荐:基于用户历史购买、浏览、加购等行为,结合商品相似度、共现关系、店铺归属等维度,实现店内推荐、相似商品推荐、搭配购推荐、协同过滤推荐等多种推荐策略。
快速发现风险交易:通过检测店铺与订单在 IP、设备、地址等维度的异常关联,识别刷单、自买自卖等欺诈行为。
监控物流异常:通过物流站点、事件、订单的双向遍历,快速定位故障站点影响范围。
识别团伙欺诈:通过检测多订单共享相同 IP、设备等模式,发现薅羊毛、机器批量注册等团伙行为。
💡 本 Demo 展示了基础查询,仅作为简单场景下的 NebulaGraph 使用参考。实际生产环境中,还可结合社区发现、标签传播、PageRank 等图算法,实现更智能的推荐与风控策略。
交流图数据库技术?加入 Nebula 交流群请先填写下「你的 Nebula 名片」,Nebula 小助手会拉你进群~~



