solr学习之完成商品搜索功能

一:创建taotao core

1、 在example目录下创建taotao-solr文件夹;

2、 将./solr下的solr.xml拷贝到taotao-solr目录下;

3、 在taotao-solr下创建taotao目录,并且在taotao目录下创建confdata目录;

4、 将example\solr\collection1\core.properties文件拷贝到example\taotao-solr\taotao下,并且修改name=taotao;

5、 将example\solr\collection1\conf下的schema.xml、solrconfig.xml拷贝到example\taotao-solr\taotao\conf下;

6、 修改schema.xml文件,使其配置最小化:

<?xml version="1.0" encoding="UTF-8" ?>

<schema name="example" version="1.5">
 
   <field name="_version_" type="long" indexed="true" stored="true"/>
   

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

   
   <field name="id" type="long" indexed="true" stored="true" required="true" multiValued="false" /> 
   <field name="title" type="text_ik" indexed="true" stored="true"/>
<field name="sellPoint" type="string" indexed="false" stored="true"/>
<field name="price" type="long" indexed="true" stored="true"/>
<field name="image" type="string" indexed="false" stored="true"/>
<field name="cid" type="long" indexed="true" stored="true"/>   
  <field name="status" type="int" indexed="true" stored="false"/>   
  
 <uniqueKey>id</uniqueKey>


    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />

	<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>

    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
	
	<fieldType name="text_ik" class="solr.TextField">   
     <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>   
</fieldType>

<solrQueryParser defaultOperator="AND"/>

</schema>

7、 修改solrconfig.xml文件,修改一些配置,大部分配置先保持默认:

a) 将所有的<lib>标签注释掉;

 

b) 搜索<str name="df">text</str>替换成<str name="df">title</str>

c) 将<searchComponent name="elevator" class="solr.QueryElevationComponent" >注释掉(这个的功能类似百度的竞价排名):

 

8、 启动solr

java -Dsolr.solr.home=taotao-solr -jar start.jar


二、集成IK分析器

1、 将IKAnalyzer-2012-4x.jar拷贝到example\solr-webapp\webapp\WEB-INF\lib下;

2、 在schema.xml文件中添加fieldType(上面已写好,这里忽略):

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

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

</fieldType>

三、配置nginx 通过域名访问 solr

server {
        listen       80;
        server_name  solr.taotao.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

		proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		
		proxy_set_header Host $host; 
		
        location / {
	    proxy_pass http://127.0.0.1:8983;
	    proxy_connect_timeout 600;
	    proxy_read_timeout 600;
        }
        
    }
四、添加host

五、 将商品数据导入到solr

1、商品

package cn.itcast.solrj.pojo;

