1. 程式人生 > >solr極速搜尋

solr極速搜尋

一 。solr簡介

solr是以lucene為核心開發的企業級搜尋應用  應用程式可以通過http請求方式來提交索引,查詢索引,提供了比lucene更豐富的查詢語言,是

一個高效能,高可用環境全文搜尋引擎

二 。solr安裝配置

 1》下載solr安裝包  solr所有版本 (http://archive.apache.org/dist/lucene/solr/)  這裡下載 solr-5.5.5
       
 2》安裝 解壓將solr-5.5.5\server\solr-webapp下的webapp 拷貝到tomcat\webapps目錄下 改名為solr 啟動tomcat

   直接訪問 出現404  找到tomcat/logs/localhost.2017-08-17.log 日誌  出現以下異常
    java.lang.NoClassDefFoundError: Failed to initialize Apache Solr: Could not find necessary SLF4j logging jars. 
    If using Jetty, the SLF4j logging jars need to go in the jetty lib/ext directory. For other containers, 
    the corresponding directory should be used. For more information, see:
http://wiki.apache.org/solr/SolrLogging at org.apache.solr.servlet.CheckLoggingConfiguration.check(CheckLoggingConfiguration.java:27) at org.apache.solr.servlet.BaseSolrFilter.<clinit>(BaseSolrFilter.java:30)

可用看到缺少SLF4j包 應該去 應該去 解壓包 /server/lib/ext下找到並拷貝到 tomcat/solr/lib目錄下 然後重啟

繼續訪問 出現以下錯誤 
java.lang.NoSuchMethodError: javax.servlet.ServletInputStream.isFinished()Z
	org.apache.solr.servlet.SolrDispatchFilter.consumeInputFully(SolrDispatchFilter.java:284)
	org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:274)
	org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:208)
    明顯是Servlet版本不一致  tomcat6不支援solr5.54 加大tomcat版本 tomcat7也不支援 換成tomcat8  啟動後訪問 依然錯誤:

org.apache.solr.common.SolrException: Error processing the request. CoreContainer is either not initialized or shutting down.
	org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:217)
	org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:208)

因為需要配置solrhome和solrhome的配置環境

3》配置solrhome

 找到 tomcat\solr\WEB-INF\web.xml 編輯  找到以下這段(配置solrhome)  去掉註釋 將第二個引數配置為本地任意一個目錄即可 
    <env-entry>
       <env-entry-name>solr/home</env-entry-name>
       <env-entry-value>D:\learn\solr-5.5.4\home</env-entry-value>
       <env-entry-type>java.lang.String</env-entry-type>
    </env-entry>

找到solr解壓包/server/solr目錄拷貝所有檔案到 以上web.xml指定的路徑
D:\learn\solr-5.5.5\home下 重啟tomcat 訪問

http://localhost:8080/solor/index.html 或者 http://localhost:8080/solr/admin.html

pom檔案

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>cn.ps</groupId>
	<artifactId>Solr</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency> <!-- 分詞器,附帶引入下面三個jar,版本為4.7.2不支援中文分詞,此處需要5.5.5故需單獨引入下列包-->
			<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>
	</dependencies>
	
</project>

4》修改原始碼,因為ik 2012年停止更新,僅支援4.7,此處需要5.5.5版本,故需修改原始碼,同包,同類,同方法,會覆蓋,呼叫時優先呼叫專案自己定義的

新建包與jar包該類一致的名字,並拷貝這兩個類
在這裡插入圖片描述

修改IKAnalyzer類此方法

  @Override
  protected TokenStreamComponents createComponents(String fieldName, final Reader in) {
    Tokenizer _IKTokenizer = new IKTokenizer(in, this.useSmart());
    return new TokenStreamComponents(_IKTokenizer);
  }

修改為下圖方法內容

  @Override
protected TokenStreamComponents createComponents(String fieldName) {
    Tokenizer _IKTokenizer = new IKTokenizer( this.useSmart());
    return new TokenStreamComponents(_IKTokenizer);
 }

修改IKTokenizer

 //修改前
  public IKTokenizer(Reader in, boolean useSmart) {
    super(in);
    offsetAtt = addAttribute(OffsetAttribute.class);
    termAtt = addAttribute(CharTermAttribute.class);
    typeAtt = addAttribute(TypeAttribute.class);
    _IKImplement = new IKSegmenter(input, useSmart);
  }

 //修改後
 public IKTokenizer(boolean useSmart) {
    offsetAtt = addAttribute(OffsetAttribute.class);
    termAtt = addAttribute(CharTermAttribute.class);
    typeAtt = addAttribute(TypeAttribute.class);
    _IKImplement = new IKSegmenter(input, useSmart);
  }

將這兩個的class檔案替換到jar包中

在這裡插入圖片描述

用壓縮工具開啟jar包ikanalyzer-2012_u6.jar

路徑:ikanalyzer-2012_u6.jar\org\wltea\analyzer\lucene

在這裡插入圖片描述
替換這兩個檔案即可
在這裡插入圖片描述
點選Add core後 成功後 檢查 mycore目錄 發現多了 core.properties和data兩個資源
在這裡插入圖片描述

登陸solr管理網站發現 列表中多了mycore
在這裡插入圖片描述

5 》配置檔案理解

core/conf目錄下的兩個配置檔案非常重要

managed-schema 主要用於配置 可以提交到該core的所有field定義,field的型別定義,唯一識別符號等

