下一节
Solr是搜索引擎的一个技术。说到搜索,我们可能会想到Lucene,他俩什么关系呢?这个Lucene本身是一个类库,这个类库需要我们在程序中去调用它,完成一个搜索功能,也就是说Lucene的搜索功能室偏底层的,然后我们的应用去调用Lucene的类库来实现相应的搜索功能,这是Lucene要解决的问题。但是Solr是解决什么问题呢?Solr本身底层还是调用这个Lucene,这个Solr本身是一个应用,它去调用Lucene,然后实现了相应的搜索功能,然后我们要实现搜索功能,只需要调用Solr这个服务,这个服务其实就是部署在Tomcat里。
然后我们的项目和Solr是怎么交互的呢?它本身是一个REST风格的这么一个程序,也就是说我们可以通过HTTP这种请求去请求这个Solr,然后Solr再给我们返回一定的结果,就这样一种交互方式。
Solr可以解决一个跨语言的问题,而Lucene是Java语言开发的,是个类库,是个Jar包,它只能被Java语言所调用。那么Solr就可以实现这种跨平台,跨语言。为什么呢?它本身由其他的应用可以调用这个Solr,比如PHPC#,它本身需要HTTP交互就可以完成这样一个功能了。所以说呢,Solr可以面向所有语言,来实现这种搜索。
为了开发更方便,这里安装的是windows系统下的。
1.安装Tomcat。因为Solr要在Tomcat下运行,解压缩apache-tomcat-7.0.52.zip即可。
2.解压Solr,在dist目录下找到war包,放到Tomcat的webapps目录下。
3.启动Tomcat,目的是将solr.war解压开。
4.加扩展包。将solr目录下example目录下lib目录下ext目录下的所有jar包复制到tomcat里Solr的WEB-INF下的lib中。
5.创建一个solrhome。其实Solr本身也相当于一个数据库,它不仅仅是一个索引库,其实索引库里也就相当于很多数据,那么我们说他是数据库也对,它也是一种NoSQL类型的一种数据库。那么这种数据库它存在哪?主要就是存在这个solrhome里,它并不是存到solr本身的这个应用里,而是单独的一个存储目录。所以我们需要创建一个solrhome。其实这个solrhome本身存在,就在solr/example/solr这个目录中。我们将这个目录单独复制一份放到其他地方。改名为solrhome。
6.在solr中配置solrhome的目标位置。在tomcat中的solr/WEB-INF/web.xml修改配置如下
<env-entry>
<env-entry-name>solr/homeenv-entry-name>
<env-entry-value>F:\solrhomeenv-entry-value>
<env-entry-type>java.lang.Stringenv-entry-type>
env-entry>
7.重启tomcat
也叫分词器,IK本身也是一个开源的。另外IK可以实现对一些主流的词汇进行分词。分词的意思就是比如“ronybo是一头猪”这句话,IK就会把它进行分词,分成“ronybo”,“是”,“一头”,“猪”这种格式的词汇。IK比较方便,就是它可以自己扩充一些词典,或者自己扩充一些自定义的词典,或者说对一些词进行排除。
1.将IK Analyzer 2012FF_hf1\IKAnalyzer2012FF_u1.jar
jar包放到apache-tomcat-Solr\webapps\solr\WEB-INF\lib
目录下。
2.将IK Analyzer 2012FF_hf1
目录下的扩展字典mydict.dic
和扩展停止词字典ext_stopword.dic
还有一个配置文件IKAnalyzer.cfg.xml
放到apache-tomcat-Solr\webapps\solr\WEB-INF\classes
目录下。
配置文件的内容如下:
<properties>
<comment>IK Analyzer 扩展配置comment>
<entry key="ext_dict">mydict.dic;entry>
<entry key="ext_stopwords">ext_stopword.dicentry>
properties>
其实扩展字典是自己定义的。
停止词字典里面放的是一些敏感词汇,和一些辅助词。
3.修改solrhome目录下的collection1\conf\schema.xml
文件让solr能够找到中文分析器所在的位置。
<filedType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer" />
fieldType>
所有的中文词汇分析都在IKAnalyzer类里进行实现。
4.重启Tomcat
没配置ik之前,效果是这样的:
因为外国人不知道中文哪个词和哪个词应该组成一个词。所以每个词都被分开了。
使用了IK之后,效果是这样的:
是字为什么丢了呢?因为是字属于辅助词汇,不会在关键字的行列中。我们搜索的时候也不会把是当成关键字进行搜索吧?他也不傻。
<dependencies>
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-solrartifactId>
<version>1.5.5.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>4.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.9version>
dependency>
dependencies>
在src/main/resources下创建applicationContext-solr.xml
<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-server id="solrServer" url="http://127.0.0.1:8080/solr" />
<bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate">
<constructor-arg ref="solrServer" />
bean>
beans>
@Field注解是在Solr中配置的业务域,用来搜索使用。
public class TbItem implements Serializable{
@Field
private Long id;
@Field("item_title")
private String title;
@Field("item_price")
private BigDecimal price;
@Field("item_image")
private String image;
@Field("item_goodsid")
private Long goodsId;
@Field("item_category")
private String category;
@Field("item_brand")
private String brand;
@Field("item_seller")
private String seller;
......
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext-solr.xml")
public class TestTemplate {
@Autowired
private SolrTemplate solrTemplate;
@Test
public void testAdd() {
TbItem item = new TbItem();
item.setId(1L);
item.setTitle("华为METE10");
item.setCategory("手机");
item.setBrand("华为");
item.setSeller("华为旗舰店");
item.setGoodsId(1L);
item.setPrice(new BigDecimal(3000.01));
solrTemplate.saveBean(item);
solrTemplate.commit();
}
}
其实修改和增加的方法时一样的。如果id
是一样的,它就进行修改,如果id
不一样,他就进行增加。
3.1 根据ID进行查询
solrTemplate.getById();
3.2 根据ID进行删除
solrTemplate.deleteById();
3.3 分页查询
首先插入100条数据
public void testAddList() {
List<TbItem> list = new ArrayList<TbItem>();
for (int i = 0; i < 100; i++) {
TbItem item = new TbItem();
item.setId(i + 1L);
item.setBrand("华为"+i);
item.setCategory("手机");
item.setGoodsId(1L);
item.setPrice(new BigDecimal(2000+i));
item.setSeller("华为旗舰店");
item.setTitle("华为Meta"+i);
list.add(item);
}
solrTemplate.saveBeans(list);
solrTemplate.commit();
}
然后进行查询
分页查询
public void queryByPage() {
// Query是一个接口,它有一个儿子叫SimpleQuery,它由一个构造参数
// 可以传一个查询的表达式。下面这个就是查询全部的表达式
// 如果是查询某个字段,那前面的*就是某个字段,后面的*就是查询什么什么值。
Query query = new SimpleQuery("*:*");
// 每页记录数
query.setRows(20);
// // 开始索引
// query.setOffset(20);
// 返回一个分页结果
ScoredPage<TbItem> page = solrTemplate.queryForPage(query, TbItem.class);
// page.getContent();返回每一页的结果
for (TbItem item : page.getContent()) {
System.out.println(item.getTitle()+" "+item.getBrand()+" "+item.getPrice());
}
// 总记录数
System.out.println("总记录数:"+page.getTotalElements());
// 总页数
System.out.println("总页数:"+page.getTotalPages());
}
条件查询
public void queryByCondition() {
Query query = new SimpleQuery("*:*");
// Query对查询表达式进行了封装。可以直接调用方法进行查询,和MyBatis用法相似
// 查询item_category包含手机的所有记录
Criteria criteria = new Criteria("item_category").contains("手机");
criteria = criteria.and("item_brand").contains("2");
query.addCriteria(criteria);
ScoredPage<TbItem> page = solrTemplate.queryForPage(query , TbItem.class);
for (TbItem item : page.getContent()) {
System.out.println(item.getTitle()+" "+item.getBrand()+" "+item.getPrice());
}
}
将品优购数据库中的数据导入到索引库当中。因为接下来我们要实现搜索,所有我们需要导入一个真是的数据。
1.创建Maven项目pinyougou-solr-util.jar。
2.添加依赖pinyougou-dao
<dependency>
<groupId>com.pinyougougroupId>
<artifactId>pinyougou-daoartifactId>
<version>0.0.1-SNAPSHOTversion>
dependency>
3.导入Spring相关依赖
4.创建Spring配置文件spring/applicationContext.xml
<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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.pinyougou.solrutil">context:component-scan>
beans>
5.创建包com.pinyougou.solrutil
,创建类SolrUtil
。
5.1 先将SKU的TbItem表中的数据查出来,因为SKU的数据比较全。
// 声明一个Bean
@Component
public class SolrUtil {
@Autowired
private TbItemMapper tbItemMapper;
public void importItemData() {
TbItemExample example = new TbItemExample();
Criteria criteria = example.createCriteria();
// 只有状态为1的才导入
criteria.andStatusEqualTo("1");
List<TbItem> itemList = tbItemMapper.selectByExample(example);
System.out.println("----商品列表----");
for (TbItem item : itemList) {
System.out.println(item.getId()+" "+item.getTitle()+ " " + item.getPrice());
}
System.out.println("----结束----");
}
public static void main(String[] args) {
// classpath不加*是找当前项目的根目录下的文件,加*会去找jar包里的所有根目录下的文件
// 文件名后加*是匹配所有前面是applicationContext的文件
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:spring/applicationContext*.xml");
SolrUtil solrUtil = (SolrUtil) context.getBean("solrUtil");
solrUtil.importItemData();
}
}
5.2 在pojo项目中导入Solr的依赖。将刚才Demo中的实体类TbItem
再拷贝到当前工程中。
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-solrartifactId>
<version>1.5.5.RELEASEversion>
dependency>
5.3 添加Solr的配置文件
5.4 导入其实就是调用solrTemplate的saveBeans()方法。
出来了。
下一节