B2Ctt商城08 Solr

一、solr是什么?

是基于Lucene的全文搜索服务器。


二、安装solr

2.1.1   安装步骤

需要把solr服务器安装到linux环境:

第一步:安装linux、jdk、tomcat。

[root@bogon ~]# ll

total 8044

-rw-r--r--. 1 root root 8234674 Oct 27  2013 apache-tomcat-7.0.47.tar.gz

[root@bogon ~]# tar -zxfapache-tomcat-7.0.47.tar.gz

[root@bogon ~]# ll

total 8048

drwxr-xr-x. 9 root root    4096 Sep 10 17:55 apache-tomcat-7.0.47

-rw-r--r--. 1 root root 8234674 Oct 27  2013 apache-tomcat-7.0.47.tar.gz

[root@bogon ~]# mkdir /usr/local/solr

[root@bogon ~]# cp apache-tomcat-7.0.47/usr/local/solr/tomcat

cp: omitting directory`apache-tomcat-7.0.47'

[root@bogon ~]# cp apache-tomcat-7.0.47/usr/local/solr/tomcat -r

[root@bogon ~]# cd /usr/local/solr/

[root@bogon solr]# ll

total 4


第二步:把solr的压缩包上传到服务器。并解压。


第三步:把/root/solr-4.10.3/dist/solr-4.10.3.war包部署到tomcat下。并改名为solr.war

[root@bogon dist]# cp solr-4.10.3.war/usr/local/solr/tomcat/webapps/solr.war


第四步:解压war包。启动tomcat自动解压。关闭tomcat。删除solr.war.


第五步:把/root/solr-4.10.3/example/lib/ext目录下所有的jar包复制到solr工程中。

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


第六步:创建solrhome。Solrhome是存放solr服务器所有配置文件的目录。

[root@bogon example]# pwd

/root/solr-4.10.3/example

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

[root@bogon example]#

第七步:告诉solr服务器solrhome的位置。

需要修改solr工程的web.xml文件。


第八步:启动tomcat




2.2.1 配置业务字段

1、在solr中默认是中文分析器,需要手工配置。配置一个FieldType,在FieldType中指定中文分析器。

2、Solr中的字段必须是先定义后使用。

1.1.1.1        中文分析器的配置

第一步:使用IK-Analyzer。把分析器的文件夹上传到服务器。

第二步:需要把分析器的jar包添加到solr工程中。

[root@bogon IK Analyzer 2012FF_hf1]# cpIKAnalyzer2012FF_u1.jar /usr/local/solr/tomcat/webapps/solr/WEB-INF/lib/

[root@bogon IK Analyzer 2012FF_hf1]#

第三步:需要把IKAnalyzer需要的扩展词典及停用词词典、配置文件复制到solr工程的classpath。

/usr/local/solr/tomcat/webapps/solr/WEB-INF/classes

 

[root@bogon IK Analyzer 2012FF_hf1]# cp KAnalyzer.cfg.xml ext_stopword.dic mydict.dic/usr/local/solr/tomcat/webapps/solr/WEB-INF/classes

[root@bogon IK Analyzer 2012FF_hf1]#

 

注意:扩展词典及停用词词典的字符集必须是utf-8。不能使用windows记事本编辑。

 

第四步:配置fieldType。需要在solrhome/collection1/conf/schema.xml中配置。

技巧:使用vi、vim跳转到文档开头gg。跳转到文档末尾:G

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

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

</fieldType>







1.1.1.1        业务字段配置

业务字段判断标准:

1、在搜索时是否需要在此字段上进行搜索。例如:商品名称、商品的卖点、商品的描述

2、后续的业务是否需要用到此字段。例如:商品id。

 

需要用到的字段:

1、商品id

2、商品title

3、卖点

4、价格

5、商品图片

6、商品分类名称

7、商品描述

 

Solr中的业务字段:

1、id——》商品id

其他的对应字段创建solr的字段。

<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_desc" type="text_ik" indexed="true" stored="false" />

 

<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"/>

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

 

重新启动tomcat


1.1  维护索引库

添加:添加一个json格式的文件就可以。

修改:在solr中没有update,只需要添加一个新的文档,要求文档id和被修改文档的id一致。原理是先删除后添加。

删除:使用xml格式。

删除两种方法:

1、根据id删除:

<delete>

<id>test001</id>

</delete>

<commit/>

2、根据查询删除:

<delete>

<query>*:*</query>

</delete>

<commit/>


3  solrJ客户端

<!-- solr客户端-->

            <dependency>

                  <groupId>org.apache.solr</groupId>

                  <artifactId>solr-solrj</artifactId>

            </ dependency >

测试 添加和删除


public class SolrJTest {

 

      @Test

      public void addDocument() throws Exception {

            //创建一连接

            SolrServer solrServer =new HttpSolrServer("http://192.168.25.154:8080/solr");

            //创建一个文档对象

            SolrInputDocument document =new SolrInputDocument();

            document.addField("id","test001");

            document.addField("item_title","测试商品2");

            document.addField("item_price", 54321);

            //把文档对象写入索引库

            solrServer.add(document);

            //提交

            solrServer.commit();

      }

     

      @Test

      public void deleteDocument() throws Exception {

            //创建一连接

            SolrServer solrServer =new HttpSolrServer("http://192.168.25.154:8080/solr");

            //solrServer.deleteById("test001");

            solrServer.deleteByQuery("*:*");

            solrServer.commit();

      }

}

3.2  把商品信息导入到索引库

使用java程序读取mysql数据库中的商品信息,然后创建solr文档对象,把商品信息写入索引库。

需要发布一个服务。

 

为了灵活的进行分布式部署需要创建一搜素的服务工程发布 搜素服务。Taotao-search。



3.1.1   创建taotao-search工程

需要依赖taottao-common工程

需要依赖的jar包:

Spring的jar包

Springmvc的jar包。

Solrj的jar包。

Mybatis的jar包。


web.xml

<servlet-mapping>

            <servlet-name>taotao-search</servlet-name>

            <url-pattern>/search/*</url-pattern>

      </servlet-mapping>




1.1.1   Sql语句

SELECT

       a.id,

       a.title,

       a.sell_point,

       a.price,

       a.image,

       b.`name`category_name,

       c.item_desc

FROM

       tb_itema

LEFT JOIN tb_item_cat b ON a.cid = b.id

LEFT JOIN tb_item_desc c ON a.id =c.item_id


1.1.1   Dao层

需要创建一个mapper接口+mapper映射文件。名称相同且在同一目录下。


sql语句执行后,没有完全对应的bean, 

创建一个sql语句对应的pojo。


public class Item {

 

      privateString id;

      privateString title;

      privateString sell_point;

      private long price;

      privateString image;

      privateString category_name;

      private String item_des;

}


mapper。xml


<selectid="getItemList"   resultType="com.taotao.search.pojo.Item">

            SELECT

                  a.id,

                  a.title,

                  a.sell_point,

                  a.price,

                  a.image,

                  b. NAME category_name

            FROM

                  tb_item a

            LEFT JOIN tb_item_catb ON a.cid = b.id

      </select>


1.1.1   Service层

核心:将数据导入索引库

功能:导入所有的商品数据。没有参数。返回结果TaotaoResult。

从数据库中查询出所有的商品数据。创建一个SolrInputDocument对象,把对象写入索引库。

@Service

publicclass ItemServiceImpl implements ItemService {

 

      @Autowired

      private ItemMapperitemMapper;

     

      @Autowired

      private SolrServersolrServer;

     

      @Override

      public TaotaoResultimportAllItems() {

            try {

                 

                  //查询商品列表

                  List<Item> list = itemMapper.getItemList();

                  //把商品信息写入索引库

                  for (Itemitem : list) {

                        //创建一个SolrInputDocument对象

                        SolrInputDocument   document =    new SolrInputDocument();

                        document.setField("id", item.getId());

                        document.setField("item_title", item.getTitle());

                        document.setField("item_sell_point", item.getSell_point());

                        document.setField("item_price", item.getPrice());

                        document.setField("item_image", item.getImage());

                        document.setField("item_category_name",item.getCategory_name());

                        document.setField("item_desc", item.getItem_des());

                        //写入索引库

                        solrServer.add(document);

                  }

                  //提交修改

                  solrServer.commit();

            } catch (Exceptione) {

                  e.printStackTrace();

                  return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));

            }

            return TaotaoResult.ok();

      }

 

注入SolrServer

applicationContext-solr.xml

<!-- 配置SolrServer对象 -->

      <!--单机版 -->

      <beanid="httpSolrServer"class="org.apache.solr.client.solrj.impl.HttpSolrServer">

            <constructor-arg name="baseURL" value="${SOLR.SERVER.URL}"></constructor-arg>

      </bean>



1.1.1   Controller层

功能:发布一个rest形式的服务。调用Service的服务方法,把数据导入到索引库中

返回TaotaoResult。


@Controller

@RequestMapping("/manager")

publicclass ItemController {

     

      @Autowired

      private ItemServiceitemService;

 

      /**

       *导入商品数据到索引库

       */

      @RequestMapping("/importall")

      @ResponseBody

      public TaotaoResult importAllItems() {

            TaotaoResult result = itemService.importAllItems();

            returnresult;

      }

}


执行报错,没有资源,resources 没有编译到classes下

修改pom文件,添加如下配置:

<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>


4   搜索服务发布

4.1  需求分析

http形式的服务。对外提供搜索服务是一个get形式的服务。

调用此服务时需要查询条件,分页条件可以使用page(要显示第几页)、rows(每页显示的记录数)

返回一个json格式的数据。可以使用TaotaoResult包装一个商品列表转换成json。


/search/query?q={查询条件}&page={page}&rows={rows}

返回的结果:TaotaoResult包装商品列表。


1.1  Dao层

分析:尽可能的做的通用一些。参数应该是SolrQuery。返回商品列表、查询结果总记录数

 

查询测试:

@Test

      publicvoid queryDocument() throws Exception {

            SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");

            //创建一个查询对象

            SolrQuery query = new SolrQuery();

            //设置查询条件

            query.setQuery("*:*");

            query.setStart(20);

            query.setRows(50);

            //执行查询

            QueryResponse response = solrServer.query(query);

            //取查询结果

            SolrDocumentList solrDocumentList = response.getResults();

            System.out.println("共查询到记录:" +solrDocumentList.getNumFound());

            for (SolrDocumentsolrDocument : solrDocumentList) {

                  System.out.println(solrDocument.get("id"));

                  System.out.println(solrDocument.get("item_title"));

            }

      }

 

返回结果pojo:

public class SearchResult {

 

      //商品列表

      private List<Item>itemList                 ;

      //总记录数

      private long recordCount;

      //总页数

      private long pageCount;

      //当前页

      private long curPage;

}

 

@Repository          dao用这个注解

public class SearchDaoImpl implements SearchDao {

     

      @Autowired

      private SolrServersolrServer;

 

      @Override

      public SearchResult search(SolrQueryquery) throws Exception {

            //返回值对象

            SearchResult result = new SearchResult();

            //根据查询条件查询索引库

            QueryResponse queryResponse = solrServer.query(query);

            //取查询结果

            SolrDocumentList solrDocumentList = queryResponse.getResults();

            //取查询结果总数量

            result.setRecordCount(solrDocumentList.getNumFound());

            //商品列表

            List<Item> itemList = new ArrayList<>();

            //取高亮显示

            Map<String, Map<String, List<String>>>highlighting = queryResponse.getHighlighting();

            //取商品列表

            for (SolrDocumentsolrDocument : solrDocumentList) {

                  //创建一商品对象

                  Item item = new Item();

                  item.setId((String) 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");

                  }

                  item.setTitle(title);

                  item.setImage((String) solrDocument.get("item_image"));

                  item.setPrice((long) solrDocument.get("item_price"));

                  item.setSell_point((String) solrDocument.get("item_sell_point"));

                  item.setCategory_name((String) solrDocument.get("item_category_name"));

                  //添加的商品列表

                  itemList.add(item);

            }

            result.setItemList(itemList);

            returnresult;

      }

 

}


1.1  Service层

功能:接收查询条件。查询条件及分页条件(page、rows),创建一个SolrQuery对象。

指定查询条件、分页条件、默认搜索域、高亮显示。

@Service

public class SearchServiceImplimplements SearchService {

 

      @Autowired

      private SearchDaosearchDao;

      @Override

      public SearchResultsearch(StringqueryString, intpage, introws) throws Exception {

            //创建查询对象

            SolrQuery query = new SolrQuery();

            //设置查询条件

            query.setQuery(queryString);

            //设置分页

            query.setStart((page - 1) *rows);

            query.setRows(rows);

            //设置默认搜素域

            query.set("df","item_keywords");

            //设置高亮显示

            query.setHighlight(true);

            query.addHighlightField("item_title");

            query.setHighlightSimplePre("<emstyle=\"color:red\">");

            query.setHighlightSimplePost("</em>");

            //执行查询

            SearchResult searchResult = searchDao.search(query);

            //计算查询结果总页数

            longrecordCount = searchResult.getRecordCount();

            longpageCount = recordCount /rows;

            if (recordCount %rows > 0) {

                  pageCount++;

            }

            searchResult.setPageCount(pageCount);

            searchResult.setCurPage(page);

           

            returnsearchResult;

      }

 

}


1.1  Controller层

接收查询参数:查询条件、page、rows

调用Service执行查询返回一个查询结果对象。

把查询结果包装到TaotaoResult中返回,结果是json格式的数据。

 

如果查询条件为空,返回状态码:400,消息:查询条件不能为空。

Page为空:默认为1

Rows 为空:默认为60


@Controller

public class SearchController{

 

      @Autowired

      private SearchServicesearchService;

     

      @RequestMapping(value="/query", method=RequestMethod.GET)

      @ResponseBody

      public TaotaoResultsearch(@RequestParam("q")StringqueryString,

                  @RequestParam(defaultValue="1")Integerpage,

                  @RequestParam(defaultValue="60")Integerrows) {

            //查询条件不能为空

            if (StringUtils.isBlank(queryString)) {

                  return TaotaoResult.build(400,"查询条件不能为空");

            }

            SearchResult searchResult = null;

            try {

// 解决get请求乱码问题

queryString = new String(queryString.getBytes("iso8859-1"), "utf-8");

                  searchResult = searchService.search(queryString,page, rows);

            } catch (Exceptione) {

                  e.printStackTrace();

                  return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));

            }

            return TaotaoResult.ok(searchResult);

           

      }

     

}

不扫描controller

<context:component-scanbase-package="com.taotao.search">

      <context:exclude-filtertype="annotation"expression="org.springframework.stereotype.Controller"/>

   </context:component-scan>


测试url

http://localhost:8083/search/query?q=手机 &page=1&rows=10

action配置

<servlet-mapping>

   <servlet-name>springmvc</servlet-name>

   <url-pattern>*.action</url-pattern>

  </servlet-mapping>

这里的配置

<servlet-mapping>

      <servlet-name>taotao-search</servlet-name>

      <url-pattern>/search/*</url-pattern>

   </servlet-mapping>


1、在taotao-portal工程中调用taotao-search工程发布的服务。实现商品搜索功能。




1、在页面里找到搜索框 和方法

在heard.jsp中

<input type="button" value="搜索" class="button" onclick="search('key');returnfalse;"

       当前jsp中没有这个方法,那一定是在js

<script type="text/javascript" src="/js/base-v1.js" charset="utf-8"></script>


查看base-v1.js

function search(a) {

   varb = "http://localhost:8082/search.html?q=" + encodeURIComponent(document.getElementById(a).value);

   returnwindow.location.href = b;

}

确定了搜索的url   :http://localhost:8082/search.html?q=


2、查看结果页面,确定页面需要的参数

<title>${query} - 商品搜索 - 淘淘</title>

<c:forEach items="${itemList}" var="item">

搜索 的结果页面需要下面这些属性

Query:回显的查询条件

totalPages:总页数

itemList:商品列表

Page:当前页码


1.1  Service层

接收两个参数1、查询条件2、页码。调用taotao-search的搜索服务。

接收返回的json数据,把json转换成java对象返回SearchResult对象。


#搜索服务基础url

SEARCH_BASE_URL=http://localhost:8083/search/query

把search 中的bean item 和 search 拷贝进当前项目,json转换属性相同,包不同没有关系


@Service

public classSearchServiceImpl implements SearchService {

 

  

   @Value("${SEARCH_BASE_URL}")

   private String SEARCH_BASE_URL;

  

   @Override

   public SearchResultsearch(String queryString,intpage){

      // 封装taotao-search 需要的参数

      Map<String,String> param= newHashMap<>();

      param.put("q", queryString);

      param.put("page", page + "");

     

      try {

        //调用taotao-search服务

        Stringjson= HttpClientUtil.doGet(SEARCH_BASE_URL, param);

        //把字符串转换成java对象

        TaotaoResulttaotaoResult= TaotaoResult.formatToPojo(json, SearchResult.class);

        if(taotaoResult.getStatus() ==200) {

           SearchResultsearchResult= (SearchResult) taotaoResult.getData();

           return searchResult;

        }

      }catch(Exception e) {

        e.printStackTrace();

      }

      return null;

   }


}


Controller

功能:接收请求的参数查询条件和页码。调用Service查询商品列表得到SearchResult对象。

需要把

Query:回显的查询条件

totalPages:总页数

itemList:商品列表

Page:当前页码

传递到页面

@Controller

public classSearchController {

 

   @Autowired

   private SearchService searchService;

  

   @RequestMapping("/search")

   public String search(@RequestParam("q")String queryString,

              @RequestParam(defaultValue="1")Integer page,Model model) throws IOException {

      // 处理get乱码

      Stringquery= null;

      if ( !StringUtils.isBlank(queryString) ) {

        query = new String(queryString.getBytes("iso8859-1"),"utf-8");

      }

      SearchResultsearchResult= searchService.search(query, page);

      model.addAttribute("itemList",searchResult.getItemList());

      model.addAttribute("totalPages",searchResult.getPageCount());

      model.addAttribute("query",query);

      model.addAttribute("page", page);

      return "search";

   }

  

}


ok!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值