常用配置如下:
    定義欄位 _version_ 型別為long  indexed="true" 會進行分詞索引  stored="true"表示儲存到磁碟
    <field name="_version_" type="long" indexed="true" stored="true"/>
    定義欄位 id required="true" 表示所有的document必須新增id欄位 multiValued="false" 表示是否是多值欄位
    <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> 
    定義動態欄位 所以_i結尾的欄位都可以寫入到當前的core
    <dynamicField name="*_i"  type="int"    indexed="true"  stored="true"/>
    定義唯一識別符號的欄位
    <uniqueKey>id</uniqueKey>
    定義欄位型別的別名
    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />
      solrconfig.xml 主要用於配置solor的主要配置資訊 比如lucene版本 快取 資料目錄 請求路徑對映 等 

表示lucene版本
<luceneMatchVersion>5.5.5</luceneMatchVersion>
表示資料目錄 預設是data目錄
<dataDir>${solr.data.dir:}</dataDir> 

自動提交配置

    <autoCommit> 
           當超過15000ms後自動提交所有資料
           <maxTime>${solr.autoCommit.maxTime:15000}</maxTime> 
           是否馬上就可以查詢到
           <openSearcher>false</openSearcher> 
    </autoCommit>

表示當路徑為 /select時查詢所有的資料

    <requestHandler name="/select" class="solr.SearchHandler">
        <!-- default values for query parameters can be specified, these
             will be overridden by parameters in the request
          -->
         <lst name="defaults">
           <str name="echoParams">explicit</str>
           <int name="rows">10</int>
         </lst>
    </requestHandler>

 嘗試在介面上新增資料和查詢資料

新增資料
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
查詢的引數列表

q表示查詢的條件 欄位名:值的格式 多個條件組合查詢可以使用 欄位:欄位值 && 欄位1:欄位值1 也可以使用大寫的AND或者OR

fq表示filter query 過濾條件 和q是and的關係支援各種邏輯運算子 (參考https://cwiki.apache.org/confluence/display/solr/The+Standard+Query+Parser)

sort表示排序 的欄位 欄位名 asc|desc

start 表示從第幾行開始 rows表示查詢的總行數

fl表示查詢顯示的列 比如只需要查詢 name_s,sex_i 這兩列 使用,隔開

df表示預設的查詢欄位 一般不設定

Raw Query Parameters表示原始查詢欄位 可以使用 start=0&rows=10這種url的方式傳入引數

wt(write type)表示寫入的格式 可以使用json和xml

shards 多核同時搜尋 solrhome拷貝mycore為mycore1 管理平臺新增core 設定引數為 路徑,路徑來設定需要搜尋的核

String shards = “localhost:8080/solr/mycore,localhost:8080/solr/mycore1”;
query.set(“shards”, shards);

其他參考(https://cwiki.apache.org/confluence/display/solr/Common+Query+Parameters)
將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該欄位型別 比如

重啟 或者 cloud環境下重新生成collection 插入資料即可實現中文分詞 通過某些中文關鍵字搜尋

建立配置data-conf.xml

<?xml version="1.0" encoding="UTF8"?>  
<dataConfig>  
  <dataSource name="source1" type="JdbcDataSource" driver="com.mysql.jdbc.Driver" 
 url="jdbc:mysql://192.168.0.250:3306/school" user="root" password="ps123456" batchSize="-1" />  
<document>  													<!-- 自動匯入要查詢表的資料 -->
      <entity name="book" pk="newid"  dataSource="source1"  query="select * from  mytext" > 
      	 <field column="newid" name="id"/>
         <field column="newtitle" name="title_ik"/>  
      </entity>
</document>  
</dataConfig> 

新增到solrconfig.xml,並一同拷貝到mycore1 核的配置目錄

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

拷回去
docker cp ./data-conf.xml my_solr:/opt/solr/server/solr/mycore1/conf
docker cp ./solrconfig.xml my_solr:/opt/solr/server/solr/mycore1/conf

managed-schema 拷出來,新增如下配置,在拷回去

docker cp my_solr:/opt/solr/server/solr/mycore1/conf/managed-schema ./

改完後拷回去
docker cp ./managed-schema my_solr:/opt/solr/server/solr/mycore1/conf/


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

訪問solrweb管理介面 http://ip:
在這裡插入圖片描述
mysql資料
在這裡插入圖片描述
頁面查詢資料
在這裡插入圖片描述

支援資料庫語句,關鍵字必須大寫
在這裡插入圖片描述

java程式碼查詢

控制層

@RestController
public class SolrControll {
	@Autowired
	private SolrTemplate temp;
	
	@GetMapping("/que")
	public List<Entity> news(String keyword) {
		SimpleQuery siq=new SimpleQuery("title_ik:"+keyword);
		System.out.println(keyword+"------------");
		Page<Entity> query=temp.query(siq, Entity.class);
		return query.getContent();
	}
}

pom

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

properties

    spring.data.solr.host=http://192.168.174.131:8983/solr
    server.port=8888

頁面

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>什麼鬼頁面</title>
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.min.js"></script>
	<script type="text/javascript">
		 function  query(){
			$.ajax({
				url:"que",
				dataType:"json",
				type:"get",
				data:"keyword="+$("#keys").val(),
				success:function(r){
					$("#mynews").text(JSON.stringify(r));
				}
			});
		}
	</script>
</head>
<body>
	<div>新聞:<input  id="keys"  type="text"name="keyword" ></div>
	<button onclick="query()">搜尋</button>
	<div id="mynews"> </div>
</body>
</html>