data-direct-query.md 12 KB

数据直查层(data_* 数据库 / 缓存 / 上游)

直接读数据库、缓存或上游平台,跳过 Service 层。全部只读。仅当 service_* 工具无法满足(自定义 filter、聚合统计、上游原始数据)时使用。

MongoDB

工具 参数 说明
data_mongo_find collection(必填)、filter(JSON)、fields(字段投影数组)、limit(默认10,最大100)、skip、sort(JSON) 查询集合文档
data_mongo_count collection(必填)、filter(JSON,可空) 统计符合条件的文档数
data_mongo_export collection(必填)、filter(JSON)、fields(数组)、sort(JSON)、max_docs 全量导出到 NDJSON 文件,游标流式、内存常数级;仅回 localPath+count+summary
data_mongo_aggregate collection(必填)、pipeline(JSON数组字符串,必填)、max_docs 聚合管道:在数据库侧完成过滤+关联(JOIN)+分组统计,结果流式落盘

collection 白名单(仅以下集合可查;$lookup/$graphLookup/$unionWith 引用的集合也必须在此列表内): SiteInfoManageData、SiteInfoManageRecord、SimCardManage、SimCardMonthlyData、BatchDownloadConfig、SiteAnalysisConfig、StatisticsShutdown、StatisticsAlarm、SiteMonitorConfig、AutoUpdateConfigOption、AutoUpdateConfig

注意:UserInfo(内部用户身份数据)与 AiChatSessions(历史对话自由文本)已从白名单移除,不可直查,也不可作为 $lookup/$unionWith 的目标。

find/export 示例:

{ "collection": "SiteInfoManageData", "filter": "{\"sn\": \"xxx\"}", "limit": 10, "sort": "{\"createdAt\": -1}" }

用法提示:

  • filter / sort / pipeline 都是 JSON 字符串(如 "{\"sn\":\"xxx\"}")。
  • 分页用 skip + limit;大数据量导出用 data_mongo_export(不受 100 条上限)。
  • 优先用对应的 service_* 工具;直查仅用于灵活筛选/聚合/关联。
  • 所有 data_mongo_* 返回都无条件落盘:仅返回 localPath + summary,需用文件读取工具按 localPath 读取完整数据。

data_mongo_aggregate(聚合 / 跨集合 JOIN)

在数据库侧一次性完成"过滤 + 关联(JOIN) + 分组统计",避免多次取数与 Agent 侧拼接,是大数据量关联任务的首选。

允许的只读阶段:$match、$project、$addFields/$set、$unset、$group、$sort、$limit、$skip、$count、$unwind、$lookup、$graphLookup、$unionWith、$facet、$bucket/$bucketAuto、$sortByCount、$replaceRoot/$replaceWith、$sample、$redact、$setWindowFields。

禁止的阶段(会被拒绝):$out、$merge(写集合)、$function、$accumulator、$where(执行 JS)。

安全约束:

  • collection 及 $lookup/$graphLookup/$unionWith 引用的集合都必须在白名单内(含嵌套 pipeline,递归校验)。
  • 每个阶段必须恰好一个顶层操作符。
  • 结果超过 max_docs(默认 50000)会被截断。

字段字典(写 pipeline 必读)

SiteInfoManageData(站点信息,_id = 站点 SN)关键字段:

  • _id(站点 SN,20位)、iccId(SIM 卡 ICCID,20位;前 19 位 = GICCID)
  • province(州/省,如 "Puerto Rico")、city、country("United States")、countryId、provinceId
  • activeStatus(1=已激活)、status(在线状态)、runStatus、connType、signal、batterySoc
  • installerName、version、realSysHdVersion、site(站点编码)、siteId
  • 敏感字段(会被脱敏):address/deviceAddress、longitude/latitude、contactNumber、userName/firstName/lastName、account、mac/deviceIp/imei

SimCardManage(SIM 卡,_id = GICCID 19位)关键字段:

  • _id(GICCID,19位)、status(UNKNOWN/NOT_ACTIVATED/ACTIVATED/DEACTIVATED/RETIRED)、platform(SmartHub/Acceleronix)
  • allDataUsage(累计用量,单位 KB)、month(统计月份,格式不统一,见下方「month 字段双格式」)、expirationTime、updateTime
  • 敏感字段(会被脱敏):imei、imsi、msisdn

