单机搜索Solr应用

1.solr简介

solr是以lucene为内核开发的企业级搜索应用 应用程序可以通过http请求方式来提交索引,查询索引,提供了比lucene更丰富的查询语言,是一个高性能,高可用环境全文搜索引擎

2.倒排索引原理

  • 文章表
id标题内容
1我爱中国中国地大物博
2中国永存遍地都是精英
  • 倒排索引
关键词	文章号
我		1
爱		1
中国    	1,2
永存		2

3.分词器

  • 将中文拆分成有意义的词
  • 常用的IK分词器,庖丁解牛分词器。

4.lucene

  • lucene是一个将text数据类型,分词建立索引的一个库,不适合企业级使用。
    企业级考虑高可用问题。
  • solr是一个企业级应用的搜索引擎,支持使用json格式提交数据。
  • json格式:
  1. [] 代表数组
  2. {} 对象(文档 document)
  3. 键值对 属性
  • 模拟json格式:
[
{id:1,title:'我爱中国',content:'中国地大物博'},
{id:2,title:'中国永存',content:'遍地都是精英'}
]

5.solr高可用版本参考

https://blog.csdn.net/liaomin416100569/article/details/77301756

6.solr安装

  • 核(core)的概念

是用于存储json格式的数据,等价于mysql中数据库的概念

  • 文档(document)

一个json对象就是一个文档 相同属性的json数组集合就是一个表

  1. 下载solr:5.5.5版本
docker pull solr:5.5.5
  1. 启动solr:5.5.5
docker run --name my_solr -id --net host -t solr:5.5.5
  1. 检查端口是否被占用
netstat -aon | grep 8983
下载netstat:yum -y install net-tools telnet
  1. 创建core
docker exec -it --user=solr my_solr bin/solr create_core -c mycore
  1. 创建成功后提示
Copying configuration to new core instance directory:
/opt/solr/server/solr/mycore

Creating new core 'mycore' using command:
http://localhost:8983/solr/admin/cores?action=CREATE&name=mycore&instanceDir=mycore

{
  "responseHeader":{
    "status":0,
    "QTime":2137},
  "core":"mycore"}
  1. 访问linux的ip地址:8983
    例:192.168.153.133:8983
    在这里插入图片描述

7.solr搜索

  • 假设提交
{"id":"change.me","title":"change.me"}
  • q表示按照什么字段来搜索
字段名:值  (where 列名=值)
支持or 和and语法 
比如 i:1 and j:2
  • 模拟数据
    在这里插入图片描述

  • 数据查询,现在还没做分词,必须去全词比配才有值
    在这里插入图片描述

8.配置分词器

  • 默认solr 没有使用中文分词器 所有搜索的词 都是整个句子就是一个词 搜索时 将单词全部写入才能搜索或者使用* 需要配置中文分词器
  • 目前比较好用的分词器 是IK 2012年停更 只支持到 Lucene4.7 所有 solr5.5 需要lucene5支持 需要修改部分源码来支持solr5.5
  • 找到 IKAnalyzer类 需要重写 protected TokenStreamComponents createComponents(String fieldName) 方法
  • 找到 IKTokenizer类 需要重写构造方法 public IKTokenizer(Reader in, boolean useSmart) 为 public IKTokenizer(boolean useSmart)
  1. 创建一个maven项目
  2. pom.xml添加
    下载ikanalyzer后默认是2.4.7版本,要替换成5.5.5版本
		<!-- https://mvnrepository.com/artifact/com.janeluo/ikanalyzer -->
		<dependency>
			<groupId>com.janeluo</groupId>
			<artifactId>ikanalyzer</artifactId>
			<version>2012_u6</version>
		</dependency>
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-analyzers-common</artifactId>
			<version>5.5.5</version>
		</dependency>
		
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-core</artifactId>
			<version>5.5.5</version>
		</dependency>
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-queryparser</artifactId>
			<version>5.5.5</version>
		</dependency>
  1. 重写IKAnalyzer类和IKTokenizer类
  • 先创建包
org.wltea.analyzer.lucene
  • IKAnalyzer类
package org.wltea.analyzer.lucene;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Tokenizer;

/**
 * IK分词器,Lucene Analyzer接口实现
 * 兼容Lucene 4.0版本
 */
public final class IKAnalyzer extends Analyzer {

  private boolean useSmart;

  public boolean useSmart() {
    return useSmart;
  }

  public void setUseSmart(boolean useSmart) {
    this.useSmart = useSmart;
  }

  /**
   * IK分词器Lucene  Analyzer接口实现类
   *
   * 默认细粒度切分算法
   */
  public IKAnalyzer() {
    this(false);
  }

  /**
   * IK分词器Lucene Analyzer接口实现类
   *
   * @param useSmart 当为true时,分词器进行智能切分
   */
  public IKAnalyzer(boolean useSmart) {
    super();
    this.useSmart = useSmart;
  }

