Elasticsearch有效查询需确保索引存在、参数结构正确、字段映射合理:index名称严格小写且存在,body中必须含query(如match_all),text字段需配中文分词器(如ik_max_word),size需显式设置,bool查询须分离must(影响评分)与filter(可缓存的确定性条件),category_path等路径字段须设为keyword类型才支持prefix查询,用户输入须截断、白名单校验防注入。

怎么用 elasticsearch/elasticsearch 客户端发一次有效查询
直接调用 search() 就能查,但多数人卡在参数结构不对、字段没映射或连接失败。关键不是“能不能”,而是“参数怎么组织才不返回空”。
-
index必须存在且名称拼写完全一致(区分大小写),用existIndex()先确认 -
body里至少得有query,哪怕只是['match_all' => new \stdClass()] - 如果字段是
text类型但没配中文分词器(如ik_max_word),搜中文会查不到——title字段建索引时就得指定"analyzer": "ik_max_word" - 别漏掉
size,默认只返回 10 条,查不到更多不是逻辑错,是没设
bool 查询里 must 和 filter 到底放什么
混用 must 和 filter 是导致评分异常、缓存失效、性能下降的主因。Elasticsearch 9.x 强制要求显式分离。
-
filter放确定性条件:上架状态(['term' => ['status' => true]])、类目 ID(['terms' => ['category_id' => [1,2,3]]])、价格区间(['range' => ['price' => ['gte' => 100, 'lte' => 500]]])——这些不参与打分,可被缓存 -
must只放全文检索项:比如['multi_match' => ['query' => $kw, 'fields' => ['title^3', 'desc^1']]],它影响相关度计算 - 如果用了
should,必须加'minimum_should_match' => 1,否则整个bool可能匹配不上任何文档
为什么搜 category_path 要用 prefix 而不是 term
电商类目路径如 "1-2-5-" 是树形结构,用 term 只能精确匹配完整路径,根本没法支持“查二级类目下所有商品”这种需求。
-
prefix查"1-2-"就能命中"1-2-5-"、"1-2-8-"、"1-2-5-12-"等所有子路径 - 字段 mapping 必须设为
"type": "keyword",否则prefix不生效(text类型会被分词,"1-2-"就拆成"1"、"2"了) - 别在
filter里用match或query_string去查category_path,它们走分词,结果不可控
用户输入参数怎么防注入和越界
Elasticsearch 没预编译机制,script、regexp、_script 排序等 DSL 片段一旦被用户控制,就能执行任意逻辑甚至读取集群元数据。
- 关键词先
trim()+strip_tags()+mb_substr($kw, 0, 100)截断,防超长 query 拖垮节点 - 排序字段严格白名单:
in_array($sort_field, ['price', 'created_at', 'sales_count']),禁止传_score或_doc -
from/size做整型校验,size≤ 100,from + size≤ 10000——deep pagination 是 OOM 高发区 - 所有用户可控字段(如类目 ID、品牌 ID)都得走
in_array()或数据库查证,不能直接拼进 query body
category_path 字段忘了设 keyword 类型;filter 里塞了 match 导致缓存失效还慢。这些不报错,但查不准、跑得慢、线上突然崩。


















