Solr基于ApacheLucene构建的流行、快速开源企业搜索平台

Solr具有高度可靠性、可扩展性和容错性,提供分布式索引复制负载平衡查询自动故障切换恢复、集中配置等功能。Solr为许多世界上最大互联网站点提供搜索和导航功能

环境准备

linux centos7

java8

solr8.11.2

笔者使用 centos7,已经安装Java环境java 版本java8,solr 版本是8.11.2


solr官网https://solr.apache.org/

solr下载地址https://solr.apache.org/downloads.html

下载完成

下载后,将solr-8.11.2.tgz上传linux 

创建 solr 安装目录

mkdir -p /usr/local/solr

将solr安装包解压安装目录

tar -zxf solr-8.11.2.tgz -C /usr/local/solr

进入solr安装目录

cd /usr/local/solr/solr-8.11.2

bin/solr start

如果执行命令 bin/solr start 启动报错启动不起来,执行下面命令

bin/solr start -force

笔者执行 bin/solr startforce 命令启动

如果想要去除启动时的警告日志可以bin目录下 solr.in.sh 文件的 SOLR_ULIMIT_CHECKS 设置false

SOLR_ULIMIT_CHECKS=false 

 修改

笔者这里没有修改 SOLR_ULIMIT_CHECKS 配置

solr 启动后,浏览器访问Linux ip地址+端口号8983,访问 Admin Web管理页面

如果访问不到,防火墙开放端口 8983

firewall-cmd --zone=public --add-port=8983/tcp --permanent

