# 简单搜索（simple_search）使用说明

本文档介绍使用 `simple_search` 的参数化日志搜索能力。该功能会根据传入参数自动组装符合规范的 `search2` SPL 并执行查询，避免手写 SPL。

## 功能概述

- 目标：通过参数（仓库、时间、过滤、聚合、排序、限制）生成规范 SPL 并查询。
- 引擎：日志查询统一使用 `search2`。
- 语法约束：严格遵循 `log_search_syntax.md` 的规则（时间参数紧跟 `search2`，字段名单引号、值双引号，`sort by` 等）。

## 参数说明

- `repository`（必填）：仓库名，生成 `repo="..."`。
- `start`/`end`（可选）：时间参数，必须位于 `search2` 后且在 `repo` 之前，例如 `start="-1h"`、`end=""`。 # end默认为当前时间，在大多数场景下可以不写，不允许写成 `end="@now"`这种。
- `filters`（可选）：列表形式的过滤条件，支持与/或/非组合：
  - 单项结构：
    - `field`：字段名；与 `text` 互斥。
    - `op`：操作符，支持 `=, !=, >=, <=, >, <, in, not in`；当为 `contains/like` 时将转为全文匹配。
    - `value`：非 `in/not in` 场景的值（数字不加引号；字符串双引号；含双引号使用三双引号）。
    - `values`：`in/not in` 场景的数组（数字不加引号，字符串双引号）。
    - `text`：全文匹配内容，直接作为自由文本（如 `"error"`、`"*Forbidden*"`）。
    - `not`：布尔，取反，生成 `NOT (...)`。
- `logic`（可选）：`AND | OR`，用于连接多个 `filters`，默认 `AND`。
- `stats`（可选）：聚合算子列表（生成 `| stats ...`）：
  - 单项结构：
    - `func`：聚合函数，如 `count | sum | avg | min | max | distinct | percentile | earliest | latest`。
    - `field`：聚合字段；`count` 可省略；`earliest/latest`可省略字段时将生成 `func()`。
    - `alias`：结果别名，生成 `as '别名'`。
    - `args`：额外参数列表（如 `percentile` 的百分位）。
- `group_by`（可选）：分组字段列表，生成 `by 'f1', 'f2'`。
- `sort_field`/`sort_order`（可选）：排序字段与顺序（`asc|desc`），生成 `| sort by '字段' 顺序`。
- `limit`（可选）：数量限制，生成 `| limit N`；同时影响后端返回行数。
- `format_type`（可选）：`text | csv | json`，默认 `csv`。
- `output_file`（可选）：写入文件路径；提供则把结果写入该文件。

## 组装规则要点

- 查询主段：`search2 start="..." end="..." repo="..." (<filters>)`。
- 过滤连接：所有 `filters` 放入一对括号，以 `logic` 连接，确保优先级：`(cond1 AND cond2)`。
- 字段/值引号：字段名单引号（`'status'`），值双引号（`"ERROR"`）；数字值不加引号；含双引号用三双引号（`"""a"b"""`）。
- 全文匹配：无需字段名，直接写自由文本，示例 `"error"` 或 `"*Forbidden*"`；`contains/like` 自动转换为全文匹配。
- 聚合段：当传入 `stats` 时生成 `| stats <聚合表达式> by <group_by>`，支持多个聚合表达式以逗号分隔。
- 排序与限制：使用 `| sort by '字段' asc|desc | limit N`。

## 示例

### 1) 基本过滤与排序

```
repository = "_internal"
start = "-1h"
filters = [{"field":"origin","op":"=","value":"_collector"}]
sort_field = "_time"
sort_order = "asc"
limit = 3
format_type = "text"
```

生成 SPL：

```
search2 start="-1h" repo="_internal" ('origin'="_collector") | sort by '_time' asc | limit 3
```

### 2) 全文检索

```
repository = "logs_keta"
start = "-6h"
end = "@h"
filters = [{"text":"*Forbidden*"}, {"field":"level","op":"=","value":"WARN"}]
logic = "AND"
limit = 100
```

生成 SPL：

```
search2 start="-6h" end="@h" repo="logs_keta" ('level'="WARN" AND "*Forbidden*") | limit 100
```

### 3) 集合与数值比较

```
repository = "web_logs"
filters = [
  {"field":"level","op":"in","values":["WARN","ERROR"]},
  {"field":"status","op":">=","value":400}
]
logic = "AND"
sort_field = "status"
sort_order = "desc"
limit = 10
format_type = "csv"
```

生成 SPL：

```
search2 repo="web_logs" ('level' in ("WARN","ERROR") AND 'status'>=400) | sort by 'status' desc | limit 10
```

### 4) 统计聚合：计数按来源分组

```
repository = "_internal"
start = "-1h"
filters = [{"field":"origin","op":"=","value":"_collector"}]
stats = [{"func":"count","alias":"cnt"}]
group_by = ["origin"]
sort_field = "cnt"
sort_order = "desc"
limit = 5
format_type = "text"
```

生成 SPL：

```
search2 start="-1h" repo="_internal" ('origin'="_collector") | stats count() as 'cnt' by 'origin' | sort by 'cnt' desc | limit 5
```

### 5) 统计聚合：平均值与 P95

```
repository = "_internal"
start = "-1h"
filters = [{"field":"origin","op":"=","value":"_collector"}]
stats = [
  {"func":"avg","field":"avgHandlingTimeInMilli","alias":"avg_time"},
  {"func":"percentile","field":"avgHandlingTimeInMilli","args":[95],"alias":"p95"}
]
group_by = ["host"]
sort_field = "avg_time"
sort_order = "desc"
limit = 5
format_type = "csv"
```

生成 SPL：

```
search2 start="-1h" repo="_internal" ('origin'="_collector") | stats avg('avgHandlingTimeInMilli') as 'avg_time', percentile('avgHandlingTimeInMilli', 95) as 'p95' by 'host' | sort by 'avg_time' desc | limit 5
```

## 返回与错误处理

- 返回格式：按 `format_type` 输出（`text|csv|json`），默认 `csv`。
- 文件输出：提供 `output_file` 时写入文件并返回已写入提示。
- 空结果：返回友好建议（放宽条件、扩大时间范围）。
- 语法校验：当引号/管道等不合规时返回明确的修复建议，规则见 `log_search_syntax.md`。

## 编写建议

1. 先用较宽时间与少量条件验证字段与样例（可配 `limit 1`），再逐步收紧。
2. 复杂条件用括号保证优先级；全文检索优先使用自由文本而非 `contains/like`。
3. 使用 `stats` 时建议与 `sort by` 搭配以突出关键指标。

## 其它说明
### 1) 时间参数（start/end）
- 相对时间示例：
  - `start="-1h"`（近 1 小时）
  - `start="-d@d" end="@d"`（昨天整天，不包含今天）
  - `start="-3d"`（近 3 天）
  - `start="-M@M" end="@M"`（上个月）
- 对齐符号：`@s @m @h @d @w @M @y`。
- 时间参数不支持now()函数。