  /**
   * 重载Analyzer接口,构造分词组件
   */
  @Override
  protected TokenStreamComponents createComponents(String fieldName) {
    Tokenizer _IKTokenizer = new IKTokenizer(this.useSmart());
    return new TokenStreamComponents(_IKTokenizer);
  }

}
  • IKTokenizer类
package org.wltea.analyzer.lucene;

import java.io.IOException;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;

/**
 * IK分词器 Lucene Tokenizer适配器类
 * 兼容Lucene 4.0版本
 */
public final class IKTokenizer extends Tokenizer {

  // IK分词器实现
  private IKSegmenter _IKImplement;

  // 词元文本属性
  private final CharTermAttribute termAtt;
  // 词元位移属性
  private final OffsetAttribute offsetAtt;
  // 词元分类属性(该属性分类参考org.wltea.analyzer.core.Lexeme中的分类常量)
  private final TypeAttribute typeAtt;
  // 记录最后一个词元的结束位置
  private int endPosition;

  /**
   * Lucene 4.0 Tokenizer适配器类构造函数
   * @param in
   * @param useSmart
   */
  public IKTokenizer(boolean useSmart) {
    offsetAtt = addAttribute(OffsetAttribute.class);
    termAtt = addAttribute(CharTermAttribute.class);
    typeAtt = addAttribute(TypeAttribute.class);
    _IKImplement = new IKSegmenter(input, useSmart);
  }

  /*
   * (non-Javadoc)
   * @see org.apache.lucene.analysis.TokenStream#incrementToken()
   */
  @Override
  public boolean incrementToken() throws IOException {
    // 清除所有的词元属性
    clearAttributes();
    Lexeme nextLexeme = _IKImplement.next();
    if (nextLexeme != null) {
      // 将Lexeme转成Attributes
      // 设置词元文本
      termAtt.append(nextLexeme.getLexemeText());
      // 设置词元长度
      termAtt.setLength(nextLexeme.getLength());
      // 设置词元位移
      offsetAtt.setOffset(nextLexeme.getBeginPosition(), nextLexeme.getEndPosition());
      // 记录分词的最后位置
      endPosition = nextLexeme.getEndPosition();
      // 记录词元分类
      typeAtt.setType(nextLexeme.getLexemeTypeString());
      // 返会true告知还有下个词元
      return true;
    }
    // 返会false告知词元输出完毕
    return false;
  }

  /*
   * (non-Javadoc)
   * @see org.apache.lucene.analysis.Tokenizer#reset(java.io.Reader)
   */
  @Override
  public void reset() throws IOException {
    super.reset();
    _IKImplement.reset(input);
  }

  @Override
  public final void end() {
    // set final offset
    int finalOffset = correctOffset(this.endPosition);
    offsetAtt.setOffset(finalOffset, finalOffset);
  }
}
  1. 将ikanalyzer里的IKAnalyzerClass文件IKTokenizerClass文件替换成自己写的Class文件
    在这里插入图片描述
    替换到
    在这里插入图片描述

  2. 将替换好的jar包放到linux里面
    在这里插入图片描述

9.solr中文分词器配置

  1. 进入my_solr容器
docker exec -it my_solr bash

2.在当前目录下搜索lib

find . -name lib
  1. 查看my_solr容器jar包所在位置
cd server/solr-webapp/webapp/WEB-INF/lib
  1. 将linux拷贝过来的jar包拷进server/solr-webapp/webapp/WEB-INF/lib目录下
docker cp ./ikanalyzer-2012_u6.jar my_solr:/opt/solr/server/solr-webapp/webapp/WEB-INF/lib/
  1. 重启docker
关闭:docker stop my_solr
开启:docker start my_solr
  1. 拷贝my_solr容器里的managed-schema文件到linux /opt/ika/目录下去修改,配置文分词
docker cp my_solr:/opt/solr/server/solr/mycore/conf/managed-schema /opt/ika/
  1. 打开 managed-schema文件
<uniqueKey>标签表示主键
<fieldType name="stirng">设置数据类型
<dynamicField>动态字段
  1. 配置搜索引擎
<fieldType name="text_ik" class="solr.TextField" >  
      <analyzer type="index" isMaxWordLength="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/>  
      <analyzer type="query" isMaxWordLength="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
  </fieldType>

indexed代表倒排索引
stored代表存储数据
在这里插入图片描述

  1. 关掉my_solr容器
docker stop my_solr
  1. 将修改好的managed-schema文件拷贝my_solr:/opt/solr/server/solr/mycore/conf/目录下
docker cp ./managed-schema my_solr:/opt/solr/server/solr/mycore/conf/
  1. 重启my_solr容器
docker start my_solr
  1. 进行引擎搜索测试
  • 图1
    在这里插入图片描述

  • 图2
    在这里插入图片描述

10.数据库数据迁移solr

  • 拷贝支持导入的jar三个
  1. 进入my_solr容器拷贝2个jar
