Solr 原理、API 使用

日萌社

人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)


 

搜索引擎:Elasticsearch、Solr、Lucene


Solr的概述

1.Solr的下载:
	官网:http://lucene.apache.org
	历史版本下载网址:http://archive.apache.org/dist/lucene/solr/

2.Solr的安装:
	右键解压到当前文件夹即可,注意:解压的目录中一定不要中文和空格。

Solr的的目录结构

1.我们最需要关注的就是:example目录。其中就有搭建Solr服务的详细案例。
2.启动Solr的jar包:需要使用内置的Jetty服务。Jetty是一个WEB容器。
3.Solr目录:包含全文检索要存储的索引数据以及相关的一些配置文件。
4.solr-webapp和webapps:其实包含的是一样的内容,都是Solr的内置Web应用,我们可以通过Http请求访问该应用,实现对Solr服务的管理和访问
5.start.jar包:web应用需要一个Web容器来启动,而这个jar包会使用一个叫做Jetty的WEB容器(类似与Tomcat),来启动Solr的Web服务。

启动Solr的

第一种方式:码头服务器启动的Solr

步骤:
	1.第一步:进入 \solr-4.10.2\example 目录,该目录下存在“start.jar”用于 Jetty服务器启动Solr
	2.第二步:打开命令行窗口,执行“java –jar start.jar”命令,即可启动Solr服务
	3.第三步:打开浏览器,通过“http://localhost:8983/solr”来访问Solr管理页面。(Jetty服务的默认端口是8983)

第二种方式:Tomcat的服务器启动

步骤:
	1.第一步:部署Web服务。
		  1.将 \solr-4.10.2\example\webapps目录下的“solr.war”拷贝到自己的 \apache-tomcat-8.5.16\webapps目录中。
		  2.两种方式解压“solr.war”:
			第一种解压方式:直接右键解压“solr.war”
			第二种解压方式:运行\apache-tomcat-8.5.16\bin目录下的“startup.bat”,便会自动解压webapps目录中的“solr.war”
		  3.解压完毕后可以删除“solr.war”。
		    注意:如果是使用第二种解压方式启动了“startup.bat”的话,则必须先执行“shutdown.bat”关闭Tomcat之后,才能再删除“solr.war”,
			  否则在删除“solr.war”时,会连解压后的目录也一起删除的

	2.第二步:
		1.将“\资料\solr在tomcat运行需要导入的jar包\classes”文件夹下的“log4j.properties”拷贝到“\apache-tomcat-8.5.16\webapps\solr\WEB-INF”目录下
		2.将“\资料\solr在tomcat运行需要导入的jar包\lib”文件夹下的jar包拷贝到“\apache-tomcat-8.5.16\webapps\solr\WEB-INF\lib”目录下

	3.第三步:
		1.将“\solr-4.10.2\example”目录下的(索引库)“solr”文件夹 拷贝到 不带中文/空格的目录下。比如说拷贝到“E:\solr”(索引库)。
		2.到“\apache-tomcat-8.5.16\bin”目录下,编辑“catalina.bat”文件。
		  在“catalina.bat”文件中的第一行处添加一条配置信息,用于指向我们的索引库及配置目录:set "JAVA_OPTS=-Dsolr.solr.home=E:/solr"

		3.到“\apache-tomcat-8.5.16\webapps\solr\WEB-INF”下 编辑“web.xml”文件,编辑如下:

	4.第四步:
		1.运行\apache-tomcat-8.5.16\bin目录下的“startup.bat”
		2.打开浏览器,访问 http://localhost:8080/solr 进入Solr管理页面

Solr的教学文档

2.1、启动Solr服务的方式
2.1.1、方式一,Jetty服务器启动Solr(了解)
步骤:
1)进入solr-4.10.2/example目录
2)打开命令行,执行java –jar start.jar命令,即可启动Solr服务
3)打开浏览器,通过http://localhost:8983/solr来访问Solr管理页面。(Jetty服务的默认端口是8983)

2.1.2、方式二,Tomcat服务器启动
步骤:
1)部署Web服务,将solr-4.10.2/example/webapps/solr.war复制到自己的tomcat/webapps目录中,并解压,然后删除solr.war文件

2)在Tomcat中加入相关jar包:将“resource\solr在tomcat运行需要导入的jar包\lib”下的jar包复制tomcat/webapps/solr/WEB-INF/lib下。
并且把class/log4j.properties复制到tomcat/webapps/solr/WEB-INF下

