java框架复习——solr(待更新)

概述

Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。

Solr可以独立运行,运行在Jetty、Tomcat等这些Servlet容器中,Solr 索引的实现方法很简单,用 POST 方法向 Solr 服务器发送一个描述 Field 及其内容的 XML 文档,Solr根据xml文档添加、删除、更新索引 。

Solr 搜索只需要发送 HTTP GET 请求,然后对 Solr 返回Xml、json等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。
在这里插入图片描述

Solr目录结构

在这里插入图片描述
bin:solr的运行脚本
contrib:solr的一些贡献软件/插件,用于增强solr的功能。
dist:该目录包含build过程中产生的war和jar文件,以及相关的依赖文件。
docs:solr的API文档
example:solr工程的例子目录:

  • example/solr:
    该目录是一个包含了默认配置信息的Solr的Core目录。
  • example/multicore:
    该目录包含了在Solr的multicore中设置的多个Core目录。
  • example/webapps:
    该目录中包括一个solr.war,该war可作为solr的运行实例工程。

licenses:solr相关的一些许可信息

Solr与Tomcat整合配置

可以参考以下文章
https://blog.csdn.net/qq_35262405/article/details/95476021

Solr管理界面

访问http://localhost:8080/solr,可以看到以下界面
在这里插入图片描述
管理界面中的页面如下:

  • Dashboard

仪表盘,显示了该Solr实例开始启动运行的时间、版本、系统资源、jvm等信息。

  • Logging

Solr运行日志信息

  • Cloud

Cloud即SolrCloud,即Solr云(集群),当使用Solr Cloud模式运行时会显示此菜单,如下图是Solr Cloud的管理界面:
在这里插入图片描述

  • Core Admin

Solr Core的管理界面。Solr Core 是Solr的一个独立运行实例单位,它可以对外提供索引和搜索服务,一个Solr工程可以运行多个SolrCore(Solr实例),一个Core对应一个索引目录。

  • java properties

Solr在JVM 运行环境中的属性信息,包括类路径、文件编码、jvm内存设置等信息。

  • Tread Dump

显示Solr Server中当前活跃线程信息,同时也可以跟踪线程运行栈信息。

  • Core selector

选择一个SolrCore进行详细操作,如下:
在这里插入图片描述

  • Analysis(重点)

在这里插入图片描述
通过此界面可以测试索引分析器和搜索分析器的执行情况。

  • dataimport

可以定义数据导入处理器,从关系数据库将数据导入 到Solr索引库中。

  • Document(重点)

通过此菜单可以创建索引、更新索引、删除索引等操作,界面如下:
在这里插入图片描述
/update表示更新索引,solr默认根据id(唯一约束)域来更新Document的内容,如果根据id值搜索不到id域则会执行添加操作,如果找到则更新。

  • query(重点)

在这里插入图片描述
通过/select执行搜索索引,必须指定“q”查询条件方可搜索。

Solr索引

scheam.xml

schema.xml,在SolrCore的conf目录下,它是Solr数据表配置文件,它定义了加入索引的数据的数据类型的。主要包括FieldTypes、Fields和其他的一些缺省设置。
在这里插入图片描述

FieldType域类型定义

下边“text_general”是Solr默认提供的FieldType,通过它说明FieldType定义的内容:
在这里插入图片描述
FieldType子结点包括name,class,positionIncrementGap等一些参数:
在这里插入图片描述
在FieldType定义的时候最重要的就是定义这个类型的数据在建立索引和进行查询的时候要使用的分析器analyzer,包括分词和过滤

索引分析器中:使用solr.StandardTokenizerFactory标准分词器,solr.StopFilterFactory停用词过滤器,solr.LowerCaseFilterFactory小写过滤器。

搜索分析器中:使用solr.StandardTokenizerFactory标准分词器,solr.StopFilterFactory停用词过滤器,这里还用到了solr.SynonymFilterFactory同义词过滤器。

precisionStep的具体作用

1.precisionStep是在做range search的起作用的,默认值是4

2.数值类型(int float double)在Lucene里都是以string形式存储的,当然这个string是经过编码的

3.经过编码后的string保证是顺序的,也就是说num1>num2,那么strNum1>strNum2

