Solr 7.3.0自定义QueryResponseWriter无法正常工作求助
我帮你梳理下可能导致这个问题的几个关键点,以及对应的排查和修复方案:
先回顾你的配置与实现细节
1. 自定义库加载情况
你已经在Solr配置中添加了自定义库路径,且启动日志确认该路径已被加载:
<lib dir="${solr.install.dir:../../../..}/contrib/customresponsewriter" regex=".*\.jar" />
Added 63 libs to classloader, from paths: [/home/bibek/software/java/solr-7.3.0/contrib/clustering/lib, /home/bibek/software/java/solr-7.3.0/contrib/customresponsewriter, /home/bibek/software/java/solr-7.3.0/contrib/extraction/lib, /home/bibek/software/java/solr-7.3.0/contrib/langid/lib, /home/bibek/software/java/solr-7.3.0/contrib/velocity/lib, /home/bibek/software/java/solr-7.3.0/dist]
2. 自定义ResponseWriter代码
你的TypeAheadResponseWriter实现了QueryResponseWriter接口,核心逻辑是遍历响应中的DocList并输出HTML列表:
public class TypeAheadResponseWriter implements QueryResponseWriter { private Set<String> fields; public void write(Writer writer, SolrQueryRequest solrQueryRequest, SolrQueryResponse solrQueryResponse) throws IOException { SolrIndexSearcher searcher = solrQueryRequest.getSearcher(); NamedList namedList = solrQueryResponse.getValues(); int size = namedList.size(); for (int i = 0; i < size; i++) { Object val = namedList.getVal(i); if (val instanceof DocList) { DocList docList = (DocList) val; DocIterator docIterator = docList.iterator(); writer.append("<ul>\n"); while (docIterator.hasNext()) { int id = docIterator.nextDoc(); Document doc = searcher.doc(id, fields); String name = doc.get("title"); writer.append("<li>" + name + "</li>"); } writer.append("</ul>\n"); } } } public String getContentType(SolrQueryRequest solrQueryRequest, SolrQueryResponse solrQueryResponse) { return "text/html;charset=UTF-8"; } public void init(NamedList namedList) { fields = new HashSet<String>(); fields.add("title"); } }
3. Solr核心配置
你已经注册了tah类型的ResponseWriter,并配置了对应的请求处理器:
<queryResponseWriter name="tah" class="cqw.TypeAheadResponseWriter"/> <requestHandler name="/type-ahead" class="solr.SearchHandler"> <lst name="defaults"> <str name="wt">tah</str> <str name="defType">dismax</str> <str name="qf">title_prefix_typeahead^1.0</str> </lst> </requestHandler>
可能的问题点及修复方案
1. 核心问题:未正确获取查询结果的DocList
Solr的查询结果默认存储在NamedList的**"response"**键下,而你的代码是遍历整个NamedList的顶层元素,大概率找不到DocList对象,导致没有输出。
修改write方法,直接定位到"response"对应的结果:
public void write(Writer writer, SolrQueryRequest solrQueryRequest, SolrQueryResponse solrQueryResponse) throws IOException { SolrIndexSearcher searcher = solrQueryRequest.getSearcher(); NamedList<?> namedList = solrQueryResponse.getValues(); // 直接获取response对应的DocList(Solr默认的结果存储键) Object responseVal = namedList.get("response"); if (responseVal instanceof DocList) { DocList docList = (DocList) responseVal; DocIterator docIterator = docList.iterator(); writer.append("<ul>\n"); while (docIterator.hasNext()) { int id = docIterator.nextDoc(); Document doc = searcher.doc(id, fields); String title = doc.get("title"); // 避免输出空列表项 if (title != null) { writer.append(" <li>" + title + "</li>\n"); } } writer.append("</ul>\n"); } else { // 调试用:输出当前响应的结构,确认结果是否存在 writer.append("<p>No results found or unexpected response structure. Response content: " + namedList.toString() + "</p>"); } }
2. 验证查询本身是否返回结果
先排除查询配置的问题:用wt=json发起相同请求,确认是否有匹配的文档:
http://localhost:8983/solr/collectiona/type-ahead?q=fayes&wt=json
如果这个请求也返回空结果,那问题出在查询逻辑上:
- 检查
title_prefix_typeahead字段是否存在于你的Schema中 - 确认该字段是否有匹配"fayes"的数据
- 验证
dismax查询的qf配置是否合理
3. 确认类路径与包名一致性
确保你的Jar包中TypeAheadResponseWriter的包名确实是cqw,与配置中的class="cqw.TypeAheadResponseWriter"完全一致。可以解压Jar包,查看目录结构是否为cqw/TypeAheadResponseWriter.class。
4. 添加日志调试,确认方法是否被调用
在代码中添加日志输出,确认ResponseWriter是否被正确初始化和调用:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TypeAheadResponseWriter implements QueryResponseWriter { private static final Logger log = LoggerFactory.getLogger(TypeAheadResponseWriter.class); private Set<String> fields; @Override public void write(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) throws IOException { log.info("TypeAheadResponseWriter is handling request with query: {}", req.getParams().get("q")); // ... 后续代码 } @Override public void init(NamedList<?> args) { log.info("Initializing TypeAheadResponseWriter"); fields = new HashSet<>(); fields.add("title"); } // ... 其他方法 }
然后查看Solr的日志文件,确认这些日志是否输出,以此判断组件是否被正确加载和调用。
5. 检查Solr版本兼容性
你使用的是Solr 7.3.0,确认代码导入的是正确的Solr 7.x包:
import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.QueryResponseWriter; import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.common.util.NamedList; import org.apache.solr.search.DocList; import org.apache.solr.search.DocIterator; import org.apache.solr.search.SolrIndexSearcher; import org.apache.solr.common.document.Document;
内容的提问来源于stack exchange,提问作者Bibek Shakya