3)修改Tomcat配置文件,指向Solr的索引库及配置目录。
注意,这里可以指向solr-4.10.2/example/solr目录,如果想独立出来,也可以将这个solr文件夹复制出来到任意位置(不要出现中文),例如:例如:C:/tmp/solr
		我们这里就把这个文件夹复制出来,独立使用

		进入Tomcat文件夹,用记事本打开:tomcat/bin/catalina.bat文件

		添加一条配置信息,指向我们的索引库及配置目录:set "JAVA_OPTS=-Dsolr.solr.home=C:/tmp/solr"

4)进入tomcat/bin目录,双击 startup.bat文件启动服务器

5)打开浏览器,访问 http://localhost:8080/solr 进入Solr管理页面


第一种启动方式:java -jar start.jar


Solr的管理页面

 

面板(仪表盘)

 

日志(日志)

 

核心管理员(核心管理)

在Solr中,每一个Core,代表一个索引库,里面包含索引数据及其配置信息。 Solr中可以拥有多个Core,也就同时管理多个索引库!就像在MySQL中可以有多个database一样!

 

默认核心的目录

 

JavaProperties和ThreadDump

 


管理索引库的控制台

 


CoreSelector(核心选择器)


核心的配置文件详解

1.Core的配置文件详解:
	1.core.properties
	2.schemal.xml
	3.solrconfig.xml

2.core.properties 的作用:
	Core的属性文件,记录当前core的名称、索引位置、配置文件名称等信息,也可以不写。
	一般要求Core名称跟Core的文件夹名称一致!这里都是collection1,我们可以手动修改这个属性,把Core的名字改成我们喜欢的。


添加多个核心

 

1.在solr的目录下创建新的文件夹的Core2,作为新的核心目录

2)在核2下创建的conf目录和数据目录,并且创建文件core.properties,添加属性:名称= core2的

3)从核心-1 / CONF目录下复制配置文件的Core2 / CONF /下  

4)重启的Tomcat,访问管理页面

 



schema.xml中配置详解

<?xml version="1.0" encoding="UTF-8" ?>
<schema name="example" version="1.5">
 
	<!-- "_version_" 和 "_root_" 不能删--> 
	<field name="_version_" type="long" indexed="true" stored="true"/>
	<field name="_root_" type="string" indexed="true" stored="false"/>

   	<!-- 唯一键id:必须是 type="string"。
		indexed="true" 创建索引。stored="true" 存储。multiValued="false" 该字段不能有多个值。 -->   
   	<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> 
        
  	<field name="age" type="long" indexed="true" stored="true"/>
   	<field name="name" type="string" indexed="true" stored="true"/>

	<!--  使用IK分词器(中文分词器):type="text_ik" 关联  <fieldType name="text_ik" >--> 
   	<field name="title" type="text_ik" indexed="true" stored="true"/>
 
   	<!--"text"字段是solrconfig.xml中默认定义的默认搜索字段,由solrconfig.xml中的这一句话来定义:<str name="df">text</str>。
	    如果删除不使用"text"字段的话,那么也必须修改solrconfig.xml的默认搜索字段。 -->
   	<field name="text" type="text_ik" indexed="true" stored="true" multiValued="true"/>

   	<!-- 当新插入的字段名 并没有在schema.xml所定义的话,但只要符合以下规则,照样可以保存该字段名和字段值数据:
		 新插入字段名的末尾字符 符合“<dynamicField name=“*_s”>规定的”后缀名/末尾字符 为“_s”的话,
		 那么就能动态插入该字段名和字段值数据。 -->    
   	<dynamicField name="*_s"  type="string"  indexed="true"  stored="true" />
   
	<!-- 唯一主键 --> 
 	<uniqueKey>id</uniqueKey>

	<!--1.<copyField source=“普通字段名” dest=“复制域字段名text”>:表示把普通字段名 关联到 复制域字段“text”中。
	    2.此处表示把"title"字段 和 "name"字段 关联到"text"字段,那么当查询时,默认把 "title"字段的值 和 "name"字段的值 
	      赋值给"text"字段。
	    3.当不指定查询字段时,默认查询"text"字段,也即相当于查询"text"字段所关联的 "title"字段的值 和 "name"字段的值 -->
   	<copyField source="title" dest="text"/>
   	<copyField source="name" dest="text"/>
  
    	<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
    	<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/> 

	<!-- 定义了IK中文分词器,那么只要有字段中使用type="text_ik" 关联  <fieldType name="text_ik" >,那么该字段既可以进行中文分词 --> 
	<fieldType name="text_ik" class="solr.TextField">
		<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
	 </fieldType>