4.precisionStep用来分解编码后的string,例如有一个precisionStep,默认是4,也就是隔4位索引一个前缀,比如0100,0011,0001,1010会被分成下列的二进制位“0100,0011,0001,1010“,”0100,0011,0001“,0100,0011“,”0100“。这个值越大,那么索引就越小,那么范围查询的性能(尤其是细粒度的范围查询)也越差;这个值越小,索引就越大,那么性能越差。

5.range search的过程参见下图:
在这里插入图片描述
如果用户希望查找423~642的记录,如果没有precisionStep,那么就必须从最底层一个一个匹配了,性能肯定不行。有了precisionStep,那么range search可以这么做:44可以匹配445,446,448,而5可以匹配521,522;63可以匹配632,633,634;而只有423,641,642在最底层匹配。

Field定义

在fields结点内定义具体的Field,filed定义包括nametype(为之前定义过的各种FieldType)indexed(是否被索引)stored(是否被储存)multiValued(是否存储多个值)等属性。

<field name="name" type="text_general" indexed="true" stored="true"/>
<field name="features" type="text_general" indexed="true" stored="true" multiValued="true"/>

在这里插入图片描述
multiValued:该Field如果要存储多个值时设置为true,solr允许一个Field存储多个值,比如存储一个用户的好友id(多个),商品的图片(多个,大图和小图),通过使用solr查询要看出返回给客户端是数组:
在这里插入图片描述

uniqueKey

Solr中默认定义唯一主键key为id域,如下:
在这里插入图片描述
Solr在删除、更新索引时使用id域进行判断,也可以自定义唯一主键。

注意在创建索引时必须指定唯一约束。

copyField复制域

copyField复制域,可以将多个Field复制到一个Field中,以便进行统一的检索:
比如,输入关键字搜索title标题内容content

定义title、content、text的域:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
根据关键字只搜索text域的内容就相当于搜索title和content,将title和content复制到text中,如下:
在这里插入图片描述

dynamicField(动态字段)

动态字段就是不用指定具体的名称,只要定义字段名称的规则,例如定义一个 dynamicField,name 为_i,定义它的type为text,那么在使用这个字段的时候,任何以_i结尾的字段都被认为是符合这个定义的,例如:name_i,gender_i,school_i等。*

自定义Field名为:product_title_t,“product_title_t”和scheam.xml中的dynamicField规则匹配成功,如下:
在这里插入图片描述
“product_title_t”是以“_t”结尾

创建索引
在这里插入图片描述
搜索索引
在这里插入图片描述

安装中文分词器IKAnalyzer

IKAnalyzer部署

拷贝IKAnalyzer的文件到Tomcat下Solr目录中,将IKAnalyzer2012FF_u1.jar拷贝到 Tomcat的webapps/solr/WEB-INF/lib下。

在Tomcat的webapps/solr/WEB-INF/下创建classes目录,将IKAnalyzer.cfg.xmlext_stopword.dicmydict.dic copy到 Tomcat的
webapps/solr/WEB-INF/classes

注意:ext_stopword.dic 和mydict.dic必须保存成无BOM的utf-8类型。

修改schema.xml文件

FieldType

首先需要在types结点内定义一个FieldType子结点,包括name,class等参数,name就是这个FieldType的名称,class指向org.apache.solr.analysis包里面对应的class名称,用来定义这个类型的行为。

在FieldType定义的时候最重要的就是定义这个类型的数据在建立索引和进行查询的时候要使用的分析器analyzer,包括分词和过滤。

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

Field

FieldType定义好后就可以在fields结点内定义具体的field,filed定义包括name,type(即FieldType),indexed(是否被索引),stored(是否被储存),multiValued(是否有多个值)等。

<!--IKAnalyzer Field-->
<field name="title_ik" type="text_ik" indexed="true" stored="true" />
<field name="content_ik" type="text_ik" indexed="true" stored="false" multiValued="true"/>
设置业务系统Field

如果不使用Solr提供的Field可以针对具体的业务需要自定义一套Field,如下是商品信息Field:

<!--product-->
<field name="product_name" type="text_ik" indexed="true" stored="true"/>
<field name="product_price"  type="float" indexed="true" stored="true"/>
<field name="product_description" type="text_ik" indexed="true" stored="false" />
<field name="product_picture" type="string" indexed="false" stored="true" />
<field name="product_catalog_name" type="string" indexed="true" stored="true" />

