zoukankan      html  css  js  c++  java
  • JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

    1. 学习计划

    1、Solr服务搭建

    2、Solrj使用测试

    3、把数据库中的数据导入索引库

    4、搜索功能的实现

    2. Solr服务搭建

    2.1. Solr的环境

    Solrjava开发。

    需要安装jdk

    安装环境Linux

    需要安装Tomcat

    2.2. 搭建步骤

    第一步:把solr 的压缩包上传到Linux系统

    第二步:解压solr

    第三步:安装Tomcat,解压缩即可。

    第四步:把solr部署到Tomcat下。

    第五步:解压缩war包。启动Tomcat解压。

    tail -f ../logs/catalina.out 查看tomcat运行情况 f是循环读取的意思

    第六步:把/root/solr-4.10.3/example/lib/ext目录下的所有的jar包,添加到solr工程中。

    [root@localhost ext]# pwd

    /root/solr-4.10.3/example/lib/ext

    [root@localhost ext]# cp * /usr/local/solr/tomcat/webapps/solr/WEB-INF/lib/

    第七步:创建一个solrhome/example/solr目录就是一个solrhome。复制此目录到/usr/local/solr/solrhome

    [root@localhost example]# pwd

    /root/solr-4.10.3/example

    [root@localhost example]# cp -r solr /usr/local/solr/solrhome

    [root@localhost example]#

    第八步:关联solrsolrhome。需要修改solr工程的web.xml文件。

    第九步:启动Tomcat

    http://192.168.25.154:8080/solr/

    windows下的配置完全一样。

    2.3. 配置业务域

    schema.xml中定义

    1、商品Id

    2、商品标题

    3、商品卖点

    4、商品价格

    5、商品图片

    6、分类名称

    创建对应的业务域。需要制定中文分析器。

    创建步骤:

    第一步:把中文分析器添加到工程中。

    1、IKAnalyzer2012FF_u1.jar添加到solr工程的lib目录下

    2、把扩展词典、配置文件放到solr工程的WEB-INF/classes目录下。

    第二步:配置一个FieldType,制定使用IKAnalyzer

    修改schema.xml文件

    修改Solrschema.xml文件,添加FieldType

    <fieldType name="text_ik" class="solr.TextField">

      <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>

    </fieldType>

    第三步:配置业务域,type制定使用自定义的FieldType

    设置业务系统Field

    <field name="item_title" type="text_ik" indexed="true" stored="true"/>

    <field name="item_sell_point" type="text_ik" indexed="true" stored="true"/>

    <field name="item_price"  type="long" indexed="true" stored="true"/>

    <field name="item_image" type="string" indexed="false" stored="true" />

    <field name="item_category_name" type="string" indexed="true" stored="true" />

    <field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>

    <copyField source="item_title" dest="item_keywords"/>

    <copyField source="item_sell_point" dest="item_keywords"/>

    <copyField source="item_category_name" dest="item_keywords"/>

    第四步:重启tomcat

    3. 搜索工程搭建

     

    要实现搜索功能,需要搭建solr服务、搜索服务工程、搜索系统

    3.1. 搜索服务工程搭建

    可以参考e3-manager创建。

    e3-search(聚合工程pom

    |--e3-search-interfacejar

    |--e3-search-Servicewar

    e3-search-webwar

     

    4. 使用solrJ管理索引库

    使用SolrJ可以实现索引库的增删改查操作。

    4.1. 添加文档

    第一步:把solrJjar包添加到工程中。

    第二步:创建一个SolrServer,使用HttpSolrServer创建对象。

    第三步:创建一个文档对象SolrInputDocument对象。

    第四步:向文档中添加域。必须有id域,域的名称必须在schema.xml中定义。

    第五步:把文档添加到索引库中。

    第六步:提交。

    @Test
        public void addDocument() throws Exception {
            // 第一步:把solrJ的jar包添加到工程中。
            // 第二步:创建一个SolrServer,使用HttpSolrServer创建对象。
            SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
            // 第三步:创建一个文档对象SolrInputDocument对象。
            SolrInputDocument document = new SolrInputDocument();
            // 第四步:向文档中添加域。必须有id域,域的名称必须在schema.xml中定义。
            document.addField("id", "test001");
            document.addField("item_title", "测试商品");
            document.addField("item_price", "199");
            // 第五步:把文档添加到索引库中。
            solrServer.add(document);
            // 第六步:提交。
            solrServer.commit();
        }


    4.2. 删除文档
     

    4.2.1. 根据id删除

    第一步:创建一个SolrServer对象。

    第二步:调用SolrServer对象的根据id删除的方法。

    第三步:提交。

    @Test
        public void deleteDocumentById() throws Exception {
            // 第一步:创建一个SolrServer对象。
            SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
            // 第二步:调用SolrServer对象的根据id删除的方法。
            solrServer.deleteById("1");
            // 第三步:提交。
            solrServer.commit();
        }


    4.2.2. 根据查询删除
     

    @Test
        public void deleteDocumentByQuery() throws Exception {
            SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
            solrServer.deleteByQuery("title:change.me");
            solrServer.commit();
        }


    4.3. 查询索引库
     

    查询步骤:

    第一步:创建一个SolrServer对象

    第二步:创建一个SolrQuery对象。

    第三步:向SolrQuery中添加查询条件、过滤条件。。。

    第四步:执行查询。得到一个Response对象。

    第五步:取查询结果。

    第六步:遍历结果并打印。

    4.3.1. 简单查询

    @Test
        public void queryDocument() throws Exception {
            // 第一步:创建一个SolrServer对象
            SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
            // 第二步:创建一个SolrQuery对象。
            SolrQuery query = new SolrQuery();
            // 第三步:向SolrQuery中添加查询条件、过滤条件。。。
            query.setQuery("*:*");
            // 第四步:执行查询。得到一个Response对象。
            QueryResponse response = solrServer.query(query);
            // 第五步:取查询结果。
            SolrDocumentList solrDocumentList = response.getResults();
            System.out.println("查询结果的总记录数:" + solrDocumentList.getNumFound());
            // 第六步:遍历结果并打印。
            for (SolrDocument solrDocument : solrDocumentList) {
                System.out.println(solrDocument.get("id"));
                System.out.println(solrDocument.get("item_title"));
                System.out.println(solrDocument.get("item_price"));
            }
        }


    4.3.2. 带高亮显示
     

    @Test
        public void queryDocumentWithHighLighting() throws Exception {
            // 第一步:创建一个SolrServer对象
            SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
            // 第二步:创建一个SolrQuery对象。
            SolrQuery query = new SolrQuery();
            // 第三步:向SolrQuery中添加查询条件、过滤条件。。。
            query.setQuery("测试");
            //指定默认搜索域
            query.set("df", "item_keywords");
            //开启高亮显示
            query.setHighlight(true);
            //高亮显示的域
            query.addHighlightField("item_title");
            query.setHighlightSimplePre("<em>");
            query.setHighlightSimplePost("</em>");
            // 第四步:执行查询。得到一个Response对象。
            QueryResponse response = solrServer.query(query);
            // 第五步:取查询结果。
            SolrDocumentList solrDocumentList = response.getResults();
            System.out.println("查询结果的总记录数:" + solrDocumentList.getNumFound());
            // 第六步:遍历结果并打印。
            for (SolrDocument solrDocument : solrDocumentList) {
                System.out.println(solrDocument.get("id"));
                //取高亮显示
                Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
                List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
                String itemTitle = null;
                if (list != null && list.size() > 0) {
                    itemTitle = list.get(0);
                } else {
                    itemTitle = (String) solrDocument.get("item_title");
                }
                System.out.println(itemTitle);
                System.out.println(solrDocument.get("item_price"));
            }
        }


    5. 
    把商品数据导入到索引库中 

    5.1. Dao

    5.1.1. Sql语句

    SELECT
        a.id,
        a.title,
        a.sell_point,
        a.price,
        a.image,
        b.`name` category_name
    FROM
        `tb_item` a
    LEFT JOIN tb_item_cat b ON a.cid = b.id
    WHERE a.`status`=1


     
    需要自己创建
    Mapper文件。

    5.1.2. 创建对应数据集的pojo

    public class SearchItem implements Serializable{
        private String id;
        private String title;
        private String sell_point;
        private long price;
        private String image;
        private String category_name;
    }


    5.1.3. 接口定义
     

    public interface ItemMapper {

    List<SearchItem> getItemList();

    } 


    5.1.4. Mapper映射文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="cn.e3mall.search.mapper.ItemMapper" >
        
        <select id="getItemList" resultType="cn.e3mall.common.pojo.SearchItem">
            SELECT
                a.id,
                a.title,
                a.sell_point,
                a.price,
                a.image,
                b.`name` category_name
            FROM
                `tb_item` a
            LEFT JOIN tb_item_cat b ON a.cid = b.id
            WHERE a.`status`=1
        </select>
    
    </mapper>


    5.2. Service
     

    5.2.1. 功能分析

    1、查询所有商品数据。

    2、循环把商品数据添加到索引库。使用solrJ实现。

    3、返回成功。返回E3Result

    参数:无

    返回值:E3Result

    5.2.2. solrJ添加索引库

    1、solrJjar包添加到工程。

    2、创建一个SolrServer对象。创建一个和sorl服务的连接。HttpSolrServer

    3、创建一个文档对象。SolrInputDocument

    4、向文档对象中添加域。必须有一个id域。而且文档中使用的域必须在schema.xml中定义。

    5、把文档添加到索引库

    6、Commit

    @Test
        public void addDocument() throws Exception {
            // 1、把solrJ的jar包添加到工程。
            // 2、创建一个SolrServer对象。创建一个和sorl服务的连接。HttpSolrServer。
            //如果不带Collection默认连接Collection1
            SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
            // 3、创建一个文档对象。SolrInputDocument。
            SolrInputDocument document = new SolrInputDocument();
            // 4、向文档对象中添加域。必须有一个id域。而且文档中使用的域必须在schema.xml中定义。
            document.addField("id", "test001");
            document.addField("item_title", "测试商品");
            // 5、把文档添加到索引库
            solrServer.add(document);
            // 6、Commit。
            solrServer.commit();
        }


    5.2.3. 代码实现
     

    /**
     * 将商品数据导入索引库
     * <p>Title: SearchItemServiceImpl</p>
     * <p>Description: </p>
     * <p>Company: www.itcast.cn</p> 
     * @version 1.0
     */
    @Service
    public class SearchItemServiceImpl implements SearchItemService {
    
        @Autowired
        private ItemMapper itemMapper;
        @Autowired
        private SolrServer solrServer;
        
        @Override
        public E3Result importItmes() {
            try {
                //查询商品列表
                List<SearchItem> itemList = itemMapper.getItemList();
                //导入索引库
                for (SearchItem searchItem : itemList) {
                    //创建文档对象
                    SolrInputDocument document = new SolrInputDocument();
                    //向文档中添加域
                    document.addField("id", searchItem.getId());
                    document.addField("item_title", searchItem.getTitle());
                    document.addField("item_sell_point", searchItem.getSell_point());
                    document.addField("item_price", searchItem.getPrice());
                    document.addField("item_image", searchItem.getImage());
                    document.addField("item_category_name", searchItem.getCategory_name());
                    //写入索引库
                    solrServer.add(document);
                }
                //提交
                solrServer.commit();
                //返回成功
                return E3Result.ok();
                
            } catch (Exception e) {
                e.printStackTrace();
                return E3Result.build(500, "商品导入失败");
            }
        }
    
    }


    5.2.4. SolrServer
    的配置 

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
    
        <bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
            <constructor-arg index="0" value="http://192.168.25.154:8080/solr"/>
        </bean>
    
    </beans>


    5.2.5. 发布服务
     

     

    5.3. 表现层

    后台管理工程中调用商品导入服务。

     

    5.3.1. 功能分析

     

    请求的url/index/item/import

    响应的结果:json数据。可以使用E3Result

    5.3.2. Controller

    @Controller
    public class SearchItemController {
    
        @Autowired
        private SearchItemService searchItemService;
        
        @RequestMapping("/index/item/import")
        @ResponseBody
        public E3Result impotItemIndex() {
            E3Result result = searchItemService.importItmes();
            return result;
        }
    
    }


    5.4. 
    解决Mapper映射文件不存在异常 

    e3-search-servicepom文件中需要添加资源配置。

    <!-- 如果不添加此节点mybatis的mapper.xml文件都会被漏掉。 -->
        <build>
            <resources>
                <resource>
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>false</filtering>
                </resource>
                <resource>
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>false</filtering>
                </resource>
            </resources>
        </build>


      

    6. 搜索功能实现

    6.1. 使用sorlJ 查询索引库

    //使用solrJ实现查询
        @Test
        public void queryDocument() throws Exception {
            //创建一个SolrServer对象
            SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
            //创建一个查询对象,可以参考solr的后台的查询功能设置条件
            SolrQuery query = new SolrQuery();
            //设置查询条件
    //        query.setQuery("阿尔卡特");
            query.set("q","阿尔卡特");
            //设置分页条件
            query.setStart(1);
            query.setRows(2);
            //开启高亮
            query.setHighlight(true);
            query.addHighlightField("item_title");
            query.setHighlightSimplePre("<em>");
            query.setHighlightSimplePost("</em>");
            //设置默认搜索域
            query.set("df", "item_title");
            //执行查询,得到一个QueryResponse对象。
            QueryResponse queryResponse = solrServer.query(query);
            //取查询结果总记录数
            SolrDocumentList solrDocumentList = queryResponse.getResults();
            System.out.println("查询结果总记录数:" + solrDocumentList.getNumFound());
            //取查询结果
            Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
            for (SolrDocument solrDocument : solrDocumentList) {
                System.out.println(solrDocument.get("id"));
                //取高亮后的结果
                List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
                String title= "";
                if (list != null && list.size() > 0) {
                    //取高亮后的结果
                    title = list.get(0);
                } else {
                    title = (String) solrDocument.get("item_title");
                }
                System.out.println(title);
                System.out.println(solrDocument.get("item_sell_point"));
                System.out.println(solrDocument.get("item_price"));
                System.out.println(solrDocument.get("item_image"));
                System.out.println(solrDocument.get("item_category_name"));
            }
            
        }


    6.2. 功能分析
     

    把搜索结果页面添加到工程中。

     

    请求的url/search

    请求的方法:GET

    参数:

    keyword:查询条件

    Page:页码。如果没有此参数,需要给默认值1

    返回的结果:

    1)商品列表

    2)总页数

    3)总记录数

    使用jsp展示,返回逻辑视图。

    商品列表使用:SearchItem表示。

    需要把查询结果封装到一个pojo中:

    1)商品列表List<SearchItem>

    2)总页数。Int totalPages。总记录数/每页显示的记录数向上取整。把每页显示的记录是配置到属性文件中。

    3)总记录数。Int recourdCount

    public class SearchResult implements Serializable {

      private List<SearchItem> itemList;

      private int totalPages;

      private int recourdCount;

    }

    6.3. Dao

    跟据查询条件查询索引库,返回对应的结果。

    参数:SolrQuery

    返回结果:SearchResult

    @Repository
    public class SearchDao {
    
        @Autowired
        private SolrServer solrServer;
        
        public SearchResult search(SolrQuery query) throws Exception {
            //根据查询条件查询索引库
            QueryResponse queryResponse = solrServer.query(query);
            //取查询结果总记录数
            SolrDocumentList solrDocumentList = queryResponse.getResults();
            long numFound = solrDocumentList.getNumFound();
            //创建一个返回结果对象
            SearchResult result = new SearchResult();
            result.setRecourdCount((int) numFound);
            //创建一个商品列表对象
            List<SearchItem> itemList = new ArrayList<>();
            //取商品列表
            //取高亮后的结果
            Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
            for (SolrDocument solrDocument : solrDocumentList) {
                //取商品信息
                SearchItem searchItem = new SearchItem();
                searchItem.setCategory_name((String) solrDocument.get("item_category_name"));
                searchItem.setId((String) solrDocument.get("id"));
                searchItem.setImage((String) solrDocument.get("item_image"));
                searchItem.setPrice((long) solrDocument.get("item_price"));
                searchItem.setSell_point((String) solrDocument.get("item_sell_point"));
                //取高亮结果
                List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
                String itemTitle = "";
                if (list != null && list.size() > 0) {
                    itemTitle = list.get(0);
                } else {
                    itemTitle = (String) solrDocument.get("item_title");
                }
                searchItem.setTitle(itemTitle);
                //添加到商品列表
                itemList.add(searchItem);
            }
            //把列表添加到返回结果对象中
            result.setItemList(itemList);
            return result;
        }
    }


    6.4. Service
     

    需要有一个接口一个实现类,需要对外发布服务。

    参数:String keyWord

          int page

          int rows

    返回值:SearchResult

    业务逻辑:

    1)根据参数创建一个查询条件对象。需要指定默认搜索域,还需要配置高亮显示。

    2)调用dao查询。得到一个SearchResult对象

    3)计算查询总页数,每页显示记录数就是rows参数。

    @Service
    public class SearchServiceImpl implements SearchService {
    
        @Autowired
        private SearchDao searchDao;
        
        @Value("${DEFAULT_FIELD}")
        private String DEFAULT_FIELD;
        
        @Override
        public SearchResult search(String keyWord, int page, int rows) throws Exception {
            //创建一个SolrQuery对象
            SolrQuery query = new SolrQuery();
            //设置查询条件
            query.setQuery(keyWord);
            //设置分页条件
            query.setStart((page - 1) * rows);
            //设置rows
            query.setRows(rows);
            //设置默认搜索域
            query.set("df", DEFAULT_FIELD);
            //设置高亮显示
            query.setHighlight(true);
            query.addHighlightField("item_title");
            query.setHighlightSimplePre("<em style="color:red">");
            query.setHighlightSimplePost("</em>");
            //执行查询
            SearchResult searchResult = searchDao.search(query);
            //计算总页数
            int recourdCount = searchResult.getRecourdCount();
            int pages = recourdCount / rows;
            if (recourdCount % rows > 0) pages++;
            //设置到返回结果
            searchResult.setTotalPages(pages);
            return searchResult;
        }
    
    }


    6.4.1. 发布服务
     

     

    6.5. 表现层

    6.5.1. 引用服务

    e3-search-web中添加接口依赖

     

    Springmvc.xml

     

    6.5.2. Controller

    请求的url/search

    请求的方法:GET

    参数:

    keyword:查询条件

    Page:页码。如果没有此参数,需要给默认值1

    返回的结果:

    使用jsp展示,返回逻辑视图。

    @Controller
    public class SearchController {
    
        @Autowired
        private SearchService searchService;
        @Value("${PAGE_ROWS}")
        private Integer PAGE_ROWS;
        
        @RequestMapping("/search")
        public String search(String keyword,@RequestParam(defaultValue="1") Integer page, Model model) throws Exception {
            //需要转码
            keyword = new String(keyword.getBytes("iso8859-1"), "utf-8");
            //调用Service查询商品信息 
            SearchResult result = searchService.search(keyword, page, PAGE_ROWS);
            //把结果传递给jsp页面
            model.addAttribute("query", keyword);
            model.addAttribute("totalPages", result.getTotalPages());
            model.addAttribute("recourdCount", result.getRecourdCount());
            model.addAttribute("page", page);
            model.addAttribute("itemList", result.getItemList());
            //返回逻辑视图
            return "search";
        }
        
    }
  • 相关阅读:
    SQL优化之博客案例
    Drools之规则属性
    Android 8.0以上系统应用如何保活
    Android 8.0(api27)静态广播和动态广播接收问题
    Android开发 WorkManager详解
    使用EOS Camera Movie Record 软件在计算机上使用 Canon EOS DSLR相机录制视频 。
    关于使用AlarmManager的注意事项
    系统服务之定时服务(AlarmManager)
    Android定时器AlarmManager
    Android 代码混淆
  • 原文地址:https://www.cnblogs.com/xieyupeng/p/9374655.html
Copyright © 2011-2022 走看看