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>
1 概述 4 1.1 企业搜索引擎方案选型 4 1.2 Solr的特性 4 1.2.1 Solr使用Lucene并且进行了扩展 4 1.2.2 Schema(模式) 5 1.2.3 查询 5 1.2.4 核心 5 1.2.5 缓存 5 1.2.6 复制 6 1.2.7 管理接口 6 1.3 Solr服务原理 6 1.3.1 索引 6 1.3.2 搜索 7 1.4 源码结构 8 1.4.1 目录结构说明 8 1.4.2 Solr home说明 9 1.4.3 solr的各包的说明 10 1.5 版本说明 11 1.5.1 1.3版本 11 1.5.2 1.4版本 12 1.6 分布式和复制 Solr 架构 13 2 Solr的安装与配置 13 2.1 在Tomcat下Solr安装 13 2.1.1 安装准备 13 2.1.2 安装过程 14 2.1.3 验证安装 15 2.2 中文分词配置 15 2.2.1 mmseg4j 15 2.2.2 paoding 19 2.3 多核(MultiCore)配置 22 2.3.1 MultiCore的配置方法 22 2.3.2 为何使用多core ? 23 2.4 配置文件说明 23 2.4.1 schema.xml 24 2.4.2 solrconfig.xml 25 3 Solr应用 29 3.1 SOLR应用概述 29 3.1.1 Solr应用模式 29 3.1.2 SOLR的使用过程说明 30 3.2 一个简单的例子 30 3.2.1 Solr Schema 设计 30 3.2.2 构建索引 30 3.2.3 搜索测试 31 3.3 搜索引擎的规划设计 32 3.3.1 定义业务模型 32 3.3.2 定制索引服务 34 3.3.3 定制搜索服务 34 3.4 搜索引擎配置 34 3.4.1 Solr Schema 设计(如何定制索引的结构?) 34 3.5 如何进行索引操作? 36 3.5.1 基本索引操作 36 3.5.2 批量索引操作 37 3.6 如何进行搜索 39 3.6.1 搜索语法 39 3.6.2 排序 42 3.6.3 字段增加权重 42 3.6.4 Solr分词器、过滤器、分析器 42 3.6.5 Solr高亮使用 46 4 SolrJ的用法 46 4.1 搜索接口的调用实例 46 4.2 Solrj的使用说明 47 4.2.1 Adding Data to Solr 47 4.2.2 Directly adding POJOs to Solr 49 4.2.3 Reading Data from Solr 51 4.3 创建查询 51 4.4 使用 SolrJ 创建索引 52 4.5 Solrj包的结构说明 53 4.5.1 CommonsHttpSolrServer 53 4.5.2 Setting XMLResponseParser 53 4.5.3 Changing other Connection Settings 53 4.5.4 EmbeddedSolrServer 54 5 Solr的实际应用测试报告 54 5.1 线下压力测试报告 54 5.2 线上环境运行报告 54 6 solr性能调优 55 6.1 Schema Design Considerations 55 6.1.1 indexed fields 55 6.1.2 stored fields 55 6.2 Configuration Considerations 55 6.2.1 mergeFactor 55 6.2.2 mergeFactor Tradeoffs 56 6.3 Cache autoWarm Count Considerations 56 6.4 Cache hit rate(缓存命中率) 56 6.5 Explicit Warming of Sort Fields 56 6.6 Optimization Considerations 56 6.7 Updates and Commit Frequency Tradeoffs 56 6.8 Query Response Compression 57 6.9 Embedded vs HTTP Post 57 6.10 RAM Usage Considerations(内存方面的考虑) 57 6.10.1 OutOfMemoryErrors 57 6.10.2 Memory allocated to the Java VM 57 7 FAQ 58 7.1 出现乱码或者查不到结果的排查方法: 58
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值