SimCardMonthlyData(SIM 月用量):simId(GICCID)、month(格式不统一,见下方「month 字段双格式」)、allDataUsage(单位 KB)、dailyUsage。

流量单位换算(写阈值必看):allDataUsage、dailyUsage.dataUsage 一律为 KB。 换算:1 MB = 1024 KB,1 GB = 1048576 KB。 常用阈值:200MB = 204800、500MB = 512000、1GB = 1048576、2GB = 2097152。 因此"流量大于 200M"应写 {"allDataUsage": {"$gt": 204800}},不要用 200 或 200000000。

⚠️ month 字段双格式(按 month 过滤/分组必看):SimCardManage.month 与 SimCardMonthlyData.month 历史上存在两种写法并存:

  • yyyy-MM(带连字符,如 2026-01)——SmartHub 平台写入。
  • yyyyMM(无连字符,如 202601)——Acceleronix 平台写入。

因此不能只用一种格式做等值匹配,否则会漏掉另一半数据。按月份筛选时用以下任一兼容写法:

  • 枚举两种格式(推荐,简单可用索引): {"month": {"$in": ["2026-01", "202601"]}}
  • 归一化后匹配(在 pipeline 里先去掉连字符再比):

    >   { "$addFields": { "monthNorm": { "$replaceAll": { "input": "$month", "find": "-", "replacement": "" } } } },
    >   { "$match": { "monthNorm": "202601" } }
    >   ```
    > 按 month 分组统计时同理,建议先用上面的 `$addFields` 归一化出 `monthNorm` 再 `$group`,避免同一个月被拆成两组。
    > `service_sim_monthly_data` 等 service 层工具入参仍用 `yyyy-MM`(由后端处理),此双格式问题**仅影响 `data_mongo_*` 直查**。
    
    #### JOIN 关系图谱(跨集合关联键)
    
    - **站点 ↔ SIM**:`SiteInfoManageData.iccId` 取**前 19 位** = `SimCardManage._id`(GICCID)。
    在 pipeline 中先用 `$addFields` 计算 `giccid = $substrBytes(iccId, 0, 19)`,再 `$lookup` 关联。
    - **SIM ↔ 月用量**:`SimCardManage._id` = `SimCardMonthlyData.simId`。
    
    #### 配方:波多黎各站点关联 SIM 信息(一步完成)
    
    

    json

[ { "$match": { "province": "Puerto Rico" } }, { "$addFields": { "giccid": { "$substrBytes": ["$iccId", 0, 19] } } }, { "$lookup": {

  "from": "SimCardManage",
  "localField": "giccid",
  "foreignField": "_id",
  "as": "sim"

}}, { "$project": {

  "sn": "$_id", "city": 1, "giccid": 1,
  "simStatus": { "$arrayElemAt": ["$sim.status", 0] },
  "simPlatform": { "$arrayElemAt": ["$sim.platform", 0] },
  "dataUsage": { "$arrayElemAt": ["$sim.allDataUsage", 0] }

}} ]

调用(pipeline 作为 JSON 字符串传入):

json { "collection": "SiteInfoManageData", "pipeline": "[{\"$match\":{\"province\":\"Puerto Rico\"}}, ...]" }


#### 配方:按 SIM 流量阈值反向筛出站点信息(如"流量 > 200M 的站点")

从 SIM 侧起点:先按用量过滤 SIM,再关联回站点,一步得到"高流量站点"清单。
关键点:起点集合是 `SimCardManage`,用量阈值按 **KB**(200MB = 204800);
站点侧 `iccId` 前 19 位才等于 GICCID,故在 `$lookup` 的子 pipeline 里用 `$substrBytes` 对齐后再匹配。

json [ { "$match": { "allDataUsage": { "$gt": 204800 } } }, { "$lookup": {

  "from": "SiteInfoManageData",
  "let": { "giccid": "$_id" },
  "pipeline": [
    { "$addFields": { "siteGiccid": { "$substrBytes": ["$iccId", 0, 19] } } },
    { "$match": { "$expr": { "$eq": ["$siteGiccid", "$$giccid"] } } },
    { "$project": { "sn": "$_id", "province": 1, "city": 1, "activeStatus": 1 } }
  ],
  "as": "sites"

}}, { "$match": { "sites": { "$ne": [] } } }, { "$project": {

  "giccid": "$_id", "allDataUsage": 1, "platform": 1, "simStatus": "$status",
  "sites": 1

}} ]

调用(pipeline 作为 JSON 字符串传入):

json { "collection": "SimCardManage", "pipeline": "[{\"$match\":{\"allDataUsage\":{\"$gt\":204800}}}, ...]" }

说明:
- 阈值改其它值时按 KB 换算(见上面「流量单位换算」)。
- 只关心站点、不关心 SIM 明细时,可在末尾加 `{"$unwind":"$sites"}` + `{"$replaceRoot":{"newRoot":"$sites"}}` 直接输出站点文档。
- 只要计数("有多少个这样的站点")时,末尾用 `{"$unwind":"$sites"}` 后接 `{"$count":"siteCount"}`,不要把明细拉回上下文。

#### 配方:按州统计站点数与激活率

json [ { "$group": {

  "_id": "$province",
  "total": { "$sum": 1 },
  "active": { "$sum": { "$cond": [{ "$eq": ["$activeStatus", 1] }, 1, 0] } }

}}, { "$sort": { "total": -1 } } ] ```

