介绍
Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口(传输数据:xml)。
用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;
也可以通过HttpGet操作提出查找请求,并得到XML格式的返回结果。(传输json:轻量级的数据、解析简单)
solr的底层是lucene
solrhome的目录结构
- solr.xml文件:有一个标签(节点)solrCloud(solr云)— 配置solr集群中需要监听的web容器的端口的。
- collection1:索引库 — MySQL的库
1)data(/index):存储索引文件的。在启动solr服务号自动创建的。
2)core.properties:
- 可以配置索引库的名称:name=xxx
- 配置solr的分片(shard)— 数据的拆分
3)conf:存放solr home的配置(掌握两个配置文件)
3. schema.xml文件—MySQL中表:配置业务字段以及字段类型的。(Lucene开发的时候:字段如何指定的 Document addFiled(filed) IndexableFiled-接口)
- field:配置业务字段
?name:字段名称
?type:字段类型
?indexed:true or false 是否创建索引
?stored:true or false 是否存储
?multiValued:true or false 是否允许多值 - dynamicField:动态字段(匹配字段)
- uniqueKey:索引库的主键
- copyField:复制字段
?source:源字段
?dest:目标字段(后期可以根据该字段检索) - fieldType:字段类型
- solrconfig.xml文件—MySQL的sql语法:配置solr的运行规则(方法 — url的请求)
?luceneMatchVersion:底层使用的Lucene的版本
?lib:引入额外的插件(jar包)
?requestHandler(请求处理器/请求执行句柄):url的请求
停用词与扩展词
停用词是为节省存储空间和提高搜索效率,搜索引擎在索引页面或处理搜索请求时会自动忽略某些字或词,这些字或词即被称为Stop Words(停用词)。
比如语气助词、副词、介词、连接词等,通常自身并无明确的意义,只有将其放入一个完整的句子中才有一定作用,如常见的“的”、“在”、“是”、“啊”等。
扩展词:网络用语
springDataSolr
虽然支持任何编程语言的能力具有很大的市场价值,你可能感兴趣的问题是:我如何将Solr的应用集成到Spring中?可以,Spring Data Solr就是为了方便Solr的开发所研制的一个框架,其底层是对SolrJ(官方API)的封装。
schema.xml文件(部分)
<uniqueKey>id</uniqueKey>
<!-- ik分词器配置 -->
<fieldType name="text_ik" class="solr.TextField">
<analyzer type="index" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
<analyzer type="query" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
<!-- 配置业务字段以及字段类型 -->
<field name="item_goodsid" type="long" indexed="true" stored="true"/>
<field name="item_title" type="text_ik" indexed="true" stored="true"/>
<field name="item_price" type="double" indexed="true" stored="true"/>
<field name="item_image" type="string" indexed="false" stored="true" />
<field name="item_category" type="string" indexed="true" stored="true" />
<field name="item_seller" type="text_ik" indexed="true" stored="true" />
<field name="item_brand" type="string" indexed="true" stored="true" />
<field name="item_updatetime" type="date" indexed="true" stored="true" />
<!-- 这个类型是使用ik分词器的意思 -->
<field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="item_title" dest="item_keywords"/>
<copyField source="item_category" dest="item_keywords"/>
<copyField source="item_seller" dest="item_keywords"/>
<copyField source="item_brand" dest="item_keywords"/>
<!-- 配置动态字段 -->
<dynamicField name="item_spec_*" type="string" indexed="true" stored="true" />
solr与spring整合的配置文件
applicationContext-solr.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:solr="http://www.springframework.org/schema/data/solr"
xsi:schemaLocation="http://www.springframework.org/schema/data/solr
http://www.springframework.org/schema/data/solr/spring-solr-1.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- solr服务器地址 -->
<solr:solr-server id="solrServer" url="http://192.168.200.128:8080/solr" />
<!-- solr模板,使用solr模板可对索引库进行CRUD的操作 -->
<bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate">
<constructor-arg ref="solrServer" />
</bean>
</beans>
pojo类
package cn.itcast.core.pojo.item;
import org.apache.solr.client.solrj.beans.Field;
import org.springframework.data.solr.core.mapping.Dynamic;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
public class Item implements Serializable {
/**
* 商品id,同时也是商品编号
*/
@Field
private Long id;
/**
* 商品标题
*/
@Field("item_title")
private String title;
/**
* 商品卖点
*/
private String sellPoint;
/**
* 商品价格,单位为:元
*/
@Field("item_price")
private BigDecimal price;
private Integer stockCount;
/**
* 库存数量
*/
private Integer num;
/**
* 商品条形码
*/
private String barcode;
/**
* 商品图片
*/
@Field("item_image")
private String image;
/**
* 所属类目,叶子类目
*/
private Long categoryid;
/**
* 商品状态,1-正常,2-下架,3-删除
*/
private String status;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
@Field("item_updatetime")
private Date updateTime;
private String itemSn;
private BigDecimal costPirce;
private BigDecimal marketPrice;
private String isDefault;
@Field("item_goodsid")
private Long goodsId;
private String sellerId;
private String cartThumbnail;
@Field("item_category")
private String category;
@Field("item_brand")
private String brand;
private String spec;
@Field("item_seller")
private String seller;
// {"机身内存":"16G","网络":"联通3G"}
@Dynamic
@Field("item_spec_*")
private Map<String, String> specMap;
solrTemplate
保存,删除
solrTemplate.saveBeans(items);
solrTemplate.commit();
//删除
SimpleQuery query = new SimpleQuery("item_goodsid:"+id);
solrTemplate.delete(query);
solrTemplate.commit();
检索
// 指定根据哪个字段检索 where filename like ?
// item_keywords就是schema.xml文件中的字段
Criteria criteria = new Criteria("item_keywords");
// is方法:对检索的内容切词(词条) ,这个是前台传过来的搜索的那个词
criteria.is(keywords);
//
SimpleQuery query = new SimpleQuery(criteria);
// 设置起始行
query.setOffset(startRow);
// 设置每页显示的条数
query.setRows(pageSize);
// 根据条件检索
ScoredPage<Item> scoredPage = solrTemplate.queryForPage(query, Item.class);
// 总页数
scoredPage.getTotalPages();
//总条数
scoredPage.getTotalElements();
// 商品列表
scoredPage.getContent();
// 高亮
SimpleHighlightQuery query = new SimpleHighlightQuery(criteria);
// 3、封装高亮的条件
HighlightOptions highlightOptions = new HighlightOptions();
highlightOptions.addField("item_title"); // 添加对该字段中包含的关键字进行高亮
highlightOptions.setSimplePrefix("<font color='red'>");
highlightOptions.setSimplePostfix("</font>");
query.setHighlightOptions(highlightOptions);
// 4、根据条件检索
HighlightPage<Item> highlightPage = solrTemplate.queryForHighlightPage(query, Item.class);
// 此时并不能高亮显示,因为solr把高亮之后的值封装到了另一个对象中,需要替换一下
// 封装高亮的结果
List<HighlightEntry<Item>> highlighted = highlightPage.getHighlighted();
if(highlighted != null && highlighted.size() > 0){
for (HighlightEntry<Item> highlightEntry : highlighted) {
Item item = highlightEntry.getEntity(); // 普通的结果
List<HighlightEntry.Highlight> highlights = highlightEntry.getHighlights();
if(highlights != null && highlights.size() > 0){
// 取出高亮的title
String title = highlights.get(0).getSnipplets().get(0);
item.setTitle(title);
}
}
}
// 分组查询
// 2、设置分组条件
SimpleHighlightQuery query = new SimpleHighlightQuery(criteria);
GroupOptions groupOptions = new GroupOptions();
groupOptions.addGroupByField("item_category"); // 根据哪个字段进行分组
query.setGroupOptions(groupOptions);
// 3、根据条件查询
List<String> list = new ArrayList<>();
GroupPage<Item> groupPage = solrTemplate.queryForGroupPage(query, Item.class);
GroupResult<Item> groupResult = groupPage.getGroupResult("item_category");
Page<GroupEntry<Item>> groupEntries = groupResult.getGroupEntries();
for (GroupEntry<Item> groupEntry : groupEntries) {
String groupValue = groupEntry.getGroupValue(); // 数据
list.add(groupValue);
}
// select * from table where keywords like ?
// 过滤:继续封装过滤的条件
// 分类过滤
String category = searchMap.get("category");
if(category != null && !"".equals(category)){
Criteria cri = new Criteria("item_category");
cri.is(category);
SimpleFilterQuery filterQuery = new SimpleFilterQuery(cri);
query.addFilterQuery(filterQuery);
}
// 页面传递的价格:区间段[min-max] xxx以上 [xxx-*]
// between >=
cri.between(prices[0], prices[1], true, true);
// 以上
cri.greaterThanEqual(prices[0]);
// 排序
Sort s = new Sort(Sort.Direction.ASC, "item_" + searchMap.get("sortField"));
query.addSort(s);