<field name="product_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="product_name" dest="product_keywords"/>
<copyField source="product_description" dest="product_keywords"/>

索引维护

使用/update进行索引维护,进入Solr管理界面SolrCore下的Document下:
在这里插入图片描述
overwrite="true" : solr在做索引的时候,如果文档已经存在,就用xml中的文档进行替换

commitWithin="10000": solr 在做索引的时候,每个10000(10秒)毫秒,做一次文档提交。

为了方便测试也可以在Document中立即提交,在后边添加“”,如下:

<add>
<doc>
<field name="id">change.me</field>
<field name="title">change.me</field>
</doc>
</add>
<commit/>
添加/更新索引

solr默认根据id(唯一约束)域来更新Document的内容,如果根据id值搜索不到id域则会执行添加操作,如果找到则更新。

<add>
<doc>
<field name="id">change.me</field>
<field name="??" >??</field>
。。。
</doc>
</add>

说明:唯一标识 Field必须有,这里使用Solr默认的id。

删除索引

删除制定ID的索引

<delete>
	<id>8</id>
	。。。
</delete>

删除查询到的索引数据

<delete>
	<query>product_catalog_name:幽默杂货</query>
</delete>

删除所有索引数据

<delete>
	<query>*:*</query>
</delete>

dataimport-handler

安装dataimport-Handler从关系数据库将数据导入到索引库。

第一步:向SolrCore中加入jar包

在SolrCore目录中创建lib目录,将dataimportHandler和mysql数据库驱动的jar拷贝至lib下。

dataimportHandler在solr安装目录的dist 下:
在这里插入图片描述

第二步:修改solrconfig.xml,添加requestHandler

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

第三步:编辑data-config.xml文件,存放在SolrCore的conf目录

<?xml version="1.0" encoding="UTF-8" ?>  
<dataConfig>   
<dataSource type="JdbcDataSource"   
		  driver="com.mysql.jdbc.Driver"   
		  url="jdbc:mysql://localhost:3306/lucene"   
		  user="root"   
		  password="mysql"/>   
<document>   
	<entity name="product" query="SELECT pid,name,catalog_name,price,description,picture FROM products ">
		 <field column="pid" name="id"/> 
		 <field column="name" name="product_name"/> 
		 <field column="catalog_name" name="product_catalog_name"/> 
		 <field column="price" name="product_price"/> 
		 <field column="description" name="product_description"/> 
		 <field column="picture" name="product_picture"/> 
	</entity>   
</document>   
</dataConfig>

<field column="pid" name="id"/>必须有一个id域,这里使用Solr默认的id域,域值是从关系数据库查询的pid列值。

下边以“product_”开头的Field都是在schema.xml中自定义的商品信息Field。

第四步:重启Tomcat,进入管理界面–》SolrCore–》dataimport下执行导入
在这里插入图片描述
如果有什么问题可以参考在tomcat上solr服务器的搭建(5.2.0)

第五步:查看导入结果

进入管理界面–》SolrCore–》dataimport下
在这里插入图片描述

Solr搜索

requestHandler

可以通过get的方式直接访问Solr的服务来查询

<requestHandler name="/select" class="solr.SearchHandler">
    <!-- 设置默认的参数值,可以在请求地址中修改这些参数-->
    <lst name="defaults">
         <str name="echoParams">explicit</str>
        <int name="rows">10</int><!--显示数量-->
        <str name="wt">json</str><!--显示格式-->
        <str name="df">text</str><!--默认搜索字段-->
    </lst>
</requestHandler>
http://localhost:8080/solr/core/select?wt=json&q=product_keywords:%E6%B5%AA%E6%BC%AB%E6%A8%B1%E8%8A%B1%20AND%20product_keywords:%E9%9F%A9%E5%9B%BD%20OR%20product_catalog_name:%E4%B8%8E%E9%92%9F%E4%B8%8D%E5%90%8C&indent=on

上面这个请求等同于
在这里插入图片描述

查询语法

通过/select搜索索引,Solr制定一些参数完成不同需求的搜索

q - 查询字符串

如果查询所有使用*:*
在这里插入图片描述

fq - (filter query)过虑查询

在q查询符合结果中同时是fq查询符合的
在这里插入图片描述
过滤查询价格从1到20的记录