</schema>


Solr中会提前对文档中的字段进行定义,并且在schema.xml中对这些字段的属性进行约束,
例如:字段数据类型、字段是否索引、是否存储、是否分词等等。

1.通过Field字段定义字段的属性信息:

	1.属性及含义:
		name:字段名称,最好以下划线或者字母开头
		type:字段类型,指向的是本文件中的<fieldType>标签
		indexed:是否创建索引
		stored:是否被存储
		multiValued:是否可以有多个值,如果字段可以有多个值,设置为true

	2.注意:在本文件中,有两个字段是Solr自带的字段,绝对不要删除:_version_节点和_root_节点

2)通过FieldType指定数据类型

		1.<fieldType name="" class="">
			1.name:字段类型的名称,可以是系统定义的数据类型,也可以是自定义的类型。
				<field type="">标签的type属性则负责引用<fieldType name="">中的name值,用于来指定数据类型或自定义的类型。
			2.class:字段类型在Solr中的类。
				  class="solr.StrField":字段自动创建索引,但不会进行分词。
				  class="solr.TextField":字段自动创建索引,并且自动进行分词,因此必须指定分词器,比如中文分词器(IK分词器)。
 
		2.<analyzer>:在<fieldType>标签体中 使用 <analyzer>子标签 用来指定分词器,比如中文分词器(IK分词器)。
 
3)唯一主键
	Lucene中本来是没有主键的。删除和修改都需要根据词条进行匹配。
	而Solr却可以设置一个字段为唯一主键,这样删改操作都可以根据主键来进行!

4)动态字段



Solr的中的修改:本质是先删除,再插入新的数据


动态域(动态产生域):动态插入字段名和字段值

动态插入字段名和字段值的规则:
	只要插入字段名的末尾字符 符合“<dynamicField name=“*_s”>规定的”后缀名/末尾字符为_s的话,
	那么就能动态插入字段名和字段值。


复制域:“文本”字段

复制域的用法:
	1.首先在schema.xml中配置把其他字段关联到“text”字段。
	2.上图分别有两个普通字段<field name=“字段名name”>、<field name=“字段名title”>,	
	  和 一个复制域字段<field name=“复制域字段名text”>;
	  使用<copyField source=“普通字段名” dest=“复制域字段名text”>:表示把普通字段名 关联到 复制域字段“text”中。
	3.作用:
		1.普通字段名 关联到 复制域字段“text”之后,便能自动把所关联的普通字段的值 赋值给 复制域字段“text”中。
		2.在查询时不指定要查询的具体字段的话,默认使用复制域字段“text”来作为查询字段,
		  因为在\solr\collection1\conf\solrconfig.xml中配置了<str name="df">text</str>。
		  因为会自动把所关联的普通字段的值 赋值给 复制域字段“text”,所以当默认使用复制域字段“text”来作为查询字段进行查询时,
		  相当于查询复制域字段“text”所关联的普通字段的值。

在插入数据时无需给“text”字段插入数据,而在查询时,自动把“title”和“name”的数据作为“text”字段的数据。
因为schema.xml中配置了“text”字段指定关联了“title”和“name”字段。

 


IK分词器(中文分词器)

1.引入IK分词器的jar包
		<!-- 引入IK分词器 -->
		<dependency>
			<groupId>com.janeluo</groupId>
			<artifactId>ikanalyzer</artifactId>
			<version>2012_u6</version>
		</dependency>

2.下面三个配置文件 拷贝到 Tomcat根目录下的\webapps\solr\WEB-INF\classes 文件中

3.在schemal.xml中自定义fieldType,引入IK分词器

 	<fieldType name="text_ik" class="solr.TextField">
		<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
	</fieldType>

4.让字段使用我们的自定义数据类型,引入IK分词器

5.可以正确分词了:


自定义字段的数据类型:定义有IK分词器(中文分词器)

<field type="text_ik">标签的type属性则负责引用<fieldType name="text_ik">中的name值,用于来指定数据类型或自定义的类型。
该字段使用到“带有IK分词器的”字段类型,那么该字段“title”就能分词了。
如果字段不使用“带有IK分词器的”字段类型,而使用string类型声明(type=string)的话,是无法中文分词的。


solrconfig.xml中