import org.apache.solr.client.solrj.beans.Field;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
 * 商品
 *
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public class Item {
    @Field("id")
    private Long id;

    @Field("title")
    private String title;

    @Field("sellPoint")
    private String sellPoint;

    @Field("price")
    private Long price;

    @Field("image")
    private String image;

    @Field("cid")
    private Long cid;

    @Field("status")
    private Integer status;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getSellPoint() {
        return sellPoint;
    }

    public void setSellPoint(String sellPoint) {
        this.sellPoint = sellPoint;
    }

    public Long getPrice() {
        return price;
    }

    public void setPrice(Long price) {
        this.price = price;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public Long getCid() {
        return cid;
    }

    public void setCid(Long cid) {
        this.cid = cid;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "Item [id=" + id + ", title=" + title + ", sellPoint=" + sellPoint + ", price=" + price
                + ", image=" + image + ", cid=" + cid + ", status=" + status + "]";
    }

}
2、EasyUIResult
package cn.itcast.solrj.pojo;

import java.util.List;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class EasyUIResult {

    // 定义jackson对象
    private static final ObjectMapper MAPPER = new ObjectMapper();

    private Integer total;

    private List<?> rows;

    public EasyUIResult() {
    }

    public EasyUIResult(Integer total, List<?> rows) {
        this.total = total;
        this.rows = rows;
    }

    public EasyUIResult(Long total, List<?> rows) {
        this.total = total.intValue();
        this.rows = rows;
    }

    public Integer getTotal() {
        return total;
    }

    public void setTotal(Integer total) {
        this.total = total;
    }

    public List<?> getRows() {
        return rows;
    }

    public void setRows(List<?> rows) {
        this.rows = rows;
    }

    /**
     * Object是集合转化
     * 
     * @param jsonData json数据
     * @param clazz 集合中的类型
     * @return
     */
    public static EasyUIResult formatToList(String jsonData, Class<?> clazz) {
        try {
            JsonNode jsonNode = MAPPER.readTree(jsonData);
            JsonNode data = jsonNode.get("rows");
            List<?> list = null;
            if (data.isArray() && data.size() > 0) {
                list = MAPPER.readValue(data.traverse(),
                        MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
            }
            return new EasyUIResult(jsonNode.get("total").intValue(), list);
        } catch (Exception e) {
            return null;
        }
    }

}
3、测试导入

package cn.itcast.solrj.service;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.junit.Test;

import cn.itcast.solrj.pojo.EasyUIResult;
import cn.itcast.solrj.pojo.Item;

public class ItemDataImport {

    @Test
    public void start() throws Exception {
        // 1、从数据库中查询商品数据
        String url = "http://manage.taotao.com/rest/item?page={page}&rows=100";
        
        // 定义httpsolrserver
        // http://solr.taotao.com/#/taotao  -- 网页地址
        String solrUrl = "http://solr.taotao.com/taotao";
        HttpSolrServer httpSolrServer = new HttpSolrServer(solrUrl); //定义solr的server
        httpSolrServer.setParser(new XMLResponseParser()); // 设置响应解析器
        httpSolrServer.setMaxRetries(1); // 设置重试次数,推荐设置为1
        httpSolrServer.setConnectionTimeout(500); // 建立连接的最长时间
        
        // 分页获取数据
        Integer page = 1;
        Integer pageSize = 0;
        do {
            String jsonData = doGet(StringUtils.replace(url, "{page}", String.valueOf(page)));
            EasyUIResult easyUIResult = EasyUIResult.formatToList(jsonData, Item.class);
            List<Item> rows = (List<Item>) easyUIResult.getRows();
            pageSize = rows.size();

            // 2、将商品数据写入到solr
            httpSolrServer.addBeans(rows);
            httpSolrServer.commit();

            page++;
        } while (pageSize == 100);

    }

    private String doGet(String url) {
        try {
            // 创建Httpclient对象
            CloseableHttpClient httpclient = HttpClients.createDefault();

            // 创建http GET请求
            HttpGet httpGet = new HttpGet(url);

            CloseableHttpResponse response = null;
            try {
                // 执行请求
                response = httpclient.execute(httpGet);
                // 判断返回状态是否为200
                if (response.getStatusLine().getStatusCode() == 200) {
                    return EntityUtils.toString(response.getEntity(), "UTF-8");
                }
            } finally {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}       
六、 Solr Spring 的整合applicationContext-solr.xml
<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.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
	
	<bean class="org.apache.solr.client.solrj.impl.HttpSolrServer">
		<constructor-arg index="0" value="${solr.url}"/>
		<property name="parser">
			<!-- 设置相应解析器 -->
			<bean class="org.apache.solr.client.solrj.impl.XMLResponseParser"/>
		</property>
		<!-- 重试次数 -->
		<property name="maxRetries" value="${solr.maxRetries}"/>
		<!-- 建立连接的最长时间 -->
		<property name="connectionTimeout" value="${solr.connectionTimeout}"/>
	</bean>

</beans>
solr.properties:
solr.url=http://solr.taotao.com/taotao
solr.maxRetries=1
solr.connectionTimeout=500
七、实现搜索
PageInfo:

package com.taotao.search.bean;

import java.util.List;

public class PageInfo<T> {
    private Long total;

    private List<T> rows;

    public PageInfo() {
    }

    public PageInfo(Long total, List<T> rows) {
        this.total = total;
        this.rows = rows;
    }

    public Long getTotal() {
        return total;
    }

    public void setTotal(Long total) {
        this.total = total;
    }

    public List<T> getRows() {
        return rows;
    }

    public void setRows(List<T> rows) {
        this.rows = rows;
    }
}
Item.java添加一个方法

public String[] getImages(){
        return this.getImage()==null?null:StringUtils.split(this.getImage(), ',');
    }
ItemSearchService:

package com.taotao.search.service;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.taotao.search.bean.Item;
import com.taotao.search.bean.PageInfo;

@Service
public class ItemSearchService {
    
    public static final Integer ROWS = 28;
    
    @Autowired
    private HttpSolrServer httpSolrServer;

    public PageInfo<Item> search(String keyword, Integer page) throws Exception {
        SolrQuery solrQuery = new SolrQuery(); // 构造搜索条件
        solrQuery.setQuery("title:" + keyword + " AND status:1"); // 搜索关键词
        // 设置分页 start=0就是从0开始,,rows=5当前返回5条记录,第二页就是变化start这个值为5就可以了。
        solrQuery.setStart((Math.max(page, 1) - 1) * ROWS);
        solrQuery.setRows(ROWS);

        // 是否需要高亮
        boolean isHighlighting = !StringUtils.equals("*", keyword) && StringUtils.isNotEmpty(keyword);

        if (isHighlighting) {
            // 设置高亮
            solrQuery.setHighlight(true); // 开启高亮组件
            solrQuery.addHighlightField("title");// 高亮字段
            solrQuery.setHighlightSimplePre("<em>");// 标记,高亮关键字前缀
            solrQuery.setHighlightSimplePost("</em>");// 后缀
        }

        // 执行查询
        QueryResponse queryResponse = this.httpSolrServer.query(solrQuery);
        List<Item> items = queryResponse.getBeans(Item.class);
        if (isHighlighting) {
            // 将高亮的标题数据写回到数据对象中
            Map<String, Map<String, List<String>>> map = queryResponse.getHighlighting();
            for (Map.Entry<String, Map<String, List<String>>> highlighting : map.entrySet()) {
                for (Item item : items) {
                    if (!highlighting.getKey().equals(item.getId().toString())) {
                        continue;
                    }
                    item.setTitle(StringUtils.join(highlighting.getValue().get("title"), ""));
                    break;
                }
            }
        }
        
        return new PageInfo<Item>(queryResponse.getResults().getNumFound(), items);
    }

}
ItemSearchController:
package com.taotao.search.controller;

import java.io.UnsupportedEncodingException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.taotao.search.bean.Item;
import com.taotao.search.bean.PageInfo;
import com.taotao.search.service.ItemSearchService;

@Controller
public class ItemSearchController {
    @Autowired
    private ItemSearchService itemSearchService;
    
    @RequestMapping(value="search",method = RequestMethod.GET)
    public ModelAndView search(@RequestParam("keyword")String keyword,
            @RequestParam(value="page",defaultValue="1")Integer page){
        try {
            //解决get请求乱码问题
            keyword=new String(keyword.getBytes("ISO-8859-1"), "UTF-8");
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        }
        
        ModelAndView mv=new ModelAndView("search");
        mv.addObject("query", keyword);
        mv.addObject("page", page);
        
        try {
            PageInfo<Item> pageInfo=this.itemSearchService.search(keyword,page);
            mv.addObject("itemList", pageInfo.getRows());
            mv.addObject("pages", (pageInfo.getTotal()+ItemSearchService.ROWS-1)/ItemSearchService.ROWS);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mv;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值