更新防火墙规则(无需断开连接动态添加规则

firewall-cmd --reload

笔者ip地址是192.168.1.104,笔者访问地址 http://192.168.1.104:8983/solr

创建实例名称为 solr_book实例

bin/solr create -c solr_book

如果上面命令创建不成功,执行命令 bin/solr createc solr_bookforce

bin/solr create -c solr_book -force

创建成功后,在 Admin Web管理页面查看

bin/solr stop -all

solr 默认没有中文分词,中文分词需要手动添加这里使用 ikanalyzer-8.5.0.jar

ikanalyzer GitHub 地址https://github.com/magese/ik-analyzer-solr

下载 ikanalyzer-8.5.0.jar

ikanalyzer-8.5.0.jar 上传到 Linux

将 ikanalyzer-8.5.0.jar 移动到 /usr/local/solr/solr-8.11.2/server/solr-webapp/webapp/WEB-INF/lib 目录

mv /root/ik-analyzer-8.5.0.jar /usr/local/solr/solr-8.11.2/server/solr-webapp/webapp/WEB-INF/lib

 进入 /usr/local/solr/solr-8.11.2/server/solr-webapp/webapp/WEB-INF/lib 目录

cd /usr/local/solr/solr-8.11.2/server/solr-webapp/webapp/WEB-INF/lib

查看 ikanalyzer-8.5.0.jar 是否移动成功

 

移动成功

进入solr目录查看创建的实例

cd /usr/local/solr/solr-8.11.2/server/solr

可以看到上面创建的实例 solr_book

进入实例配置目录

cd solr_book/conf

编辑 managed-schema ,或者将 managed-schema 下载下来添加配置再上传回去

vi managed-schema

在managed-schema末尾添加下面配置

<!-- ik分词器 -->
<fieldType name="text_ik" class="solr.TextField">
  <analyzer type="index">
      <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" conf="ik.conf"/>
      <filter class="solr.LowerCaseFilterFactory"/&gt;
  </analyzer&gt;
  <analyzer type="query">
      <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" conf="ik.conf"/>
      <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

笔者是将 managed-schema下载下来后编辑,再上传上去

SFTP下载命令

get /usr/local/solr/solr-8.11.2/server/solr/solr_book/conf/managed-schema

修改后的 managed-schema 移动到原来目录的位置

mv /root/managed-schema /usr/local/solr/solr-8.11.2/server/solr/solr_book/conf/

关闭 solr 后重新启动

Admin Web管理页面查看添加的中文分词

中文分词测试

使用 docker 安装 solr

拉取 solr 镜像

docker pull solr:8.11.2

开启容器

docker run --name solr_demo -d -p 8983:8983 solr:8.11.2 

开启容器后,浏览器访问宿主机器ip+8983端口,访问 Admin Web管理页面

创建实例 shop_solr

docker exec -it solr_demo solr create_core -c shop_solr

创建后可在 Admin Web管理页面查看

步骤linux 安装 solr 添加中文分词一样,先添加 ik-analyzer-8.5.0.jar 包,然后在 managed-schema 中添加配置

docker cp ik-analyzer-8.5.0.jar solr_demo:/opt/solr-8.11.2/server/solr-webapp/webapp/WEB-INF/lib

docker器中的 managed-schema 文件复制出来进行修改

docker cp solr_demo:/var/solr/data/shop_solr/conf/managed-schema /root

添加下面配置

<!-- ik分词器 -->
<fieldType name="text_ik" class="solr.TextField">
  <analyzer type="index">
      <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" conf="ik.conf"/>
      <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
  <analyzer type="query">
      <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" conf="ik.conf"/>
      <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

在managed-schema 文件中添加配置和上面Linux安装solr添加中文分词处理一样,可以编辑managed-schema 文件或下载下来再处理这里不再赘述

修改后,将 managed-schema 文件复制docker 容器

docker cp /root/managed-schema solr_demo:/var/solr/data/shop_solr/conf/

重启 solr 容器

docker restart solr_demo

Admin Web管理页面查看添加的中文分词

这里新建一个springboot项目

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.7.7</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.wsjz</groupId>
	<artifactId>solr-learn</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>solr-learn</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-solr</artifactId>
            <version>2.4.13</version>
        </dependency>
        
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

SolrConfig 配置类

package com.wsjz.config;

import org.apache.solr.client.solrj.SolrClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.solr.core.SolrTemplate;

@Configuration
public class SolrConfig {

	@Autowired
	private SolrClient solrClient;

	@Bean
	public SolrTemplate solrTemplate() {
		return new SolrTemplate(solrClient);
	}

}

Book 实体类

package com.wsjz.bean;

import org.apache.solr.client.solrj.beans.Field;
import org.springframework.data.annotation.Id;
import org.springframework.data.solr.core.mapping.SolrDocument;

import lombok.Data;

@Data
@SolrDocument(collection = "solr_book")
public class Book {

	@Id
	@Field
	private String id;

	/**
	 * 书名
	 */
	@Field
	private String name;

	/**
	 * 作者
	 */
	@Field
	private String author;

	/**
	 * 介绍
	 */
	@Field
	private String introduce;

}

HighlightBook 实体类

package com.wsjz.bean;

import java.util.List;

import org.springframework.data.solr.core.query.result.HighlightEntry;

import lombok.Data;

@Data
public class HighlightBook extends Book {

	/**
	 * 存储高亮字段
	 */
	private List<HighlightEntry.Highlight> highlight;

	@Override
	public String toString() {
		String snipplets = "";
		for (HighlightEntry.Highlight h : highlight) {
			snipplets += h.getSnipplets().toString();
		}

		return "HighlightBook [highlight=" + snipplets + "]" + super.toString();
	}

}

BookController

package com.wsjz.controller;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.Criteria;
import org.springframework.data.solr.core.query.HighlightOptions;
import org.springframework.data.solr.core.query.SimpleHighlightQuery;
import org.springframework.data.solr.core.query.SimpleQuery;
import org.springframework.data.solr.core.query.result.HighlightEntry;
import org.springframework.data.solr.core.query.result.HighlightPage;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.wsjz.bean.Book;
import com.wsjz.bean.HighlightBook;

@RestController
public class BookController {

	@Autowired
	private SolrTemplate solrTemplate;

	/**
	 * solr实例名称
	 */
	private static final String collection = "solr_book";

	/**
	 * 添加
	 * 
	 * @return
	 */
	@RequestMapping("/add")
	public String add() {
		Book book = new Book();
		book.setName("红楼梦");
		book.setAuthor("曹雪芹");
		book.setIntroduce("《红楼梦》,原名《石头记》,中国古代章回体长篇小说,中国古典四大名著之一");

		solrTemplate.saveBean(collection, book);
		solrTemplate.commit(collection);
		return "add ok";
	}

	/**
	 * 删除
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping("/del/{id}")
	public String del(@PathVariable("id") String id) {
		solrTemplate.deleteByIds(collection, id);
		solrTemplate.commit(collection);
		return "del ok";
	}

	/**
	 * 修改
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping("/update/{id}")
	public String update(@PathVariable("id") String id) {
		Book book = new Book();
		book.setId(id);
		book.setName("西游记");
		book.setAuthor("吴承恩");
		book.setIntroduce("《西游记》是明代吴承恩创作中国古代第一部浪漫主义章回体长篇神魔小说");

		// 有id进行修改操作
		solrTemplate.saveBean(collection, book);
		solrTemplate.commit(collection);
		return "update ok";
	}

	/**
	 * 查询
	 * 
	 * @return
	 */
	@RequestMapping("/query")
	public String query() {
		Criteria criteria = Criteria.where("introduce").is("古典");
		SimpleQuery query = new SimpleQuery(criteria);
		Page<Book> page = solrTemplate.query(collection, query, Book.class);
		List<Book> list = page.getContent();
		list.forEach(System.out::println);
		return "query ok";
	}

	/**
	 * 分页查询
	 * 
	 * @return
	 */
	@RequestMapping("/find")
	public String find(Integer pageNum, Integer pageSize) {
		Criteria criteria = Criteria.where("introduce").is("古典");
		SimpleQuery query = new SimpleQuery(criteria);
		// 通过id降序排序
		query.setPageRequest(PageRequest.of(pageNum - 1, pageSize, Sort.by(Sort.Direction.DESC, "id")));

		Page<Book> page = solrTemplate.query(collection, query, Book.class);
		List<Book> list = page.getContent();
		// 总页数
		int pages = page.getTotalPages();
		// 总条数
		long total = page.getTotalElements();
		list.forEach(System.out::println);
		System.out.println(pages);
		System.out.println(total);

		return "find ok";
	}

	/**
	 * 高亮查询
	 * 
	 * @param pageNum
	 * @param pageSize
	 * @return
	 */
	@RequestMapping("/highlightFind")
	public String highlightFind(Integer pageNum, Integer pageSize) {
		Criteria criteria = Criteria.where("introduce").is("古典");
		// 高亮查询
		SimpleHighlightQuery query = new SimpleHighlightQuery(criteria);
		// 通过id降序排序
		query.setPageRequest(PageRequest.of(pageNum - 1, pageSize, Sort.by(Sort.Direction.DESC, "id")));

		HighlightOptions highlightOptions = new HighlightOptions();
		highlightOptions.addField("introduce");
		highlightOptions.setSimplePrefix("<span style='color:red'>");
		highlightOptions.setSimplePostfix("</span>");
		query.setHighlightOptions(highlightOptions);

		HighlightPage<Book> page = solrTemplate.queryForHighlightPage(collection, query, Book.class);
		List<Book> content = page.getContent();
		List<HighlightBook> list = content.stream().map(book -> {
			HighlightBook highlightBook = new HighlightBook();
			BeanUtils.copyProperties(book, highlightBook);
			List<HighlightEntry.Highlight> highlights = page.getHighlights(book);
			highlightBook.setHighlight(highlights);
			return highlightBook;
		}).collect(Collectors.toList());

		// 总页数
		int pages = page.getTotalPages();
		// 总条数
		long total = page.getTotalElements();
		list.forEach(System.out::println);
		System.out.println(pages);
		System.out.println(total);

		return "highlightFind ok";
	}

}

solr中域名和域的类型,等同于mysql中表字段和表字段类型

上面有Book实体类,有字段nameauthor、introduce;需要在solr中定义对应的域,以及对应的分词器

这里笔者对introduce字段进行中文分词,使用上面配置的中文分词器 text_ik

需要在solr_book实例下面的managed-schema文件中添加域的配置

<field name="name" type="string" indexed="true" stored="true" multiValued="false" />
<field name="author" type="string" indexed="true" stored="true" multiValued="false" />
<field name="introduce" type="text_ik" indexed="true" stored="true" multiValued="false" />

下面笔者使用 Linux 搭建的 solr 进行操作

编辑 managed-schema 文件

vi /usr/local/solr/solr-8.11.2/server/solr/solr_book/conf/managed-schema

在managed-schema文件末尾添加域的配置

配置后重启 solr

bin/solr restart -force

测试添加

浏览器请求http://localhost:8080/

然后在Admin Web管理页面查询

 

测试删除 

通过id删除

测试修改

修改前先添加一条

测试查询

测试分页查询

 测试高亮查询

至此完

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注