这个配置文件主要配置跟索引库和请求处理相关的配置。
solr服务的优化主要通过这个配置文件进行。

<LIB />标签

1.用途:配置插件依赖的jar包
2.注意事项:
	如果引入多个jar包,要注意包和包的依赖关系,被依赖的包配置在前面
	这里的jar包目录如果是相对路径,那么是相对于core所在目录。

3.例如 在配置文件中默认有以下配置:这些是Solr中插件所依赖的Jar包

4.这里的相对路径其实是相对于 core所在目录。
  我们把所引来的Jar包复制到solr的HOME中:

  然后修改配置文件:

  效果:


处理日志中的警告信息

该警告信息:表示索引库目录(E:\solr\collection1\conf)下找不到contrib和dist文件夹。
解决:
	1.第一步:把“\solr-4.10.2”目录下的contrib和dist文件夹 拷贝到 索引库目录(E:\solr\collection1\conf)下即可。
	2.第二步:修改“E:\solr\collection1\conf”下的solrconfig.xml文件:将“../../../”修改为“../”。

索引库目录:E:\ Solr的\ collection1 \的conf目录下的solrconfig.xml中

修改“E:\ Solr的\ collection1 \的conf”下的solrconfig.xml中文件:将“../../../”修改为“../”

最终修改为“../”

1.到\apache-tomcat-8.5.16\bin目录下,先执行“shutdown.bat”停止Tomcat,再执行“startup.bat”启动Tomcat
2.打开浏览器,访问 http://localhost:8080/solr 进入Solr管理页面


<requestHandler />标签

1.用途:配置Solr处理各种请求(搜索/select、更新索引/update、等)的各种参数
2.主要参数:
	name:请求类型,例如:select、query、get、update
	class:处理请求的类
	initParams:可选。引用<initParams>标签中的配置
	<lst name="defaults">:定义各种缺省的配置,比如缺省的parser、缺省返回条数

3.例子:负责搜索请求的Handler

	1.<int name="rows">10</int>:
		不进行分页查询的话,默认只查询出10条数据

	2.<str name="df">text</str>:
		1.在查询时不指定要查询的具体字段的话,默认使用复制域字段“text”来作为查询字段,
		  因为会自动把所关联的普通字段的值 赋值给 复制域字段“text”,所以当默认使用复制域字段“text”来作为查询字段进行查询时,
		  相当于查询复制域字段“text”所关联的普通字段的值。
		2.<str name="df">默认搜索的字段</str> 默认设置为:text。我们可以设置为title:


<initParams在/>标签

1.用途:为一些requestHandlers定义通用的配置,以便在一个地方修改后,所有地方都生效
2.主要参数:
	path:指明该配置应用于哪些请求路径,多个 的话用逗号分开,可以用通配符(*表示一层子路径,**表示无限层)
	name:如果不指定path,可以指定一个name,然后在<requestHander>配置中可以引用这个name
3.例子(配置一个缺省的df): 
	<initParams path="/update/**,/query,/select,/tvrh,/elevate,/spell,/browse">    	
		<lst name="defaults">      
			<str name="df">_text_</str>    
		</lst>  
	</initParams>
  如果配置name,在<requestHander>中引用的例子:<requestHandler name="/dump1" class="DumpRequestHandler"  initParams="myParams"/>

<updateHandler />标签

1.用途:定义一些更新索引相关的参数,比如定义commit的时机
2.主要参数:
	autoCommit:定义自动commit的触发条件。如果没配置这个参数,则每次都必须手动commit
		maxDocs
		maxTime(毫秒)
		penSearcher:autoCommit结束后,是否开启一个新的searcher让更改生效。缺省为false
	autoSoftCommit:定义自动softCommit的触发条件。相关参数同autoCommit
	listener:配置事件监听器
		event:监听哪个事件,比如:event="postCommit", event="postOptimize"
		class:处理的类,可以是自己的实现类。如果是RunExecutableListener,可以配置下面的参数:
			exe:可执行文件,包括Solr Home的相对路径和文件名
			dir:工作目录,缺省是“.”
			wait: 调用者是否等待可执行文件执行结束,缺省是true
			args:传递给可执行文件的参数
			env:其他所需要的环境变量
	updateLog:配置log的保存路径、等
		dir:保存路径
		numRecordsToKeep:一个log保存的记录数,缺省为100
		maxNumLogsToKeep:log的数量,缺省为10
		numversionBuckets:追踪max version的bucket数量(?),缺省为65535

	配置这些参数要考虑到搜索的准确度和性能的平衡。^_^
	注:commit和softCommit:
		commit:正式提交、对索引的修改会被保存到永久存储中(比如磁盘),会比较耗时
		softCommit:软提交,对索引的修改会被立即应用到工作中的索引中,即立即生效,但没有保存进磁盘

