Java大型互联网项目-开发日记-移动电子商城-首页筛选Solr
需求
我们要实现每点击一个选项,就更新下面的商品信息,在访问量过大时,如果点击时去请求数据库,那么会造成访问速度过慢,所以我们采用以下策略
Solr背景
缓慢原因模型
Solr位置模型
Solr操作
在工作中全文检索在文档总来查找指定关键字并不是特别多,而是通过关键字查找相关的文档用的特别多
solr把整个要搜索的内容叫做一个文档,跟数据库结合时文档的定义把一条数据抽取出来作为一个文档
item_name promotion key_words
三星S6 支持曲屏 盖六,S6
iPhone7 接近iPhone4 肾7
item_name为索引
三星S6为一个域
每一行为一个文档
定义域与IK分词器的配置
<field name="item_name" type="text_ik" indexed="true" stored="true" />
<field name="brand_id" type="long" indexed="true" stored="true" />
<field name="sku_price" type="float" indexed="true" stored="true" />
<field name="promotion" type="text_ik" indexed="true" stored="true" />
<field name="item_keywords" type="text_ik" indexed="true" stored="true" multiValued="true" />
<field name="imgs" type="string" indexed="false" stored="true" />
<field name="para_vals" type="text_ik" indexed="true" stored="true" />
<copyField source="item_name" dest="item_keywords"/>
<copyField source="promotion" dest="item_keywords"/>
<fieldType name="text_ik" class="solr.TextField">
<analyzer type="index" class="org.wltea.analyzer.lucene.IKAnalyzer" isMaxWordLength="false"/>
<analyzer type="query" class="org.wltea.analyzer.lucene.IKAnalyzer" isMaxWordLength="true"/>
</fieldType>
导入域数据
public void importIndex() throws Exception {
// TODO Auto-generated method stub
List<EbItem> itemList = itemDao.selectIsSelectItemList();
SolrServer ss = ECPSUtils.getSolrServer();
for(EbItem item : itemList){
SolrInputDocument sd = new SolrInputDocument() ;
sd.addField("id", item.getItemId());
sd.addField("item_name", item.getItemName());
sd.addField("sku_price", item.getSkuPrice()) ;
sd.addField("item_keywords", item.getKeywords()) ;
sd.addField("imgs", item.getImgs());
sd.addField("promotion", item.getPromotion());
sd.addField("brand_id", item.getBrandId());
String paraVals = "" ;
for(EbParaValue para : item.getParaList()){
paraVals = paraVals + para.getParaValue()+"," ;
}
sd.addField("para_vals", paraVals);
ss.add(sd) ;
}
ss.commit();
}
其中,Solr所需的数据从数据库中抽取,对应的SQL
<resultMap type="com.rl.ecps.model.EbItem" id="selectIsSelectItemListRM" extends="BaseResultMap">
<result column="sku_price" property="skuPrice"/>
<collection property="paraList" ofType="com.rl.ecps.model.EbParaValue">
<id column="PARA_ID" jdbcType="DECIMAL" property="paraId" />
<result column="ITEM_ID" jdbcType="DECIMAL" property="itemId" />
<result column="FEATURE_ID" jdbcType="DECIMAL" property="featureId" />
<result column="PARA_VALUE" jdbcType="VARCHAR" property="paraValue" />
</collection>
</resultMap>
<select id="selectIsSelectItemList" resultMap="selectIsSelectItemListRM">
select *
from (select min(es.sku_price) sku_price, ei.*
from eb_item ei, eb_sku es
where ei.item_id = es.item_id
and ei.audit_status = 1
and ei.show_status = 0
group by ei.ITEM_ID,
ei.ITEM_NAME,
ei.ITEM_NO,
ei.BRAND_ID,
ei.CAT_ID,
ei.TAG_IMG_ID,
ei.TAG_IMG,
ei.IS_NEW,
ei.IS_GOOD,
ei.IS_HOT,
ei.PROMOTION,
ei.AUDIT_STATUS,
ei.SHOW_STATUS,
ei.IMGS,
ei.KEYWORDS,
ei.PAGE_DESC,
ei.ITEM_RECYCLE,
ei.ON_SALE_TIME,
ei.CHECK_TIME,
ei.UPDATE_TIME,
ei.UPDATE_USER_ID,
ei.CREATE_TIME,
ei.CHECKER_USER_ID,
ei.FULL_PATH_DEPLOY,
ei.FULL_PATH_DEPLOY_OFFER,
ei.ORIGINAL_ITEM_ID,
ei.LAST_STATUS,
ei.MERCHANT_ID,
ei.ITEM_SORT,
ei.SALES,
ei.CREATE_USER_ID,
ei.SIM_LEVEL,
ei.GIFT_DESC,
ei.GIFT_IMG,
ei.GIFT_SHOW_TYPE,
ei.IMG_SIZE1) e1,
eb_para_value ev,
eb_feature ef
where e1.item_id = ev.item_id
and ev.feature_id = ef.feature_id
and ef.is_select = 1
</select>
搜索Solr数据
@RequestMapping("/listItem.do")
public String listItem(String price, Long brandId,
String keyWords, String paraVals, Model model) throws Exception{
List<EbItem> itemList = itemService.selectItemByIndex(price, brandId, keyWords, paraVals);
model.addAttribute("itemList", itemList);
return "phoneClassification";
}
public List<EbItem> selectItemByIndex(String price, Long brandId,
String keyWords, String paraVals) throws Exception {
List<EbItem> itemList = new ArrayList<EbItem>();
SolrServer ss = ECPSUtils.getSolrServer();
SolrQuery sq = new SolrQuery();
//价钱筛选
if(StringUtils.isNotBlank(price)){
String [] priceArr = price.split("-");
sq.set("fq", "sku_price:["+priceArr[0]+" TO "+priceArr[1]+" ]");
}
String queryStr = "*:*";
//品牌不为空
if(brandId != null){
queryStr = "brand_id:"+brandId;
}
//如果关键字也不是空
if(StringUtils.isNotBlank(keyWords)){
if(StringUtils.equals(queryStr, "*:*")){
queryStr = "item_keywords:"+keyWords;
}else{
queryStr = queryStr + " AND item_keywords:"+keyWords;
}
}
if(StringUtils.isNotBlank(paraVals)){
String [] paraValArr = paraVals.split(",");
String paraValsQuery = "";
for(String paraVal : paraValArr){
paraValsQuery = paraValsQuery + "para_vals:"+paraVal +" AND ";
}
//去掉最后一个AND
paraValsQuery = paraValsQuery.substring(0, paraValsQuery.lastIndexOf(" AND "));
if(StringUtils.equals(queryStr, "*:*")){
queryStr = paraValsQuery;
}else{
queryStr = queryStr + " AND "+paraValsQuery;
}
}
sq.setQuery(queryStr);
sq.setSort("id", ORDER.desc);
sq.setHighlight(true);
sq.addHighlightField("item_name");
sq.addHighlightField("promotion");
sq.setHighlightSimplePre("<font color='red'>");
sq.setHighlightSimplePost("</font>");
//查询索引库
QueryResponse qr = ss.query(sq);
//获得结果
SolrDocumentList dList = qr.getResults();
for(SolrDocument sd : dList){
String itemId = (String) sd.getFieldValue("id");
String itemName = (String) sd.getFieldValue("item_name");
String promotion = (String) sd.getFieldValue("promotion");
String imgs = (String) sd.getFieldValue("imgs");
String skuPrice = sd.getFieldValue("sku_price").toString();
//{1001:item_name:["<font>.."]}
Map<String, Map<String, List<String>>> hlMap = qr.getHighlighting();
if(hlMap != null){
Map<String, List<String>> listMap = hlMap.get(itemId);
if(listMap != null){
List<String> iList = listMap.get("item_name");
if(iList != null && iList.size() > 0){
String hlStr = "";
for(String hl : iList){
hlStr = hlStr + hl;
}
itemName = hlStr;
}
List<String> pList = listMap.get("promotion");
if(pList != null && pList.size() > 0){
String hlStr = "";
for(String hl : pList){
hlStr = hlStr + hl;
}
promotion = hlStr;
}
}
}
EbItem item = new EbItem();
item.setItemId(new Long(itemId));
item.setItemName(itemName);
item.setPromotion(promotion);
item.setImgs(imgs);
item.setSkuPrice(new BigDecimal(skuPrice));
itemList.add(item);
}
return itemList;
}
以上参数由前端循环遍历a链接取值并以Get形式跳转
$('.filter li a').mousedown(function(){
var cln = $(this).attr("class");
if(cln == undefined){
$(this).attr("class",'');
cln = $(this).attr("class");
};
if(cln.indexOf("btn80x22") == 0){
return;
}
var type = $(this).parent().is("p");
var obj;
if(type){
obj = $(this).parent().find('a');
}else{
obj = $(this).parent().parent().find('a');
}
obj.removeClass('here');
$(this).addClass('here');
var price = "";
var brandId = "";
var keyWords = $("#keyWords").val();
var paraVals = "";
//循环a链接找到被选中的a
$('.filter li a').each(function(){
var clazz = $(this).attr("class");
if(clazz == "here"){
//获得a的类型
var fType = $(this).attr("fType");
//获得a的值
var fValue = $(this).attr("fValue");
if(fType == "price"){
price = fValue;
}else if(fType == "brand"){
brandId = fValue;
}else if(fType == "feature" && fValue != ""){
paraVals = paraVals + fValue +",";
}
}
})
//alert(price +"======="+brandId+ "========"+keyWords+"======="+paraVals);
var iPath = path+"/item/listItem.do?price="+price+"&brandId="+brandId+"&keyWords="+keyWords+"¶Vals="+paraVals;
//刷新iframe,很简单只要重置src即可
$("#itemListIframe").attr("src", iPath);