# 数据直查层(`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 示例: ```json { "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 里先去掉连字符再比): > ```json > { "$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`。