<查询/>标签

1.用途:配置Solr如何处理和返回搜索的相关参数
2.主要参数:
	filterCache:当搜索带有“fq”参数时,使用这个配置,它保存未经过排序的所有文档
		class:实现类,有三种:solr.search.LRUCache, solr.search.FastLRUCache, solr.search.LFUCache
		size:最大保存的记录数量
		initialSize:初始数量
		autowarmCount:新Index Searcher启动的时候从旧的Index Searcher缓存拷贝过来的数据量
	queryResultCache:存储最终的搜索结果(排序后的、有范围的文档id)
		class:实现类,有三种:solr.search.LRUCache, solr.search.FastLRUCache, solr.search.LFUCache
		size:最大保存的记录数量
		initialSize:初始数量
		autowarmCount:新Index Searcher启动的时候从旧的Index Searcher缓存拷贝过来的数据量
		maxRamMB:最大分配的容量(兆)
	documentCache:缓存Lucene Document对象(就是每个文档的fields)
		class:实现类,有三种:solr.search.LRUCache, solr.search.FastLRUCache, solr.search.LFUCache
		size:最大保存的记录数量
		initialSize:初始数量
		autowarmCount:因为Lucene的内部文档 id 是临时的,所以这个缓存不应该被auto-warm,这个值应该为“0”
	cache:配置自定义的缓存,通过SolrIndexSearcher类的getCache()方法和name参数调用这个缓存
		name:被调用时的标识
		其他参数同上
	maxBooleanClauses:BooleanQuery的最大子句数量
	enableLazyFieldLoading:没有知道被请求的field是否懒加载,true/false
	useFilterForSortedQuery:如果不是按照score排序,是否从filterCache中获取数据
	queryResultWindowsize:配合queryResultCache使用,缓存一个超集。如果搜索请求第10到19条记录,而这个参数是50,那么会缓存0到49条记录
	queryResultMaxDocsCached:queryResultCache缓存的最大文档数量
	useColdSearcher:但一个新searcher正在warm-up的时候,新请求是使用旧是searcher(true)还是等待新的search(false)
	maxWarmingSearchers:定义同时在warn-up的searcher的最大数量
	listener:监听一些事件并指定处理的类,比如在solr启动时加载一些数据到缓存中,相关参数:
		event:被监听的事件,比如:firstSearcher是第一个searcher启动、也就是solr启动的事件,newSearcher是当已经有searcher在运行的时候有新searcher启动的事件
		class:处理类
		name:="queries"就是需要处理的是query
		lst, name:针对哪些搜索条件需要处理

<RequestDispatcher的/>标签

1.用途:控制Solr HTTP RequestDispatche r响应请求的方式,比如:是否处理/select url、是否支持对流的处理、
	上传文件的大小、如何处理带有cache头的HTTP请求、等等
2.主要参数:
	handleSelect:true/false,如果是false,则由requestHandler来处理/select请求。因为现在的requestHandler中/select是标配,所以这里应该填false
	requestParsers:
		enableRemoteStreaming:是否接受流格式的内容,缺省为ture
		multipartUploadLimitInKB:multi-part POST请求,上传文件的大小上限(K)
		formdataUploadLimitInKB:HTTP POST的form data大小上限(K)
		addHttpRequestToContext:原始的HttpServletRequest对象是否应该被包含在SolrQueryRequest的httpRequest中……一般自定义的插件使用这个参数……
	httpCaching:如何处理带有cache control头的HTTP请求
		nerver304:如果设为true(开发阶段),则就算所请求的内容没被修改,也不会返回304,并且下面两个参数会失效
		lastModFrom:最后修改时间的计算方式,openTime:Searcher启动的时刻;dirLastMod:索引更新的时刻
		etagSeed:HTTP返回的ETag头内容
		cacheControl:HTTP返回的Cache-Control头内容

<updateProcessor />和<updateProcessorChain />标签

1.用途:配置处理update请求的处理器、处理器链。如果不配置的话,Solr会使用缺省的三个处理器:
	LogUpdateProcessorFactory:追踪和记录日志
	DistributedUpdateProcessorFactory:分流update请求到不同的node,比如SolrCloud的情况下把请求分配给一个shard的leader,然后把更新应用到所有replica中
	RunUpdateProcessorFactory:调用Solr的内部API执行update操作
