Java 操作Solr搭建高性能搜索引擎

来源:互联网 发布:女装知茵品牌 编辑:程序博客网 时间:2024/05/18 14:46

       目前比较适合Java的搜索引擎搭建一般会选用Solr,底层操作会使用Solrj交互,其实Solr也是基于Lucene。实施过程中发现网上很多关于Java集成Solr的文档都是基于Solr5+版本的,而对于Solr7+版本的文档很少,并且很多都是坑,所以花了不少时间把自己再部署过程中的经验分享出来。

      首先去官网 Apache Solr官网  下载Solr的7.1,然后上传至服务器,在bin目录下面有个执行文件,通过命令/bin/solr start -force 可以很方便的启动Solr7。

  接下去开始Solr的相关配置:

      1.在solr中新建一个项目,在bin目录下使用solr create -C '库名'

      2.编辑managed-schema配置文件,加入IK分词器,这个分词器对中文支持较好

   <fieldType name="text_ik" class="solr.TextField">    <analyzer type="index" class="org.wltea.analyzer.lucene.IKAnalyzer"/>    <analyzer type="query" class="org.wltea.analyzer.lucene.IKAnalyzer"/>   </fieldType>
     3.配置managed-schema加入字段的通配设置,

       使用这种通配方式配置后,你的程序代码Model中的属性字段可以写成XXX_ikBookStr等即可被Solr识别添加至索引,在查询时也能够使用此字段。
     4.将第一步创建的SolrCore copy到Solr根目录下面,此时访问你的Solr网站即可看到你的SolrCore

       

    5.至此Solr服务端已经搭建完成了,接下去要在程序里面进行编码,首先在pom.xml中引入Solr包支持

    6.然后再model的属性字段set方法上面加上@Field注解,这个注解是用来告诉Solr此字段需要被添加至索引中,但是值得注意的是此字段命名必须符合上面的通配设置规范

  7.接下去就是SpringBoot对于Solr的封装操作了,我是再次做了一次封装便捷实用,贴出我的代码

public class SolrRepository {@Autowiredprivate SolrClient client;private QueryResponse response;private SolrDocumentList results;/** *  *    TODO - 针对Solr进行数据查询   @param query 查询关键字   @param offset 起始位置   @param limit 每次查询条数   @param c 实体类对象   @param bool 是否关闭Solr链接   @param qf 搜索关键字匹配某些字段的打分比其他的字段要高   @param pf 对于某些字段,搜索字符串的密集度(phrase)的打分中占的比重   @param fl 指定需要返回的字段 逗号分隔   @param fq 指定过滤条件   @return   @throws Exception   2017年10月3日   mazkc */public List getSolrData(String query,String offset,String limit,String c,Boolean bool,String qf,String pf,String solrFl,String fq) throws Exception {ModifiableSolrParams params = new ModifiableSolrParams();List beans = null;//如果limit为空 或者 超过限定抓取数量 那么返回nullif(null == limit || "".equals(limit) || Integer.parseInt(limit) > FinalArgs.SERACH_LIMIT){return null;}params.set("q", query);params.set("wt", "json");params.set("start", "0");params.set("rows", "10");params = checkNotNull(params,offset,limit,qf,pf,solrFl,fq);response = client.query(params);if(null == c || "".equals(c)){beans = response.getResults();}else{beans = response.getBeans(Class.forName(c));if(null == beans || beans.size() == 0){beans = new ArrayList<>();beans.add(Class.forName(c).newInstance());}}commitAndCloseSolr(client,bool);return beans;}/** *  *    TODO - 验证Solr查询是否有优化   @param params 参数关键字   @param offset 起始位置   @param limit 请求数据条数   @param qf 匹配权重   @param pf 出现字数权重   @param solrFl 需要返回的字段   @param fq 过滤哪些数据   @return   2017年10月17日   mazkc */private ModifiableSolrParams checkNotNull(ModifiableSolrParams params,String offset,String limit,String qf,String pf,String solrFl,String fq){if(null != offset && !"".equals(offset)){params.set("start", offset);}if(null != limit && !"".equals(limit)){if(Integer.parseInt(limit) >= 200){limit = "200";}params.set("rows", limit);}if(null != qf && !"".equals(qf)){params.set("qf", qf);}if(null != pf && !"".equals(pf)){params.set("pf", pf);}if(null != solrFl && !"".equals(solrFl)){params.set("fl", solrFl);}if(null != fq && !"".equals(fq)){params.set("fq", fq);}params.set("defType", "edismax");return params;}/** *  *    TODO - 针对集合数据对Solr进行数据索引   @param map   @throws Exception   2017年10月2日   mazkc */public void saveSolrDataList(List<Object> li,Boolean bool) throws Exception {if(null != li && li.size() > 0){client.addBeans(li);commitAndCloseSolr(client,bool);}}/** *  *    TODO - 根据索引ID查询solr数据   @param map   @throws Exception   2017年10月2日   mazkc */public SolrDocument getSolrDataById(String id,Boolean bool) throws Exception {SolrDocument so = client.getById(id);commitAndCloseSolr(client,bool);return so;}/** *  *    TODO - 针对单个数据对Solr进行数据索引   @param map   @throws Exception   2017年10月2日   mazkc */public void saveSolrData(Object bean,Boolean bool) throws Exception {if(null != bean){client.addBean(bean);commitAndCloseSolr(client,bool);}}/** *  *    TODO - 根据集合删除所有索引文档   @param map   @throws Exception   2017年10月2日   mazkc */public void delSolrDataList(List<String> li,Boolean bool) throws Exception {if(null != li && li.size() > 0){client.deleteById(li);commitAndCloseSolr(client,bool);}}/** *  *    TODO - 批量删除所有索引文档   @param map   @throws Exception   2017年10月2日   mazkc */public void delSolrDataAll(String query,Boolean bool) throws Exception {client.deleteByQuery(query);commitAndCloseSolr(client,bool);}/** *  *    TODO - 根据ID删除所有索引文档   @param map   @throws Exception   2017年10月2日   mazkc */public void delSolrDataId(String id,Boolean bool) throws Exception {client.deleteById(id);commitAndCloseSolr(client,bool);}/** *  *    TODO - 根据索引ID更新索引数据   @param map   @throws Exception   2017年10月2日   mazkc */public void updateSolrData(String queryId,HashMap<String,Object> map,Boolean bool) throws Exception {SolrInputDocument doc = new SolrInputDocument(); SolrDocument sd = getSolrDataById(queryId, false);Iterator<String> it = sd.keySet().iterator();String key = "";//获取所有源数据信息while(it.hasNext()){key = it.next();doc.addField(key, sd.getFieldValue(key));}Iterator<String> itt = map.keySet().iterator();//将需要更新的数据补充进源数据while(itt.hasNext()){key = itt.next();doc.remove(key);doc.addField(key, map.get(key));}client.add(doc);commitAndCloseSolr(client,bool);}private SolrInputDocument checkDoc(HashMap<String,Object> map,SolrInputDocument doc){if(null != map && null != doc){String key = "";Iterator<String> it = map.keySet().iterator();while(it.hasNext()){key = it.next();doc.addField(key, map.get(key));}}return doc;}/**     * 提交以及关闭服务     *      * @param solrClient     * @throws Exception     */    public void commitAndCloseSolr(SolrClient client,Boolean bool)            throws Exception {    if(null != client){    client.commit();//    if(bool){//    client.close();//    }    }    }}