欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

程序员文章站 2022-05-13 23:45:42
1. 学习计划 1、Solr服务搭建 2、Solrj使用测试 3、把数据库中的数据导入索引库 4、搜索功能的实现 2. Solr服务搭建 2.1. Solr的环境 Solr是java开发。 需要安装jdk。 安装环境Linux。 需要安装Tomcat。 2.2. 搭建步骤 第一步:把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文件。

JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

 

第九步:启动Tomcat

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. 搜索工程搭建

 JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

 

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

 

 

3.1. 搜索服务工程搭建

可以参考e3-manager创建。

e3-search(聚合工程pom

|--e3-search-interfacejar

|--e3-search-Servicewar

e3-search-webwar

 JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

 

 

 

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. 发布服务
 

 JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

 

 

5.3. 表现层

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

 JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

 

5.3.1. 功能分析

 JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

 

请求的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. 功能分析
 

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

 JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

 

请求的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. 发布服务
 

 JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

 

 

6.5. 表现层

6.5.1. 引用服务

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

 JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

 

Springmvc.xml

 JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现

 

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";
    }
    
}