2.如果需要自定义update处理器:
	updateProcessor:
		class:负责处理的类
		name:名字,给updateProcessorChain引用是使用
	updateProcessorChain:
		name:自己的名字标记
		processor:指定updateProcessor的name,多个的话用逗号“,”分开

SolrJ的使用(用于操作的Solr)

pom.xml中添加依赖:
	<dependencies>
		<!-- Junit单元测试 -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<dependency>
			<groupId>org.apache.solr</groupId>
			<artifactId>solr-solrj</artifactId>
			<version>4.10.2</version>
		</dependency>
		<!-- Solr底层会使用到slf4j日志系统 -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.22</version>
		</dependency>
		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.2</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<!-- java编译插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.2</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>
1.添加数据到solr中的某个core(数据库)中
	//当前处于java程序,solr core交由tomcat启动的solr服务器管理
	//solr对外提供接口,用户通过http请求调用接口,进行数据的CRUD
	@Test
	public void addDateToSolr() throws SolrServerException, IOException
	{
		// URL为http://localhost:8080/solr项目名/core的名字
		String url = "http://localhost:8080/solr/core2";
		//solrj连接对象:连接到solr中的某个core(数据库)中,然后可以往该core(数据库)中对数据进行增删查改
		HttpSolrServer server = new HttpSolrServer(url);

		//数据封装对象: SolrInputDocument
		SolrInputDocument document = new SolrInputDocument();
		// 新增数据:SolrInputDocument数据封装对象 提供了addField("字段名称", "字段值")设置数据
		document.addField("id", 2);
		document.addField("name", "solr");
		document.addField("age", 27L);
		document.addField("title", "solr是独立的企业级搜索服务器");

		//第一种保存方式:单个SolrInputDocument 插入保存
		//server.add(document);
		//第二种保存方式:批量多个SolrInputDocument 插入保存
		List<SolrInputDocument> list = new ArrayList<SolrInputDocument>();
		list.add(document);
		//批量添加数据
		server.add(list);
		//提交数据
		server.commit();
	}

2.使用javaBean向solr中的某个core(数据库)中添加数据
	//使用注解:先定义JavaBean对象中的字段 和 core(数据库)中的字段名 相关联
	public class User 
	{
		//@Field("core中的字段名"):使用 @Field注解显示声明javaBean中属性所对应的solr中的core(数据库)中的字段名
		@Field("id")
		private String id;
		@Field("name")
		private String name;
		@Field("title")
		private String title;
		@Field("age")
		private Long age;
	}

	@Test
	public void addJavaBeanToSolrCore() throws IOException, SolrServerException
	{
		// URL为http://localhost:8080/solr项目名/core的名字
		String url = "http://localhost:8080/solr/core2";
		//solrj连接对象:连接到solr中的某个core(数据库)中,然后可以往该core(数据库)中对数据进行增删查改
		HttpSolrServer server = new HttpSolrServer(url);
		//同时新增多条数据,批量多条数据插入保存
		List<User> list = new ArrayList<User>();
		for(int i = 3;i<30;i++)
		{
			User user = new User();
			user.setId(""+i);
			user.setName("程序员"+i+"号");
			user.setAge(Long.valueOf(""+i));
			user.setTitle("机智聪明勤奋工程师"+i);
			list.add(user);
		}
		
		//第一种保存方式:直接插入保存单个javaBean对象,添加单条数据
		//server.addBean(user);
	
		//第二种保存方式:批量插入保存多个javaBean对象,添加多条数据
		server.addBeans(list);
		//提交
		server.commit();
		
	}


3.修改/更新solr中的某个core(数据库)中的数据
	//solr中并没有更新数据的方法,没有更新这个概念。
	//通过唯一字段来判断:schema.xml中定义了uniqueKey,uniqueKey就是唯一字段。
	//如果新增数据的唯一键已经存在,新增时会直接全覆盖,即存在的话便便先删除原来的数据再增加新的数据。
	//如果新增数据时唯一键不存在,直接新增。
 
	@Test
	public void updateSolrCore() throws IOException, SolrServerException
	{
		// URL为http://localhost:8080/solr项目名/core的名字
		String url = "http://localhost:8080/solr/core2";
		//solrj连接对象:连接到solr中的某个core(数据库)中,然后可以往该core(数据库)中对数据进行增删查改
		HttpSolrServer server = new HttpSolrServer(url);
			
		//使用JavaBean对象封装数据
		User user = new User();
		user.setId("7");
		user.setName("典韦");
		user.setTitle("勇战士典韦");

		//直接插入保存单个javaBean对象,添加单条数据
		server.addBean(user);
		server.commit();
	}

