Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
Amazon-Selection-Data
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abel_cjy
Amazon-Selection-Data
Commits
dba09ae4
Commit
dba09ae4
authored
Aug 04, 2026
by
chenyuanjie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
用户固定选品模式纳入每日刷新流程
parent
7e1bfab7
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
31 additions
and
68 deletions
+31
-68
dws_flow_asin_refresh.py
Pyspark_job/doris_handle/dws_flow_asin_refresh.py
+0
-0
dwt_user_selection_pattern.py
Pyspark_job/doris_handle/dwt_user_selection_pattern.py
+31
-68
No files found.
Pyspark_job/doris_handle/dws_flow_asin_refresh.py
View file @
dba09ae4
This diff is collapsed.
Click to expand it.
Pyspark_job/doris_handle/dw
s
_user_selection_pattern.py
→
Pyspark_job/doris_handle/dw
t
_user_selection_pattern.py
View file @
dba09ae4
"""
"""
@Author : CT
@Author : CT
@Description : 根据用户筛选模式日志批量计算选品结果,写入 Doris selection.user_selection_pattern
@Description : 按站点增量追平用户筛选模式选品结果,写入 Doris selection.user_selection_pattern
- 串行逐 filter_id 执行,减小数据库压力
- 传入 site_name,只处理该站点的 active filter
- 纯增量追平:水位线落后于该站点最新月表时补齐缺失月份,不做刷新判断
(us 站点利润率/Keepa 字段每日刷新型 filter,最新月差异化刷新见 dws_flow_asin_refresh.py 第5步)
- 支持断点续算:latest_computed_month 作为水位线,跳过已算月份
- 支持断点续算:latest_computed_month 作为水位线,跳过已算月份
- Doris AGGREGATE KEY(filter_id, asin) + MIN(date_info) 自动保留首次入选月份
- Doris AGGREGATE KEY(filter_id, asin) + MIN(date_info) 自动保留首次入选月份
-
us 站点利润率/Keepa 字段每日刷新:TRUNCATE 分区(p{filter_id}) + 全量重算
-
每月执行一次即可(只有新月表出现时才会产生缺口)
- 水位线规则:成功→维护到最新月份;失败→维护到失败的前一个月
执行示例: python dwt_user_selection_pattern.py us
"""
"""
import
os
import
os
import
re
import
sys
import
sys
from
datetime
import
datetime
from
datetime
import
datetime
...
@@ -23,11 +24,6 @@ MYSQL_FILTER_TABLE = 'flow_increment_filter_sql' # MySQL 筛选模式日志表
...
@@ -23,11 +24,6 @@ MYSQL_FILTER_TABLE = 'flow_increment_filter_sql' # MySQL 筛选模式日志表
DORIS_RESULT_DB
=
'selection'
DORIS_RESULT_DB
=
'selection'
DORIS_RESULT_TABLE
=
'user_selection_pattern'
DORIS_RESULT_TABLE
=
'user_selection_pattern'
SUPPORTED_SITES
=
(
'us'
,
'uk'
,
'de'
)
SUPPORTED_SITES
=
(
'us'
,
'uk'
,
'de'
)
REFRESH_FIELDS
=
{
'ocean_profit'
,
'air_profit'
,
'launch_time'
,
'launch_time_type'
,
'tracking_since'
,
'tracking_since_type'
,
}
# ===== 连接工厂 =====
# ===== 连接工厂 =====
...
@@ -46,6 +42,7 @@ def _get_doris_conn():
...
@@ -46,6 +42,7 @@ def _get_doris_conn():
def
_get_mysql_engine
():
def
_get_mysql_engine
():
"""flow_increment_filter_sql 是跨站点共享的控制库表(带 site 字段区分),固定连 us 实例"""
return
DBUtil
.
get_db_engine
(
db_type
=
DbTypes
.
mysql
.
name
,
site_name
=
'us'
)
return
DBUtil
.
get_db_engine
(
db_type
=
DbTypes
.
mysql
.
name
,
site_name
=
'us'
)
...
@@ -79,10 +76,6 @@ def _get_available_months(doris_cur, site):
...
@@ -79,10 +76,6 @@ def _get_available_months(doris_cur, site):
return
months
return
months
def
_needs_refresh
(
where_sql
):
return
any
(
re
.
search
(
rf
'
\b
{re.escape(field)}
\b
'
,
where_sql
)
for
field
in
REFRESH_FIELDS
)
def
_update_mysql_log
(
mysql_conn
,
filter_id
,
latest_month
,
status
,
msg
):
def
_update_mysql_log
(
mysql_conn
,
filter_id
,
latest_month
,
status
,
msg
):
now
=
datetime
.
now
()
.
strftime
(
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
)
now
=
datetime
.
now
()
.
strftime
(
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
)
if
latest_month
is
not
None
:
if
latest_month
is
not
None
:
...
@@ -95,7 +88,7 @@ def _update_mysql_log(mysql_conn, filter_id, latest_month, status, msg):
...
@@ -95,7 +88,7 @@ def _update_mysql_log(mysql_conn, filter_id, latest_month, status, msg):
WHERE filter_id =
%
s"""
WHERE filter_id =
%
s"""
params
=
(
latest_month
,
status
,
now
,
msg
[:
500
],
filter_id
)
params
=
(
latest_month
,
status
,
now
,
msg
[:
500
],
filter_id
)
else
:
else
:
#
首月即失败:不更新水位线,仅记录失败状态
#
latest_month 为 None:仅记录失败状态,不更新水位线
sql
=
f
"""UPDATE `{MYSQL_FILTER_TABLE}`
sql
=
f
"""UPDATE `{MYSQL_FILTER_TABLE}`
SET last_run_status =
%
s,
SET last_run_status =
%
s,
last_run_at =
%
s,
last_run_at =
%
s,
...
@@ -110,57 +103,24 @@ def _update_mysql_log(mysql_conn, filter_id, latest_month, status, msg):
...
@@ -110,57 +103,24 @@ def _update_mysql_log(mysql_conn, filter_id, latest_month, status, msg):
# ===== 核心计算 =====
# ===== 核心计算 =====
def
_compute_one_filter
(
row
,
doris_cur
,
mysql_conn
,
months_by_site
):
def
_backfill_one_filter
(
row
,
site_name
,
available
,
doris_cur
,
mysql_conn
):
"""水位线落后于最新月表时,纯新增 INSERT 追平缺失月份(不做刷新判断)"""
filter_id
=
row
[
'filter_id'
]
filter_id
=
row
[
'filter_id'
]
site
=
row
[
'site'
]
base_month
=
row
[
'base_month'
]
base_month
=
row
[
'base_month'
]
where_sql
=
row
[
'where_sql'
]
where_sql
=
row
[
'where_sql'
]
latest_done
=
row
[
'latest_computed_month'
]
# None 表示从未计算过
latest_done
=
row
[
'latest_computed_month'
]
# None 表示从未计算过
available
=
months_by_site
.
get
(
site
,
[])
latest_available
=
available
[
-
1
]
if
not
available
:
print
(
f
" [SKIP] 站点 {site} 无可用月表"
)
return
is_refresh
=
_needs_refresh
(
where_sql
)
and
site
==
'us'
if
is_refresh
:
# 刷新模式:TRUNCATE 分区 + 从 base_month 全量重算
doris_cur
.
execute
(
f
"SELECT auto_partition_name('list', {filter_id})"
)
partition_name
=
doris_cur
.
fetchone
()[
0
]
truncate_sql
=
(
f
"TRUNCATE TABLE `{DORIS_RESULT_DB}`.`{DORIS_RESULT_TABLE}` "
f
"PARTITION ({partition_name})"
)
try
:
doris_cur
.
execute
(
truncate_sql
)
print
(
f
" [TRUNCATE] 已清空分区 {partition_name}"
)
except
Exception
as
e
:
err_str
=
str
(
e
)
if
'does not exist'
in
err_str
:
# 首次计算时分区尚未创建,跳过 TRUNCATE 直接 INSERT
print
(
f
" [TRUNCATE SKIP] 分区 {partition_name} 不存在(首次计算),跳过清空"
)
else
:
err
=
err_str
[:
200
]
print
(
f
" [TRUNCATE FAIL] {err}"
)
_update_mysql_log
(
mysql_conn
,
filter_id
,
latest_done
,
'failed'
,
f
'TRUNCATE失败: {err}'
)
return
all_months
=
[
m
for
m
in
available
if
m
>=
base_month
]
mode_label
=
'刷新重算'
last_ok_month
=
None
else
:
# 补算模式:水位线增量
start_month
=
_next_month
(
latest_done
)
if
latest_done
else
base_month
start_month
=
_next_month
(
latest_done
)
if
latest_done
else
base_month
all_months
=
[
m
for
m
in
available
if
start_month
<=
m
<=
available
[
-
1
]]
all_months
=
[
m
for
m
in
available
if
start_month
<=
m
<=
latest_available
]
mode_label
=
'新增'
last_ok_month
=
None
if
not
all_months
:
if
not
all_months
:
print
(
f
" [SKIP] 无需计算(latest_computed={latest_done},
refresh={is_refresh
})"
)
print
(
f
" [SKIP] 无需计算(latest_computed={latest_done},
已追平至最新月 {latest_available
})"
)
return
return
print
(
f
" [
{mode_label}
] 计算范围:{all_months[0]} ~ {all_months[-1]},共 {len(all_months)} 个月"
)
print
(
f
" [
新增
] 计算范围:{all_months[0]} ~ {all_months[-1]},共 {len(all_months)} 个月"
)
last_ok_month
=
None
for
month
in
all_months
:
for
month
in
all_months
:
table
=
f
'{site}_flow_asin_month_{month.replace("-", "_")}'
table
=
f
'{site
_name
}_flow_asin_month_{month.replace("-", "_")}'
sql
=
f
"""
sql
=
f
"""
INSERT INTO `{DORIS_RESULT_DB}`.`{DORIS_RESULT_TABLE}`
INSERT INTO `{DORIS_RESULT_DB}`.`{DORIS_RESULT_TABLE}`
(filter_id, asin, date_info)
(filter_id, asin, date_info)
...
@@ -183,40 +143,43 @@ def _compute_one_filter(row, doris_cur, mysql_conn, months_by_site):
...
@@ -183,40 +143,43 @@ def _compute_one_filter(row, doris_cur, mysql_conn, months_by_site):
_update_mysql_log
(
_update_mysql_log
(
mysql_conn
,
filter_id
,
last_ok_month
,
'success'
,
mysql_conn
,
filter_id
,
last_ok_month
,
'success'
,
f
'完成:
{mode_label}
{len(all_months)} 个月({all_months[0]} ~ {all_months[-1]})'
f
'完成:
新增
{len(all_months)} 个月({all_months[0]} ~ {all_months[-1]})'
)
)
# ===== 入口 =====
# ===== 入口 =====
def
main
():
def
main
():
assert
len
(
sys
.
argv
)
==
2
and
sys
.
argv
[
1
]
in
SUPPORTED_SITES
,
\
f
"用法: python dwt_user_selection_pattern.py <site_name>,site_name 需为 {SUPPORTED_SITES} 之一"
site_name
=
sys
.
argv
[
1
]
doris_conn
=
_get_doris_conn
()
doris_conn
=
_get_doris_conn
()
engine
=
_get_mysql_engine
()
engine
=
_get_mysql_engine
()
mysql_conn
=
engine
.
raw_connection
()
mysql_conn
=
engine
.
raw_connection
()
try
:
try
:
doris_cur
=
doris_conn
.
cursor
()
doris_cur
=
doris_conn
.
cursor
()
# 预加载各站点可用月份
available
=
_get_available_months
(
doris_cur
,
site_name
)
months_by_site
=
{
site
:
_get_available_months
(
doris_cur
,
site
)
for
site
in
SUPPORTED_SITES
}
if
not
available
:
for
site
,
months
in
months_by_site
.
items
():
print
(
f
"[SKIP] 站点 {site_name} 无可用月表"
)
r
ng
=
f
"{months[0]} ~ {months[-1]}"
if
months
else
"无"
r
eturn
print
(
f
"[站点 {site}] 可用月份:{rng}(共 {len(months
)} 个)"
)
print
(
f
"[站点 {site_name}] 可用月份:{available[0]} ~ {available[-1]}(共 {len(available
)} 个)"
)
# 读取全部 active 筛选模式
df
=
pd
.
read_sql
(
df
=
pd
.
read_sql
(
f
"""SELECT filter_id,
site,
base_month, where_sql, latest_computed_month
f
"""SELECT filter_id, base_month, where_sql, latest_computed_month
FROM `{MYSQL_FILTER_TABLE}`
FROM `{MYSQL_FILTER_TABLE}`
WHERE status = 'active'
WHERE status = 'active'
AND site = '{site_name}'
ORDER BY filter_id"""
,
ORDER BY filter_id"""
,
engine
engine
)
)
total
=
len
(
df
)
total
=
len
(
df
)
print
(
f
"
\n
共 {total} 条 active 筛选模式,开始串行计算...
\n
"
)
print
(
f
"
\n
共 {total} 条 active 筛选模式
(站点={site_name})
,开始串行计算...
\n
"
)
for
i
,
row
in
df
.
iterrows
():
for
i
,
row
in
df
.
iterrows
():
print
(
f
"[{i + 1}/{total}] filter_id={row['filter_id']}
site={row['site']}
"
)
print
(
f
"[{i + 1}/{total}] filter_id={row['filter_id']}"
)
try
:
try
:
_
compute_one_filter
(
row
,
doris_cur
,
mysql_conn
,
months_by_site
)
_
backfill_one_filter
(
row
,
site_name
,
available
,
doris_cur
,
mysql_conn
)
except
Exception
as
e
:
except
Exception
as
e
:
print
(
f
" [ERROR] 未预期异常:{e}"
)
print
(
f
" [ERROR] 未预期异常:{e}"
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment