solr应用

一 。solr简介

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

文章表

TYPEASCIIHTML
文章id文章标题文章内容
1我爱中国中国地大物博
2香港是中国一部分香港的英文是hongkong

倒排索引

索引文章id
1
1
中国1,2
香港2
2
一部分2
二。分词器

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

三。lucene

lucene是一个将text数据类型,分词建立索引的一个库,不适合企业级使用。
企业级考虑高可用问题。
solr是一个企业级应用的搜索引擎。
支持使用json格式提交数据。

json格式:

[] 代表数组
{} 对象(文档 document)
键值对 属性
{
id:1
hobby:[“篮球”,“上厕所”]
tt:{
}
}

数据库表结构:

文章id 文章标题 文章内容
1 我爱中国 中国地大物博
2 香港是中国一部分 香港的英文是hongkong

模拟json

[
{
id:1,
title:‘我爱中国’,
content:‘中国地大物博’

},
{
id:2,
title:‘香港是中国一部分’,
content:‘香港的英文是hongkong’
}
]

四 。solr安装

核(core):是用于存储json格式的数据,等价于mysql中数据库的概念
文档:一个json对象就是一个文档 相同属性的json数组集合就是一个表

docker安装solr

 docker run --name my_solr -id --net host -t solr:5.5.5

检测端口

 netstat -aon | grep 8983
 yum -y install net-tools telnet

创建完成后提示:

[root@localhost ~]# docker exec -it --user=solr my_solr bin/solr create_core -c mycore

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"}
五。solr搜索

假设提交:
{“id”:“change.me”,“title”:“change.me”}
q表示安装什么字段来搜索
字段名:值 (where 列名=值)
支持or 和and语法
比如 i:1 and j:2
比如 i[1 to 10]

模拟数据:

{
     "id":"1",
     "title":"我爱中国",
     "content":"中国地大物博"
 }
六。solr中文分词器配置

生成ik支持5.5.5的ikjar包
jar拷贝到 /opt/solr/server/solr-webapp/webapp/WEB-INF/lib
进入core对应的目录
/opt/solr/server/solr/mycore
类型定义文件目录
/opt/solr/server/solr/mycore/conf/managed-schema

修改文件 managed-schema
定义分词器数据类型:

<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>

定义动态字段:

 <dynamicField name="*_ik" type="text_ik" indexed="true" stored="true"/>

插入json:

{
     "id":"3",
     "title_ik":"我爱中国",
     "content_ik":"中国地大物博"
 }
七。数据库数据迁移solr

拷贝支持导入的jar:

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
docker cp ./mysql-connector-java-5.1.24.jar  my_solr:/opt/solr/server/solr-webapp/webapp/WEB-INF/lib

进入mycore/conf目录 新建连接数据的四要素

 /opt/solr/server/solr/mycore/conf/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.1.3:3306/test" user="root" password="123456" batchSize="-1" />  
    <document>          
     <entity name="book" pk="newid"  dataSource="source1"   
                query="select * from  mynew" >
        	<field column="newid" name=""/>     
  		  <field column="newtitle" name="title_ik"/>  
     </entity>
  </document> 
</dataConfig>
docker cp ./data-c.xml  my_solr:/opt/solr/server/solr/mycore/conf

修改solrconfig.xml 指定data-c.xml文件

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

内容:

<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">  
    <lst name="defaults">    
  		<str name="config">data-c.xml</str>  
 	</lst> 
</requestHandler>
docker cp ./solrconfig.xml my_solr:/opt/solr/server/solr/mycore/conf

所有实际步骤如下:

》配置中文分词器