4.删除solr中的某个core(数据库)中的数据

	//根据id删除对应的数据
	@Test
	public void deleteById() throws SolrServerException, IOException
	{
		// URL为http://localhost:8080/solr项目名/core的名字
		String url = "http://localhost:8080/solr/core2";
		//solrj连接对象:连接到solr中的某个core(数据库)中,然后可以往该core(数据库)中对数据进行增删查改
		HttpSolrServer server = new HttpSolrServer(url);
		//根据id删除对应的数据
		server.deleteById("2");
		server.commit();
	}

	//根据 集合中保存的多个id 同时删除多条数据
	@Test
	public void deleteByIds() throws SolrServerException, IOException
	{
		// URL为http://localhost:8080/solr项目名/core的名字
		String url = "http://localhost:8080/solr/core2";
		//solrj连接对象:连接到solr中的某个core(数据库)中,然后可以往该core(数据库)中对数据进行增删查改
		HttpSolrServer server = new HttpSolrServer(url);
		//根据id删除对应的数据
		List<String> ids = new ArrayList<String>();
		ids.add("1");
		ids.add("3");
		//根据 集合中保存的多个id 同时删除多条数据
		server.deleteById(ids);
		server.commit();
	}
	
	//根据查询条件删除
	@Test
	public void deleteByQuery() throws SolrServerException, IOException
	{
		// URL为http://localhost:8080/solr项目名/core的名字
		String url = "http://localhost:8080/solr/core2";
		//solrj连接对象:连接到solr中的某个core(数据库)中,然后可以往该core(数据库)中对数据进行增删查改
		HttpSolrServer server = new HttpSolrServer(url);
		//查询条件的格式:"*:*"。会删除所有数据,能够成功执行。安全越界,慎用。
		String query = "*:*"; 
		//String query = "title:聪明"; //查询条件的格式:“字段名:字段值”
		//deleteByQuery(查询条件):根据指定的查询条件删除所有匹配的结果
		server.deleteByQuery(query);
		server.commit();
	}


5.查询solr中的某个core(数据库)中的数据

	\solr\collection1\conf\solrconfig.xml中配置了如下信息:
	<lst name="defaults">
       		<str name="echoParams">explicit</str>
       		<int name="rows">10</int>//不进行分页查询的话,默认只查询出10条数据
       		<str name="df">text</str>//不写指定查询的字段名的话,则默认查询text字段的字段值数据,即查询符合该“text字段名=字段值”的数据
     	</lst>

 
	//
	@Test
	public void searchSolrCore() throws SolrServerException
	{
		// URL为http://localhost:8080/solr项目名/core的名字
		String url = "http://localhost:8080/solr/core2";
		//solrj连接对象:连接到solr中的某个core(数据库)中,然后可以往该core(数据库)中对数据进行增删查改
		HttpSolrServer server = new HttpSolrServer(url);

 		//-----------------------------------------

		//1.new SolrQuery("*:*"):查询该core(数据库)中的所有
		//2.new SolrQuery("字段名:字段值"):指定查询符合该“字段名=字段值”的数据
		//3.new SolrQuery("字段值"):不写指定查询的字段名的话,则默认查询text字段的字段值数据,即查询符合该“text字段名=字段值”的数据。
		SolrQuery query = new SolrQuery("*:*");
 
		//4.new SolrQuery("字段名:字段值?"):表示匹配出现的位置
		//5.new SolrQuery("字段名:字段值*"):表示匹配任意字符
		SolrQuery query = new SolrQuery("title:互*");
 
		//布尔搜索:AND、OR和NOT布尔操作(推荐使用大写,区分普通字段)
		//例子:new SolrQuery("字段名:字段值 OR 字段名:字段值")。
		//使用OR表示:表示并集,符合任意一个"字段名:字段值"的数据 都能查询出来
		//使用AND表示:表示交集,符合两方的"字段名:字段值"的数据 才能查询出来
 		SolrQuery query = new SolrQuery("title:solr OR title:iphone");

		//子表达式查询:(字段名:字段值 OR 字段名:字段值) OR (字段名:字段值)
 		SolrQuery query = new SolrQuery("(title:solr OR title:聪明) OR (title:iphone)");

		//相似度搜索:使用“~”字符,表示最大允许编辑次数为2次
		//core数据库中存储的是“iphone”,那么输入要搜索的"iphon~q",编辑两次后,仍然可以得到“iphone” 
 		SolrQuery query = new SolrQuery("iphon~q");

		//数字范围搜索,包含起始值和结束值:"字段名:[字段值 TO 字段值]"。
		//[字段值 TO 字段值]:表示包含两边字段值
		//{字段值 TO 字段值}:表示不包含两边字段值
		SolrQuery query = new SolrQuery("age:[1 TO 5]");
 
		//-----------------------------------------

		//根据id字段倒叙排列
		query.setSort("id", ORDER.desc);

		//-----------------------------------------

		//执行查询,获取出查询结果集
		QueryResponse response = server.query(query);

		//---------------- 解析查询结果集的方式一 -------------------------
 
		SolrDocumentList list = response.getResults(); 

		//默认只查询出10条数据:因为\solr\collection1\conf\solrconfig.xml中配置了<int name="rows">10</int>
		//不进行分页查询的话,默认只查询出10条数据
		for(SolrDocument sd : list)
		{
			System.out.println("id===="+sd.get("id"));
			System.out.println("name===="+sd.get("name"));
			System.out.println("title===="+sd.get("title"));
			System.out.println("===========next===========");
		}

		//---------------- 解析查询结果集的方式二 -------------------------
 
		//解析搜索结果集的方式二:
		//	直接返回javaBean的方式。
		//	JavaBean类中的字段上必须定义有@Field("core中的字段名")
		List<User> list = response.getBeans(User.class);

		for(User u : list)
		{
			System.out.println(u);
		}
	}
 