也可以在“q”查询条件中使用product_price:[1 TO 20],如下:
在这里插入图片描述
也可以使用“*”表示无限,例如:

20以上:product_price:[20 TO \*]
20以下:product_price:[* TO 20]
sort - 排序
sort=<field name>+<desc|asc>[,<field name>+<desc|asc>]… 

在这里插入图片描述
按价格降序

start - 分页显示使用

开始记录下标,从0开始

rows - 指定返回结果最多有多少条记录

配合start来实现分页
在这里插入图片描述
表示显示前10条

fl - 指定返回那些字段内容

用逗号或空格分隔多个
在这里插入图片描述
显示商品图片、商品名称、商品价格

df - 指定一个搜索Field

在这里插入图片描述
也可以在SolrCore目录 中conf/solrconfig.xml文件中指定默认搜索Field,指定后就可以直接在“q”查询条件中输入关键字。
在这里插入图片描述

wt - (writer type)指定输出格式

可以有 xml, json, php, phps, 后面 solr 1.3增加的,要用通知我们,因为默认没有打开

hl - 是否高亮

设置高亮Field,设置格式前缀和后缀。
在这里插入图片描述

SolrJ

solrj是访问Solr服务的java客户端,提供索引和搜索的请求方法,SolrJ通常在嵌入在业务系统中,通过SolrJ的API接口操作Solr服务,如下图:在这里插入图片描述

SolrJ对索引的维护

创建索引

使用SolrJ创建索引,通过调用SolrJ提供的API请求Solr服务,Document通过SolrInputDocument进行构建。

// 创建索引
public void testCreateIndex() throws SolrServerException, IOException {
		SolrServer solrServer = new HttpSolrServer(urlString);
		SolrInputDocument document = new SolrInputDocument();
		document.addField("id", "c0001");
		document.addField("product_name", "传智java教程");//商品名称
		document.addField("product_price", 86.5f);//商品价格
		document.addField("product_picture", "382782828.jpg");//商品图片
		document.addField("product_description", "这是一本深入浅出讲解java技术的书籍!");//商品描述
		document.addField("product_catalog_name", "javabook");//商品分类
		
		UpdateResponse response = solrServer.add(document);
		// 提交
		solrServer.commit();
}

说明:根据id(唯一约束)域来更新Document的内容,如果根据id值搜索不到id域则会执行添加操作,如果找到则更新。

删除索引
// 删除索引
@Test
public void testDeleteIndex() throws SolrServerException, IOException {
	SolrServer solrServer = new HttpSolrServer(urlString);
	
	//根据id删除
	UpdateResponse response = solrServer.deleteById("c0001");
	//根据多个id删除
	// solrServer.deleteById(ids);
	//自动查询条件删除
	// solrServer.deleteByQuery("product_keywords:教程");
	// 提交
	solrServer.commit();
}

说明:deleteById(String id)根据id删除索引,此方法为重载方法,也可以传个多个id批量删除,也可以调用deleteByQuery() 根据查询条件删除。

SolrJ完成搜索