默认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) {

在任意项目中 使用maven 引用lucene5 和ik

<dependency>
	 <groupId>org.apache.lucene</groupId>
	  <artifactId>lucene-core</artifactId>
 	 <version>5.3.1</version>
</dependency>
<dependency>
		<groupId>com.janeluo</groupId>
		<artifactId>ikanalyzer</artifactId>
		<version>2012_u6</version>
		<exclusions>
		<exclusion>
			<groupId>org.apache.lucene</groupId>
	 		 <artifactId>lucene-core</artifactId>
		</exclusion>
		</exclusions>
</dependency>

在项目中 添加完整的包名和类名 和 ik中一致 拷贝源代码
在这里插入图片描述
代码修改对应的方法即可

IKAnalyzer

package org.wltea.analyzer.lucene;
 
import java.io.Reader;
 
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Tokenizer;
public final class IKAnalyzer extends Analyzer {
 
  private boolean useSmart;

  public boolean useSmart() {
    return useSmart;
  }
 
  public void setUseSmart(boolean useSmart) {
    this.useSmart = useSmart;
  }
 
  public IKAnalyzer() {
    this(false);
  }
  public IKAnalyzer(boolean useSmart) {
    super();
    this.useSmart = useSmart;
  }
  /**这里就去掉了 Reader的一个参数
   */
  @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 java.io.Reader;
 
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;

public final class IKTokenizer extends Tokenizer {
  
  private IKSegmenter _IKImplement;
 
  private final CharTermAttribute termAtt;
 
  private final OffsetAttribute offsetAtt;
 
  private final TypeAttribute typeAtt;
 
  private int endPosition;
 
  //去掉了其中Reader的第一个构造参数
  public IKTokenizer(boolean useSmart) {
    super();//去掉super中的构造参数
    offsetAtt = addAttribute(OffsetAttribute.class);
    termAtt = addAttribute(CharTermAttribute.class);
    typeAtt = addAttribute(TypeAttribute.class);
    _IKImplement = new IKSegmenter(input, useSmart);
  }
 
 
  @Override
  public boolean incrementToken() throws IOException {
 
    clearAttributes();
    Lexeme nextLexeme = _IKImplement.next();
    if (nextLexeme != null) {
 
      termAtt.append(nextLexeme.getLexemeText());
   
      termAtt.setLength(nextLexeme.getLength());
      
      offsetAtt.setOffset(nextLexeme.getBeginPosition(), nextLexeme.getEndPosition());
   
      endPosition = nextLexeme.getEndPosition();
  
      typeAtt.setType(nextLexeme.getLexemeTypeString());
 
      return true;
    }
 
    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);
  }
}

将编译好的class文件替换原始jar包即可

将solrhome下 配置文件managed-schema 添加一个字段类型 使用ik分词器

<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>

不能修改 StrField 不支持自定义分词器

<fieldType name="string" class="solr.StrField" sortMissingLast="true" >
</fieldType>

然后将对应需要进行中文分词的字段使用 text_ik该字段类型 比如

<dynamicField name="*_s"  type="text_ik"  indexed="true"  stored="true" />

重启 或者 cloud环境下重新生成collection 插入数据即可实现中文词通过某些中文关键字搜索

》初始全量导入数据库数据

假设存在表 news表示 其中 有以下数据:
在这里插入图片描述
进入solr所在服务器 搜索 dataimport相关jar包

solr@localhost:/opt/solr$ find / -name *import*.jar
/opt/solr/dist/solr-dataimporthandler-5.5.5.jar
/opt/solr/dist/solr-dataimporthandler-extras-5.5.5.jar

将这两个jar包拷贝到 solr启动应用 webapp/lib目录下

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

同时将mysql的驱动包 丢到该目录下

编辑core的conf/solrconfig.xml 添加

<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">  
      <lst name="defaults">  
         <str name="config">data-config.xml</str>  
      </lst>  
 </requestHandler>

在solrconfig.xml同一目录下 添加 data-config.xml(配置连接的数据库以及查询的sql语句 )

<?xml version="1.0" encoding="UTF-8"?>  
<dataConfig>  
    <dataSource name="source1" type="JdbcDataSource" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://192.168.1.3:3306/test" user="root" password="123456" batchSize="-1" />  
<document>  
          <entity name="book" pk="newid"  dataSource="source1"   
                query="select * from  mynew" >
            <field column="newid" name=""/>  
            <field column="newtitle" name="title_ik"/>  
        </entity>
</document>  
</dataConfig>  

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

solr客户端 实例演示

solr提供的solrj java客户端可以使用java来添加和查询索引

使用maven引入solrj的依赖库

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		 <version>1.5.10.RELEASE</version>
	 </parent>
	<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>
		</dependency>
	</dependencies>

SolrMain

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 {
	public static void main(String[] args) {
		SpringApplication.run(SolrMain.class, args);
	}
}

Emp

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

@SolrDocument(solrCoreName="mycore")
public class Emp {
	private String id;
	@Field("ename_ik")
	private String ename;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getEname() {
		return ename;
	}
	public void setEname(String ename) {
		this.ename = ename;
	}
}

SolrController

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.Emp;

@RestController
public class SolrController {
	@Autowired
	private SolrTemplate st;
	@GetMapping("/queryEmp")
	public List<Emp> queryEmp(String keyword){
		SimpleQuery sq=new SimpleQuery("ename_ik:"+keyword);
		Page<Emp> query = st.query(sq, Emp.class);
		return query.getContent();
	}
}

application.yml配置文件

spring: 
  data: 
    solr: 
      host: http://192.168.67.128:8983/solr
server: 
  port: 8888  

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">
</script>
<script>
	function query(){
		$.ajax({
			url:'queryEmp',
			dataType:'json',
			data:'keyword='+$("#myKeyWord").val(),
			type:'get',
			success:function(r){
				$("#myEmp").html(JSON.stringify(r));
			}
		});
	}
</script>
</head>
<body>

	新闻:<input id="myKeyWord" type="text" name="keyword"><button onclick="query()">搜索</button>
<div id="myEmp">

</div>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值