• 自己写的一个Solr搜索实例,增删改查+高亮+分页


    今天个人coding的模块测试,所以闲暇之余继续研究solr,然后顺带写了一个实例,随便搞的,solr真心不熟,期待认识热爱搜索的朋友,共同进步.

    1.配置schema.xml文件[solrcollection1conf目录下]

    因为schema默认定义了一些Field,我们这里选取[id,title,description, author]这几个属性,将id主键type配置为string,其它几个type配置为自定义的ik分词器

       <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> 
       <field name="title" type="text_ik" indexed="true" stored="true" multiValued="true"/>
       <field name="description" type="text_ik" indexed="true" stored="true"/>
       <field name="author" type="text_ik" indexed="true" stored="true"/>
       <field name="keywords" type="text_ik" indexed="true" stored="true"/>

    Ik分词器定义如下

        <!--定义IK分词类型-->
        <fieldType name="text_ik" class="solr.TextField">
            <!--索引时候的分词器-->
              <analyzer type="index" isMaxWordLength="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
            <!--查询时候的分词器-->
            <analyzer type="query" isMaxWordLength="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
        </fieldType>

    2. 编写solr操作类SearchEngine.java,solrJ操作索引参看文章: http://www.cnblogs.com/dennisit/p/3623974.html
    3.这里演示solrj搜索高亮

    /**
         * solrJ搜索 高亮显示 
         * 
         * @author pudongping
         * 
         * @param server
         *                     solr客户端
         * @param queryString
         *                     查询串
         * @param pageNum
         *                     分页 页码
         * @param pageSize
         *                     每页显示大小
         * @return
         */
        public static Page<QzoneArticle> queryComHighlight(SolrServer server, String queryString, int pageNum,int pageSize){
            SolrQuery query = new SolrQuery();
            query.setQuery(queryString);
            query.setHighlight(true);//开启高亮功能
            query.addHighlightField("description");//高亮字段
            query.addHighlightField("keywords");
            query.setHighlightSimplePre("<font color='red'>");//渲染标签
            query.setHighlightSimplePost("</font>");//渲染标签 
            query.setStart((pageNum-1)*pageSize);
            query.setRows(pageSize);
            QueryResponse response = null;
            try {
                response = server.query(query);
            } catch (SolrServerException e) {
                e.printStackTrace();
                return null;
            }
            //查询结果集
            SolrDocumentList lists = response.getResults();
            
            //对象结果集
            List<QzoneArticle> items = new ArrayList<QzoneArticle>();
            
            //查询到的记录总数
            long totalRow = Long.valueOf(response.getResults().getNumFound()).intValue();
            
            String tmpId = "";
            
            Map<String,Map<String,List<String>>> highlightMap=response.getHighlighting();
             for (SolrDocument solrDocument : lists) {
                 QzoneArticle at = new QzoneArticle();
                 tmpId=solrDocument.getFieldValue("id").toString();
                 at.setId(tmpId);
                 at.setAuthor(solrDocument.getFieldValue("author").toString());
                 List<String> descList=highlightMap.get(tmpId).get("description");
                 List<String> keywsList=highlightMap.get(tmpId).get("keywords");
                 if(descList!=null && descList.size()>0){
                     at.setDescription(descList.get(0));
                 }else{
                     //获取并设置高亮的字段title
                     at.setDescription(solrDocument.getFieldValue("description").toString());
                 }
                 if(keywsList!=null && keywsList.size()>0){
                     at.setKeywords(keywsList.get(0));
                 }else{
                     at.setKeywords(solrDocument.getFieldValue("keywords").toString());
                 }
                 items.add(at);
             }
             
            //填充page对象
            return new Page<QzoneArticle>(pageNum, pageSize, totalRow, items);
            
        }

    搜索高亮是找到关键字所在的记录域,然后追加前后缀,重新填充到对象,这里拆开来将是两个步骤,第一步设置高亮域,第二步查询结果追加渲染标记,填充到对象.所以这个可以抽取出来写成一个公用的方法

    4.抽取高亮操作,实现公用方法

        /**
         * 根据关键字查询 [测试通过 - 使用 solr内部转换机制]
         * @param <T>
         * @param server    solr客户端
         * @param keyword    搜索关键字
         * @param pageNum    当前页码
         * @param pageSize    每页显示的大小
         * @param clzz        对象类型
         * @return
         */
        public static <T>Page<T> queryHighter(SolrServer server,String solrql,
                int pageNum,int pageSize,List<String> hlField, String preTag,String postTag,Class<T> clzz,String idName){
            SolrQuery query = new SolrQuery();
            query.setQuery(solrql);
            //设置高亮显示
            query.setHighlight(true);
            //添加高亮域
            for(String hlf : hlField){
                query.addHighlightField(hlf);
            }
            //渲染标签
            query.setHighlightSimplePre(preTag);
            query.setHighlightSimplePost(postTag);
            //分页查询
            query.setStart((pageNum-1)*pageSize);
            query.setRows(pageSize);
            QueryResponse response = null;
            try {
                response = server.query(query);
            } catch (SolrServerException e) {
                e.printStackTrace();
                return null;
            }
            
            //查询到的记录总数
            long totalRow = Long.valueOf(response.getResults().getNumFound()).intValue();
            //查询结果集
            List<T> items = new ArrayList<T>();
            
            //查询结果集
            SolrDocumentList solrDocuments = response.getResults();
            try {
                Object obj = null;
                Method m = null;
                Class<?> fieldType = null;
                Map<String,Map<String,List<String>>> highlightMap=response.getHighlighting();
                for(SolrDocument solrDocument : solrDocuments) {
                        obj = clzz.newInstance();
                        Collection<String> fieldNames = solrDocument.getFieldNames();            //得到所有的属性名
                        for (String fieldName : fieldNames) {
                            //需要说明的是返回的结果集中的FieldNames()比类属性多
                            Field[] filedArrays = clzz.getDeclaredFields();                        //获取类中所有属性
                            for (Field f : filedArrays) {    
                                //如果实体属性名和查询返回集中的字段名一致,填充对应的set方法
                                if(f.getName().equals(fieldName)){
                                    
                                    //获取到的属性名
                                    //private java.lang.String com.test.model.Article.id
                                    f = clzz.getDeclaredField(fieldName);    
                                    
                                    //属性类型
                                    //private java.lang.String com.test.model.Article.id
                                    fieldType = f.getType();    
                                    
                                    //构造set方法名  setId
                                    String dynamicSetMethod = dynamicMethodName(f.getName(), "set");
                                    
                                    //获取方法
                                    //public void com.test.model.Article.setId(java.lang.String)
                                    m = clzz.getMethod(dynamicSetMethod, fieldType);
                                    
                                    //获取到的值
                                    LOG.info(f.getName() + "-->" + dynamicSetMethod+ "=" + fieldType.cast(solrDocument.getFieldValue(fieldName)));
                                    
                                    //获取fieldType类型
                                    fieldType = getFileType(fieldType);
                                    
                                    //获取到的属性
                                    m.invoke(obj, fieldType.cast(solrDocument.getFieldValue(fieldName)));
                                    
                                    for(String hl : hlField){
                                        if(hl.equals(fieldName)){
                                            String idv = solrDocument.getFieldValue(idName).toString();
                                            List<String> hlfList=highlightMap.get(idv).get(fieldName);
                                            if(null!=hlfList && hlfList.size()>0){
                                                //高亮添加
                                                m.invoke(obj, fieldType.cast(hlfList.get(0)));
                                            }else{
                                                //正常添加
                                                m.invoke(obj, fieldType.cast(solrDocument.getFieldValue(fieldName)));
                                            }
                                        }
                                    }
                                    
                                    
                                }
                                
                            }
                            
                        }
                        items.add(clzz.cast(obj));
                }
                
            } catch (Exception e) {
                LOG.error("highlighter query error." + e.getMessage(), e);
                e.printStackTrace();
            }
    
            //填充page对象
            return new Page<T>(pageNum, pageSize, totalRow, items);
        }
        
        public static Class<?> getFileType(Class<?> fieldType){
            // 如果是 int, float等基本类型,则需要转型
            if (fieldType.equals(Integer.TYPE)) {
                return Integer.class;
            } else if (fieldType.equals(Float.TYPE)) {
                return Float.class;
            } else if (fieldType.equals(Double.TYPE)) {
                return  Double.class;
            } else if (fieldType.equals(Boolean.TYPE)) {
                return  Boolean.class;
            } else if (fieldType.equals(Short.TYPE)) {
                return  Short.class;
            } else if (fieldType.equals(Long.TYPE)) {
                return  Long.class;
            } else if(fieldType.equals(String.class)){
                return  String.class;
            }else if(fieldType.equals(Collection.class)){
                return  Collection.class;
            }
            return null;
        }

    需要说明的是,这里的方法定义并不是很完善,因为反射的属性可能是一个集合,所以在利用反射转换之前,需要进行更精确地判断,这实例中实体对象中的属性为简单类型,所以这个方法可以处理.

    5.junit测试

    package com.test.search;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.UUID;
    
    import org.apache.solr.client.solrj.SolrServer;
    import org.junit.Before;
    import org.junit.Test;
    
    import com.plugin.page.Page;
    import com.plugin.solr.client.SolrClient;
    import com.plugin.solr.engine.SolrEngineHandler;
    import com.test.model.QzoneArticle;
    
    
    public class SolrTest {
    
        private SolrServer server;
        
        @Before
        public void init(){
            String solrURL = "http://localhost:8888/solr"; 
            server = SolrClient.getHttpSolrServer(solrURL);
        }
    
        
        @Test
        public void qzoneAdd(){
            List<QzoneArticle> lists = new ArrayList<QzoneArticle>();
            QzoneArticle qz1 = new QzoneArticle();
            qz1.setId(UUID.randomUUID().toString());
            qz1.setAuthor("苏若年");
            qz1.setDescription("Java程序猿, 爱音乐,爱生活,爱文字");
            qz1.setKeywords("Java,音乐,生活,文字");
            
            QzoneArticle qz2 = new QzoneArticle();
            qz2.setId(UUID.randomUUID().toString());
            qz2.setAuthor("林云熙");
            qz2.setDescription("文字控,我无悔,纵是情殇离人泪");
            qz2.setKeywords("文字");
            
            lists.add(qz1);
            lists.add(qz2);
            
            SearchEngine.addBeans(server, lists);
        }
        
        @Test
        public void qzoneDeLId(){
            String id = "4f1b6b87-c824-4e38-a431-9a8f50e7af0c";
            SolrEngineHandler.deleteById(server, "id", id);
        }
        
    
        @Test
        public void qzoneDeLIds(){
            List<String> ids = new ArrayList<String>();
            ids.add("d026e3ef-b89a-4ce2-9fbb-aa195ed2070b");
            ids.add("9deb98ca-5a65-424d-95ad-91e87c2bde2c");
            ids.add("5576650d-5517-43d5-987c-6d7135588e1f");
            SolrEngineHandler.deleteByIds(server, "id", ids);
        }
        
        @Test
        public void qzoneDeLAll(){
            SolrEngineHandler.deleteAllIndex(server);
        }
        
        @Test
        public void qzoneHLQuery(){
            String solrql = "keywords:文字";
            List<String> hlFields = new ArrayList<String>();
            hlFields.add("description");
            hlFields.add("keywords");
            String preTag = "<font color='red'>";
            String postTag = "</font>";
            Page<QzoneArticle> page = SearchEngine.queryHighter(server,solrql , 1, 10, hlFields, preTag, postTag, QzoneArticle.class, "id");
            formatPrint(page, solrql);
        }
        
        
        //测试通过
        @Test
        public void qzoneCommonHLQuery(){
            String solrql = "description:文字";
            Page<QzoneArticle> page = SearchEngine.queryComHighlight(server, solrql , 1, 10);
            formatPrint(page, solrql);
        }
        
        @Test
        public void qzoneQuery(){
            String solrql = "文字";
            Page<QzoneArticle> page = SearchEngine.query(server,solrql , 1, 10,QzoneArticle.class);
            formatPrint(page, solrql);
        }
        
        @Test
        public void qzoneUpdate(){
            QzoneArticle qz = new QzoneArticle();
            qz.setId("5576650d-5517-43d5-987c-6d7135588e1f");
            qz.setAuthor("林云熙");
            qz.setDescription("文字控,我无悔,纵是情殇离人泪");
            qz.setKeywords("文字");
            SearchEngine.updateBean(server, qz, "id");
        }
    
        @Test
        public void pingSolr(){
            System.out.println("ping solr result: " +SolrEngineHandler.ping(server));
        }
    
        
        public void formatPrint(Page<QzoneArticle> page,String solrql){
            System.out.println("查询: " + solrql 
                    + "		页码" + page.getPageNum() 
                    + "/" + page.getTotalPage() 
                    + ",总共找到" + page.getTotalRow()+"条符合的记录.
    ");
            
            for(QzoneArticle qz: page.getItems()){
                System.out.println("作者:" + qz.getAuthor());
                System.out.println("描述:" + qz.getDescription());
                System.out.println("关键字:" + qz.getKeywords() + "
    
    ");
            }
        }
        
    }

    搜索结果集展示如下:

    查询: keywords:文字        页码1/1,总共找到2条符合的记录.
    
    作者:林云熙
    描述:<font color='red'>文字</font>控,我无悔,纵是情殇离人泪
    关键字:<font color='red'>文字</font>
    
    
    作者:苏若年
    描述:Java程序猿, 爱音乐,爱生活,爱<font color='red'>文字</font>
    关键字:Java,音乐,生活,<font color='red'>文字</font>

    转载请注明出处:[http://www.cnblogs.com/dennisit/p/3623984.html]

  • 相关阅读:
    UVa 116 单向TSP(多段图最短路)
    POJ 1328 Radar Installation(贪心)
    POJ 1260 Pearls
    POJ 1836 Alignment
    POJ 3267 The Cow Lexicon
    UVa 1620 懒惰的苏珊(逆序数)
    POJ 1018 Communication System(DP)
    UVa 1347 旅行
    UVa 437 巴比伦塔
    UVa 1025 城市里的间谍
  • 原文地址:https://www.cnblogs.com/dennisit/p/3623984.html
Copyright © 2020-2023  润新知