读取 Solr 分词结果时,不能把 tokenizer 与每个 filter 的输出全部拼成一个词表。分析接口展示的是各阶段如何变换 token;如果业务需要最终查询词,应明确取查询侧最后一个阶段。
请求字段必须对应真实 schema
旧代码在 Solr 8.0 中对 bk_name 发起 /analysis/field 请求,fieldValue 为空、query 为待分析文本,再读取查询侧阶段。字段不能“随便选一个支持中文的字段”:它的 fieldType 和 query analyzer 必须正是业务需要观察的配置。Solr 8.0 分析界面
下面恢复成一个不混合阶段的方法,客户端由调用方传入并管理生命周期:
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.request.FieldAnalysisRequest;
import org.apache.solr.client.solrj.response.AnalysisResponseBase.AnalysisPhase;
import org.apache.solr.client.solrj.response.AnalysisResponseBase.TokenInfo;
import org.apache.solr.client.solrj.response.FieldAnalysisResponse;
public class QueryTokens {
public static List<String> analyze(SolrClient client,
String field, String sentence)
throws IOException, SolrServerException {
if (field == null || field.isEmpty() || sentence == null) {
throw new IllegalArgumentException("字段与文本不能为空引用");
}
FieldAnalysisRequest request = new FieldAnalysisRequest("/analysis/field");
request.addFieldName(field);
request.setFieldValue("");
request.setQuery(sentence);
request.setMethod(SolrRequest.METHOD.POST);
FieldAnalysisResponse response = request.process(client);
FieldAnalysisResponse.Analysis analysis =
response.getFieldNameAnalysis(field);
if (analysis == null || analysis.getQueryPhases() == null) {
return Collections.emptyList();
}
AnalysisPhase last = null;
for (AnalysisPhase phase : analysis.getQueryPhases()) {
last = phase;
}
if (last == null) {
return Collections.emptyList();
}
List<String> result = new ArrayList<>();
for (TokenInfo token : last.getTokens()) {
result.add(token.getText());
}
return result;
}
}
方法按 8.0.0 API 整理,不包含目标 core 或中文插件安装。请求失败直接向调用者传播,不先打印异常再对 null response 继续操作。8.0.0 响应结构源码
最后阶段也不一定是一条线性词序
示例保留返回顺序和重复项;同义词等处理可能产生相同位置的多个 token。若要还原匹配关系,应同时保存 position、start、end 等信息,而不是只返回字符串。TokenInfo 定义
诊断入库文本时改看索引侧阶段,不要把查询链和索引链混用;两者可能刻意采用不同配置。
不按字节数判断中文
原代码通过字节长度阈值过滤“单字或非中文”,既受字符编码影响,也无法区分语言。单字中文、短英文、数字与混合文本都可能被误删。
是否去重、是否过滤停用词、是否保留同义词,应是明确业务规则。不能在解析响应时默默按编码长度删词,再把结果当作真实分析链输出。