约束与反模式

  • 跨集合关联必须在库侧一步完成(硬约束):凡是"站点 ↔ SIM ↔ 月用量"之间的关联/条件筛选(如"流量>200M的站点""某州站点的SIM状态"),必须用 data_mongo_aggregate 的 $lookup 在数据库侧完成。禁止分别 data_mongo_find/data_sim_* 拉两张表的明细,再在 Agent 上下文里手工遍历、匹配、过滤——这会把大量数据灌入上下文导致膨胀/超时,正是要避免的反模式。
  • 若一次聚合难以表达,可先用 $match+$group/$count 在库侧收敛出少量键(如符合条件的 GICCID/SN 列表),再用该小列表做下一步;始终让"大数据量筛选"发生在数据库侧。
  • 不要用 $project/$group 把敏感字段(contactNumber/imei/longitude 等)重命名成新字段名或拼接进字符串——脱敏按字段名匹配,改名可能绕过脱敏,导致隐私外泄。保留敏感字段原名或直接不输出。
  • $lookup 关联大集合时注意被关联集合的关联字段应有索引(SimCardManage._id、SimCardMonthlyData.simId 已有)。
  • 只需计数/分组时优先 $group,不要把明细 $push 出来再在 Agent 侧数。
  • 需要把结果交给用户或后续脚本时,按 localPath 读取 NDJSON 文件处理。

Redis

工具 参数 说明
data_redis_get key、type(string默认/hash/list/set) 读取 key 的值(仅支持 string 和 hash)
data_redis_exists key 检查 key 是否存在并返回 TTL

PostgreSQL(告警快照)

工具 参数 说明
data_pgsql_query_snapshot_data sn、date 按 SN 和日期查告警快照数据
data_pgsql_query_snapshot_file_record file_name 查告警快照文件的解析记录

EMS 参数字典

工具 参数 说明
data_emspara_pid_info id(PID ID 数字字符串) 通过 PID ID 查宏名和描述
data_emspara_vid_info id(VID ID 数字字符串) 通过 VID ID 查宏名和描述

用于把 EMS 日志/参数中的数字 PID/VID 翻译成可读含义。

SIM 上游平台

优先用 service_sim_*(见主 SKILL.md 第 4 节);需上游原始数据时用:

Acceleronix | 工具 | 参数 | 说明 | |------|------|------| | data_sim_acceleronix_card_info | iccid | 单张 SIM 详情 | | data_sim_acceleronix_card_list | page、size | SIM 卡列表 | | data_sim_acceleronix_batch_data_info | iccid_list(逗号分隔)、month(YYYYMM) | 批量用量信息 | | data_sim_acceleronix_data_pool_list | page、size | 流量池列表 | | data_sim_acceleronix_data_pool_sim_info | data_pool_id、page、size | 流量池中的 SIM 详情 |

SmartHub | 工具 | 参数 | 说明 | |------|------|------| | data_sim_smarthub_card_info | giccid | 单张 SIM 详细信息 | | data_sim_smarthub_batch_info | page、size | 批量 SIM 信息 |

注意:Acceleronix 用 iccid,SmartHub 用 giccid;月份参数 Acceleronix 批量用量为 YYYYMM。