6.分页查询:
	\solr\collection1\conf\solrconfig.xml中配置了如下信息:
	<lst name="defaults">
       		<str name="echoParams">explicit</str>
       		<int name="rows">10</int>//不进行分页查询的话,默认只查询出10条数据
       		<str name="df">text</str>//不写指定查询的字段名的话,则默认查询text字段的字段值数据,即查询符合该“text字段名=字段值”的数据
     	</lst>

	//搜索结果集的分页
	//	分页关键:需要页码和每页显示条数
	//	获取结果集时,指定开始位置start和结束位置end
	@Test
	public void searchSolrCorePageList() throws SolrServerException
	{
		// URL为http://localhost:8080/solr项目名/core的名字
		String url = "http://localhost:8080/solr/core2";
		HttpSolrServer server = new HttpSolrServer(url);
 
		Integer page = 2;//页码
		Integer pageSize = 15;//每页显示条数
		Integer start = (page -1 ) * pageSize;//从第几条开始获取
		Integer end = page * pageSize;//获取到第几条结束

		//字段名:参数值
		SolrQuery query = new SolrQuery("title:聪明");
		
		//分页查询:设置从第几条开始获取 和 每页显示条数
		query.setStart(start);//从第几条开始获取
		query.setRows(pageSize);//每页显示条数

		//根据id字段倒叙排列
		query.setSort("id", ORDER.desc);

		//开启高亮显示
		query.setHighlight(true);
		//高亮显示的标签前缀
		query.setHighlightSimplePre("<em color='red'>");
		//高亮显示的标签后缀
		query.setHighlightSimplePost("</em>");
		//添加需要高亮显示的字段
		query.addHighlightField("title");
		query.addHighlightField("name");

		QueryResponse response = server.query(query);

		//解析搜索结果集的方式一:获取高亮显示的结果集
		Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();

		//遍历的方式获取高亮的结果集
		for(String key : highlighting.keySet())
		{
			Map<String, List<String>> map = highlighting.get(key);
			for(String key2 : map.keySet())
			{
				List<String> list = map.get(key2);
				for(String str : list)
				{
					System.out.println(str);
				}
			}
		}
		
		//解析搜索结果集的方式二:
		//	直接返回javaBean的方式。
		//	JavaBean类中的字段上必须定义有@Field("core中的字段名")
		List<User> list = response.getBeans(User.class);
		for(User u : list)
		{
			String highlightTilte = highlighting.get(u.getId()).get("title").get(0);
 			System.out.println(highlightTilte);
			u.setTitle(highlightTilte);
			System.out.println(u);
		}
		
	}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

あずにゃん

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值