2021SC@SDUSC
SolrController
什么是Solr
Solr(读作“solar”)是Apache Lucene项目的开源企业搜索平台。其主要功能包括全文检索、命中标示[1]、分面搜索、动态聚类、数据库集成,以及富文本(如Word、PDF)的处理。Solr是高度可扩展的,并提供了分布式搜索和索引复制。Solr是最流行的企业级搜索引擎,[2]Solr 4还增加了NoSQL支持。[3]
Solr是用Java编写、运行在Servlet容器(如Apache Tomcat或Jetty)的一个独立的全文搜索服务器。 Solr采用了Lucene Java搜索库为核心的全文索引和搜索,并具有类似REST的HTTP/XML和JSON的API。 Solr强大的外部配置功能使得无需进行Java编码,便可对其进行调整以适应多种类型的应用程序。Solr有一个插件架构,以支持更多的高级定制。
可以认为Solr是一个NoSQL,类似于MongoDB那样的文档型数据库,它拥有很多个core,每个core中有不同的数据集,它支持很多操作,比如分词搜索,模糊搜索效率高,分摊关系型数据库压力。
服务接口
@RestController
@RequestMapping("/solr")
public class SolrController {
@Autowired
private SolrService solrService;
/**
* 查询方法
* @param coreName 查询的solr的core名称
* @param defaultField 默认查询字段
* @param query 查询关键词
* @param sortField 排序字段 格式:字段 asc\desc 字段与排序规则用空格分割
* @param order 排序规则
* @param start 起始位置
* @param rows 返回条数
* @param mode 搜索模式
* @param filterQueries 补充查询条件 格式:字段:keyword
*/
@RequestMapping(value = "/query", method = RequestMethod.POST)
@ResponseBody
public QueryResults query(String coreName,
String defaultField,
String query,
String sortField,
String order,
Integer start,
Integer rows,
String mode,
String... filterQueries) throws SolrServerException, IOException {
return solrService.query(coreName, defaultField, query, sortField, order, start, rows, mode, filterQueries);
}
@RequestMapping(value = "/getSVG", method = RequestMethod.POST)
public String getSVG(String aid, String keyword, String width, String height, String mode) throws SolrServerException, IOException {
return solrService.getSVG(aid, keyword, width, height, mode);
}
@RequestMapping(value = "/getPNG", method = RequestMethod.POST)
public String getPNG(String pid) throws SolrServerException, IOException, HttpStatusException {
return solrService.getPNG(pid);
}
@RequestMapping(value = "/getPNGs", method = RequestMethod.POST)
public List<String> getPNGs(String pids) throws SolrServerException, IOException, HttpStatusException {
return solrService.getPNGs(pids);
}
}
观察SolrService实现类:
@Component
public class SolrServiceImpl implements SolrService {
@Autowired
private SolrClient solrClient;
@Autowired
ParserObject m;
@Autowired
SolrInput solrInput;
@Override
public QueryResults query(String coreName,
String defaultField,
String query,
String sortField,
String order,
Integer start,
Integer rows,
String mode,
String... filterQueries) throws SolrServerException, IOException {
...
}
...
@Override
public String getSVG(String aid, String keyword, String width, String height, String mode) throws SolrServerException, IOException {
...
}
@Override
public String getPNG(String pid) throws HttpStatusException {
...
}
@Override
public List<String> getPNGs(String pids) throws HttpStatusException {
...
}
...
}
我们可以看到他有三个成员,分别是
- SolrClient
- ParserObject (没有用)
- SolrInput (没有用)
我们一个一个看:
SolrClient
SolrClient就是一个Apache帮我们封装好的Solr服务访问器,我们可以通过它来查询数据,它会给我们返回结果
还可以通过它来增删改数据。
ParserObject
用于处理mongoDB返回过来的数据(不过源码中并没有使用这一个成员的地方)
SolrInput
封装了SolrClient,不过也是并没有在源码中用到
首先是query接口:
@Override
public QueryResults query(String coreName,
String defaultField,
String query,
String sortField,
String order,
Integer start,
Integer rows,
String mode,
String... filterQueries) throws SolrServerException, IOException {
SolrQueryBuilder solrQueryBuilder = new SolrQueryBuilder();
SolrQuery solrQuery = solrQueryBuilder.setDefaultField(defaultField)
.setQuery(query)
.setSortField(sortField)
.setOrder(order)
.setStart(start)
.setRows(rows)
.setMode(mode)
.setFilterQueries(filterQueries)
.build();
System.out.println(solrQuery);
QueryResponse queryResponse = solrClient.query(coreName,solrQuery);
SolrDocumentList results = queryResponse.getResults();
System.out.println(results.getNumFound());
QueryResults queryResults = new QueryResults(results.getNumFound(), results);
System.out.println(queryResults);
return queryResults;
}
SolrQueryBuilder 是封装好了的SolrQuery生成器,对于SolrQuery中每一个需要设置的属性都有默认值,并且提供方便的设定查询值得方法,并有规范性检测。
QueryResults 也是封装好的实体,其中只有两个成员,一个是返回的结果SolrDocumentList, 另一个是结果个数
但是实际上SolrDocumentList中已经有获取结果个数得方法了,这个封装完全是多余的。
其次是核心接口getSVG:
@Override
public String getSVG(String aid, String keyword, String width, String height, String mode) throws SolrServerException, IOException {
//获取aid对应的文章
JSONArray article_array = this.queryArticle("dms_article","_id", aid);
SolrDocument article = (SolrDocument) article_array.get(0);
//得到文章对应的page列表
List<HashMap<String, String>> list = this.getPageInfo(o2s(JSONObject.parseArray(JSON.toJSONString(article.get("page")))));
list.remove(list.size()-1);
ArrayList<PageInfo> page_list = new ArrayList<>();
for (HashMap<String, String> stringStringHashMap : list) {
PageInfo info = new PageInfo(stringStringHashMap);
//进行缩放的操作
info.setScale(width, height);
page_list.add(info);
}
//获取词的信息
JSONArray word_array = this.queryWord("dms_word","word", keyword, aid);
if(!word_array.isEmpty()){
List<SolrDocument> word_list = new ArrayList<>();
for(Object o : word_array){
word_list.add((SolrDocument) o);
}
for(SolrDocument s : word_list){
List<String> point_list = o2s(JSONObject.parseArray(JSON.toJSONString(s.get("position"))));
for(String p : point_list){
String[] point_array = p.split("\\|");
String page = point_array[0];
for(int i = 1; i < point_array.length; i++){
ArrayList<String> position = new ArrayList<>();
String[] points = point_array[i].split(";");
for(String point : points){
String[] point_i = point.split(":");
position.add(point_i[0]);
position.add(point_i[1]);
}
for(PageInfo page_info : page_list){
if(page_info.getId().equals(page)){
page_info.addWordPolygon(position);
}
}
}
}
}
}else if (!mode.equals("precise")){
//每一个字的信息
solrQueryCharacter(aid, keyword, article, page_list);
}
System.out.println(page_list);
return page_list.toString();
}
先通过aid来查找出文章,然后解析出文章得每一个page,并将其整合成PageInfo对象列表
由于数据库中存储的内容是json风格,需要将其转换成SVG格式,所以封装了很多得操作,比如说如何将json中离散的字符通过word提供的字符序号列表来还原成文字等等。
下面两个getPNG和getPNGs都是通过调用其他微服务(这里是另一个服务器得mysql数据库中的数据)并返回。
总的来说SolrController就是通过solr存储文章数据,并且将json格式得数据转换成SVG格式。