docker exec -it my_solr bash
cp /opt/solr/dist/solr-dataimporthandler-5.5.5.jar /opt/solr/server/solr-webapp/webapp/WEB-INF/lib
cp /opt/solr/dist/solr-dataimporthandler-extras-5.5.5.jar /opt/solr/server/solr-webapp/webapp/WEB-INF/lib
  1. 第3个数据库驱动类,我使用的5.1.14版本
    下载:https://mvnrepository.com/artifact/mysql/mysql-connector-java
    将下载好的jar包放到/opt/ika目录下在拷到my_solr的/opt/solr/server/solr-webapp/webapp/WEB-INF/lib目录下
docker cp ./mysql-connector-java-5.1.14.jar  my_solr:/opt/solr/server/solr-webapp/webapp/WEB-INF/lib
  1. 在opt/ika目录下创建data_c.xml文件配置如下
<?xml version="1.0" encoding="UTF-8"?>  
<dataConfig>  
    <dataSource name="source1" type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://192.168.0.198:3306/unit02" user="root" password="ps123456" batchSize="-1" />  
<document>  
        <entity name="user_t" pk="id"  dataSource="source1"   
                query="select * from  user_t" >
            <field column="id" name="id"/>
            <field column="names" name="names_ik"/>
        </entity>
</document>
</dataConfig>
  1. 拷贝到my_solr:/opt/solr/server/solr/mycore/conf目录下
docker cp ./data_c.xml my_solr:/opt/solr/server/solr/mycore/conf

5.修改solrconfig.xml 指定data-c.xml文件先把solrconfig.xml文件从my_solr容器中拷贝出来,.代表当前目录

docker cp my_solr:/opt/solr/server/solr/mycore/conf/solrconfig.xml .

6.先solrconfig.xml增加内容

<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">  
	<lst name="defaults">  
		<str name="config">data_c.xml</str>  
	</lst> 
 </requestHandler>
  1. 再将solrconfig.xml拷贝到my_solr:/opt/solr/server/solr/mycore/conf目录下
docker cp ./solrconfig.xml my_solr:/opt/solr/server/solr/mycore/conf
  1. 重启my_solr容器
docker restart my_solr

访问页面是出现

在这里插入图片描述
说明:这个两个jar包没考到/opt/solr/server/solr-webapp/webapp/WEB-INF/lib目录下

  • solr-dataimporthandler-5.5.5.jar

  • solr-dataimporthandler-extras-5.5.5.jar

  • 访问solrweb管理界面 http://ip:
    在这里插入图片描述

11.使用Windows实现

  1. 创建SOLR Maven项目
    在这里插入图片描述
  2. 引入依赖pom.xml
	<!-- 集成SpringBoot -->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.10.RELEASE</version>
		<relativePath />
	</parent>
	
	<dependencies>
	
		<!-- 引入SpringMvc -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		
		<!-- 引入solr -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-solr</artifactId>
		</dependency>
		
	</dependencies>
  1. 配置文件application.yml
spring: 
  data: 
    solr: 
      #指定solr的ip端口
      host: http://192.168.153.133:8983/solr
server: 
  #端口号
  port: 8888
  1. 程序入口SolrMain
package cn.ps;

import org.apache.solr.client.solrj.SolrClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.solr.core.SolrTemplate;

@SpringBootApplication
public class SolrMain {
	
	/**
	 * 初始化SolrTemplate对象
	 * @param client
	 * @return
	 */
	@Bean
	 public SolrTemplate solrTemplate(SolrClient client) {
	    return new SolrTemplate(client);
	}
	
	public static void main(String [] args) {
		SpringApplication.run(SolrMain.class, args);
	}

}
  1. 控制层SolrController
package cn.ps.controller;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.SimpleQuery;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.ps.entity.User;

@RestController
public class SolrController {
	
	/**
	 * 用来操作Solr
	 */
	@Autowired
	SolrTemplate st;
	
	@GetMapping("user")
	public List<User> queryUser(String keyWord){
		//将浏览器传过来的数据赋给names_ik引擎搜索的键值
		SimpleQuery sq = new SimpleQuery("names_ik:"+keyWord);
		//去Solr里查询数据
		Page<User> query = st.query(sq, User.class);
		//返回查询出来的数据
		List<User> content = query.getContent();
		return content;
	}
	
}
  1. 实体类User
package cn.ps.entity;

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

//指定Solr的核心
@SolrDocument(solrCoreName="mycore")
public class User {
	
	private String id;
	
	//设置引擎搜索变量names_ik
	@Field("names_ik")
	private String names;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getNames() {
		return names;
	}
	public void setNames(String names) {
		this.names = names;
	}
	
}
  1. 页面index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="jquery-3.3.1.js"></script>
<script type="text/javascript">
	function query(){
		$.ajax({
			url:'user',
			dataType:'json',
			type:'get',
			data:'keyWord='+ $("#key").val(),
			success:function(data){
				$("#myUser").text(JSON.stringify(data))
			}
		})
	}
</script>
</head>
<body>
	故事:<input id="key" type="text" name="keyWord"><button onclick="query()" value="查询">查询</button>
	<div id="myUser"></div>
</body>
</html>

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值