搜索索引
// 搜索
@Test
public void testSearch() throws SolrServerException {

	SolrServer solr = new HttpSolrServer(urlString);
	// 查询对象
	SolrQuery query = new SolrQuery();
	//设置查询条件,名称“q”是固定的且必须 的
	//搜索product_keywords域,product_keywords是复制域包括product_name和product_description
	query.set("q", "product_keywords:java教程");
	// 请求查询
	QueryResponse response = solr.query(query);

	// 查询结果
	SolrDocumentList docs = response.getResults();
	// 查询文档总数
	System.out.println("查询文档总数" + docs.getNumFound());

	for (SolrDocument doc : docs) {
		//商品主键
		String id = (String) doc.getFieldValue("id");
		//商品名称
		String product_name = (String) doc.getFieldValue("product_name");
		//商品价格
		Float product_price = (Float) doc.getFieldValue("product_price");
		//商品图片
		String product_picture = (String) doc.getFieldValue("product_picture");
		//商品分类
		String product_catalog_name = (String) doc.getFieldValue("product_catalog_name");
		
		System.out.println("=============================");
		System.out.println(id);
		System.out.println(product_name);
		System.out.println(product_price);
		System.out.println(product_picture);
		System.out.println(product_catalog_name);
	}
}
组合查询
// 根据商品分类、价格范围、关键字查询,查询结果按照价格降序排序
@Test
public void testSearch2() throws SolrServerException {

	SolrServer solr = new HttpSolrServer(urlString);
	// 查询对象
	SolrQuery query = new SolrQuery();
	// 搜索product_keywords域,product_keywords是复制域包括product_name和product_description
	// 设置商品分类、关键字查询
	// query.set("q", "product_keywords:挂钩  AND product_catalog_name:幽默杂货");
	query.setQuery("product_keywords:挂钩  AND product_catalog_name:幽默杂货");

	// 设置价格范围
	query.set("fq", "product_price:[1 TO 20]");

	// 查询结果按照价格降序排序
	// query.set("sort", "product_price desc");
	query.addSort("product_price", ORDER.desc);
	
	// 请求查询
	QueryResponse response = solr.query(query);

	// 查询结果
	SolrDocumentList docs = response.getResults();
	// 查询文档总数
	System.out.println("查询文档总数" + docs.getNumFound());

	for (SolrDocument doc : docs) {
		// 商品主键
		String id = (String) doc.getFieldValue("id");
		// 商品名称
		String product_name = (String) doc.getFieldValue("product_name");
		// 商品价格
		Float product_price = (Float) doc.getFieldValue("product_price");
		// 商品图片
		String product_picture = (String) doc
				.getFieldValue("product_picture");
		// 商品分类
		String product_catalog_name = (String) doc
				.getFieldValue("product_catalog_name");

		System.out.println("=============================");
		System.out.println("id=" + id);
		System.out.println("product_name=" + product_name);
		System.out.println("product_price=" + product_price);
		System.out.println("product_picture=" + product_picture);
		System.out.println("product_catalog_name=" + product_catalog_name);
	}
}
分页、高亮
// 分页和高亮
@Test
public void testSearch3() throws SolrServerException {

	SolrServer solr = new HttpSolrServer(urlString);
	// 查询对象
	SolrQuery query = new SolrQuery();

	// 设置商品分类、关键字查询
	query.setQuery("product_keywords:透明挂钩 ");

	// 分页参数
	// 每页显示记录数
	int pageSize = 2;
	// 当前页码
	int curPage = 2;

	// 开始记录下标
	int begin = pageSize * (curPage - 1);

	// 起始下标
	query.setStart(begin);
	// 结束下标
	query.setRows(pageSize);

	// 设置高亮参数
	query.setHighlight(true); // 开启高亮组件
	query.addHighlightField("product_name");// 高亮字段
	query.setHighlightSimplePre("<span color='red'>");// 前缀标记
	query.setHighlightSimplePost("</span>");// 后缀标记

	// 请求查询
	QueryResponse response = solr.query(query);

	// 查询结果
	SolrDocumentList docs = response.getResults();
	// 查询文档总数
	System.out.println("查询文档总数" + docs.getNumFound());

	for (SolrDocument doc : docs) {
		// 商品主键
		String id = (String) doc.getFieldValue("id");
		// 商品名称
		String product_name = (String) doc.getFieldValue("product_name");
		// 商品价格
		Float product_price = (Float) doc.getFieldValue("product_price");
		// 商品图片
		String product_picture = (String) doc
				.getFieldValue("product_picture");
		// 商品分类
		String product_catalog_name = (String) doc
				.getFieldValue("product_catalog_name");

		System.out.println("=============================");
		System.out.println("id=" + id);
		System.out.println("product_name=" + product_name);
		System.out.println("product_price=" + product_price);
		System.out.println("product_picture=" + product_picture);
		System.out.println("product_catalog_name=" + product_catalog_name);

		// 高亮信息
		if (response.getHighlighting() != null) {
			if (response.getHighlighting().get(id) != null) {
				Map<String, List<String>> map = response.getHighlighting()
						.get(id);// 取出高亮片段

				if (map.get("product_name") != null) {

					for (String s : map.get("product_name")) {
						System.out.println(s);
					}
				}
			}
		}
	}
}

一些Solr案例

解决首页刷选属性索引检索的问题(solr)

从后台抽取数据到solr服务器

在tomcat上solr服务器的搭建(5.2.0)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值