solr

一、简介

基于lucene

Solr 主要特性有:强大的全文检索功能,高亮显示检索结果,动态集群,数据库接口和电子文档(Word,PDF等)的处理。而且 Solr 具有高度的可扩展,支持分布搜索和索引的复制

solr wiki :  http://wiki.apache.org/solr/FrontPage

二、jetty简易启动

cd D:\sorl\solr-4.6.0\example

java -jar start.jar  

 

http://127.0.0.1:8983/solr

引用的是D:\sorl\solr-4.6.0\example\webapps\solr.war  如果要改war包比较麻烦,比如加入ik

三、solr+Tomcat部署

1、拷贝出E:\sorl\solr-4.5.1\example\solr 作为sorlhome, E:\sorl\solrhome(改名)

2、将E:\sorl\solr-4.5.1\dist\solr-4.5.1.war拷贝到Tomcat的webapp目录下,启动,解压后改名为solr

3、 配置solrhome为E:/sorl/solrhome

去掉 webapps->solr-> web.xml里env-entry的注释,

<env-entry>

<env-entry-name>solr/home</env-entry-name>

<env-entry-value>E:/sorl/solrhome</env-entry-value>

<env-entry-type>java.lang.String</env-entry-type>

</env-entry>

 

或者tomcat增加 E:\sorl\apache-tomcat-6.0.29\conf\Catalina\localhost\solr.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<Context  docBase="E:/solr/apache-tomcat-6.0.29/webapps/solr" debug="5" crossContext="true" >    
    <Environment name="solr/home" type="java.lang.String" value="E:/solr/solrhome" override="true" />    
</Context>

 或者在server.xml的host中配置context

 

4、启动,发现报错,Error filterstart ,因为 war包中没有配置日志。将solr目录下 example\lib\ext中的jar包“、example\resources中的log4j.properties   copy到tomcat的lib目录下。

 

5 、启动正常后,访问 http://localhost:8080/solr/ 进入主目录。

 

三、中文分词

参考我的    http://thrillerzw.iteye.com/blog/2049172

 

四、solr+eclipse调试环境搭建

1、下载solr-4.5.1-src.tgz,解压

2、ant添加ivy支持:运行ant ivy-bootstrap ,安装ivy后,C:\Users\Administrator\.ant\lib多出ivy-2.3.0.jar,拷贝到apache-ant-1.8.4\lib目录中。

3、cmd进入工程目录,ant eclipse编译为eclipse工程,

4、导入eclipse

5、在源码中新建一个WebContent文件夹,复制 solr-4.5.1-src\solr\webapp\web 下的内容至 WebContent;复制 solr-4.5.1-src \solr\example中的solr文件夹复制到 WebContent中,作为solr/home

6、eclipse marketplace搜索并安装jetty插件run-jetty-run

 

7、run Configurations,右击jetty webapp,新建,配置端口为80等,在Arguments面板中的VM arguments中增加 -Dsolr.solr.home=WebContent/solr

8、运行jetty,浏览器访问http://127.0.0.1/solrsrc

 

五、demo

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.FacetField.Count;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.RangeFacet;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;

public class SolrDemo {
    	//索引
	public static void solrIndex(){
		try {
			String url = "http://localhost:8080/solr";
			HttpSolrServer server = new HttpSolrServer(url);
			SolrInputDocument doc = new SolrInputDocument();
			doc.addField("id", "1");
			doc.addField("name", "马航失联");
			doc.addField("age", 25);
			doc.addField("content", "家人好担心");
			doc.addField("testik", "希望马航顺利回来,家里人真的真的爱你,加油");
			
			SolrInputDocument doc2 = new SolrInputDocument();
			doc2.addField("id", "2");
			doc2.addField("name", "加油马航");
			doc2.addField("age", 30);
			doc2.addField("content", "必须加油2014");
			doc2.addField("testik", "马航加油,大家都在等你们回来");
			
			SolrInputDocument doc3 = new SolrInputDocument();
			doc3.addField("id", "3");
			doc3.addField("name", "软件很累");
			doc3.addField("age", 30);
			doc3.addField("content", "喜欢还好,一天一天");
			doc3.addField("testik", "测试ik,马航加油,thriller加油");
			server.add(doc);
			server.add(doc2);
			server.add(doc3);
			server.commit();
		} catch (SolrServerException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	//查询
	public static void solrSearcher(){
		try {
			String url = "http://localhost:8080/solr";
			HttpSolrServer server = new HttpSolrServer(url);
			/**
			 * 1、在程序中设定的搜索域优先级 > schema.xml文件中配置的默认搜索域
			 * 2、在搜索词前面加入搜索域的优先级 > solrconfig.xml中配置的qf值 > schema.xml文件中配置的默认搜索域
			 * 3、在程序中用setFields函数可以指定显示域,并且该指定方法的优先级 > solrconfing.xml中配置的fl值
			 */
			//AND OR 添加多个
			SolrQuery query = new SolrQuery("testik:加油"); 
			//默认搜索域
			//params.setParam("df", "name");
			
			//显示域
			String[] fields = {"id","name","content","testik","age"};
			query.setFields(fields);
			
			//高亮
			query.addHighlightField("testik");
			query.setHighlight(true);
			query.setHighlightSimplePre("<em class=\"highlight\" >");
			query.setHighlightSimplePost("</em>");
			//显示的字数
			query.setHighlightFragsize(4);
			//排序,可以添加多个。先加入的 优先级高
			query.addSort("age", ORDER.asc);
			query.addSort("id", ORDER.desc);
		
			
			//过滤:包含的留下  达到精确搜索   可添加多个
			String[] fqs = {"testik:加油"};
//			String[] fqs = {"testik:加油","name:加油马航"};
			query.addFilterQuery(fqs);
			
			//分页   起始位置   每页条数   todo:lucene、solr内存溢出问题
			query.setStart(0);
			query.setRows(10);
			
			//facet 
			//FacetField统计的域
			String[] ftf = {"name","age"};
			query.addFacetField(ftf);
			//RangeFacet统计,从1开始,到28结束,每隔10个统计一次。最后一次大于28的也会统计进去。
			query.addNumericRangeFacet("age", 1, 28, 10);
			
			QueryResponse response = server.query(query);
			
			 //"name","age" FacetField统计结果
			 List<FacetField> listField = response.getFacetFields();
			 for(FacetField facetField : listField){
				 System.out.println(facetField.getName());
				 List<Count> counts = facetField.getValues();
				 for(Count c : counts){
					 System.out.println(c.getName()+":"+c.getCount());
				 }
			 }
			//age RangeFacet统计结果
			 List<RangeFacet> listFacet = response.getFacetRanges();
			 for(RangeFacet rf : listFacet){
				 List<RangeFacet.Count> listCounts = rf.getCounts();
				 for(RangeFacet.Count count : listCounts){
					 System.out.println("RangeFacet:"+count.getValue()+":"+count.getCount());
				 }
			 }
			
			SolrDocumentList list = response.getResults();
			//第一个map key:document.getFieldValue("id")文档id值    第二个map key:高亮的域名 
			 Map<String,Map<String,List<String>>> map = response.getHighlighting();
			System.out.println("total hits:"+list.getNumFound());
			for(SolrDocument doc : list){
				System.out.println("id:"+doc.getFieldValue("id"));
				System.out.println("name:"+doc.getFieldValue("name"));
				System.out.println("content:"+doc.get("content"));
				System.out.println("age:"+doc.getFieldValue("age"));
				System.out.println("testik:"+doc.get("testik"));
				System.out.println("hl:"+map.get(doc.getFieldValue("id")).get("testik").get(0));
				//修改doc方法 document.setField(高亮域, 高亮的值);
				doc.setField("testik", map.get(doc.getFieldValue("id")).get("testik").get(0));
				System.out.println("hl testik:"+doc.get("testik"));
				System.out.println();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	//删除
	public static void solrDelIndex(){
		try {
			String url = "http://localhost:8080/solr";
			HttpSolrServer server = new HttpSolrServer(url);
			server.deleteById("1");
			server.commit();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

  5.2、

       索引前,准备数据,把action字段为delete的索引、数据库记录都删除,把action字段为update的索引删除,action字段改为add重新索引。

索引后,更新数据库flag字段,索引时间字段。

 

 六、配置文件

      schema.xml 

 

id类型:
//multiValued="true" 为多个域时候使用,跟复制域<copyField source="name" dest="name_content" /> 配合使用
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> 
<field name="pname" type="text_chinese" indexed="true"  stored="true" />

//sortMissingLast=”true”:没有该field的数据排在有该field的数据之后,而不管请求时的排序规则。
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
//动态域 以备扩展之用。在索引文档时,一个字段如果在常规字段中没有匹配时,将到动态字段中匹配。
<dynamicField name="*_i"  type="int"    indexed="true"  stored="true"/>
<dynamicField name="*_is" type="int"    indexed="true"  stored="true"  multiValued="true"/>

//中文分词,ik
   <fieldType name="text_chinese" class="solr.TextField" positionIncrementGap="100">

      <analyzer type="index">

        <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" dicPath="ext.dic"/>

        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />

        <!-- in this example, we will only use synonyms at query time

        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>

        -->
        <filter class="solr.LowerCaseFilterFactory"/>

      </analyzer>

      <analyzer type="query">

        <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory"/>

        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />

        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>

        <filter class="solr.LowerCaseFilterFactory"/>

      </analyzer>

    </fieldType>

      

一个analyzer chain中必须且只能包含一个tokenizer。tokenizer的作用是将输入的text stream (字符串,即field中存储的值)分解若干token。而filter的输入是token流,产出也是token流,因此多个filter可以组成一个filter chain。filter主要针对输入的token流进行处理,如做stem,去除stopwords等。solr本身已经提供了大量的tokenizer和filter,同时这种机制也让我们可以方便的进行定制。

solr中默认包含的analyzer,tokenizer,filter:  http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters

如果没有指定analyzer的type,则表明index与query阶段用的是同样的analyzer。

 

 

七、HttpSolrServer初始化

SysConsts.SOLR_SERVER = new HttpSolrServer(SysConsts.SOLR_URL);
SysConsts.SOLR_SERVER.setSoTimeout(SysConsts.SOLR_TIME_OUT); // socket read timeout
SysConsts.SOLR_SERVER.setConnectionTimeout(SysConsts.SOLR_TIME_OUT);
SysConsts.SOLR_SERVER.setDefaultMaxConnectionsPerHost(100);
SysConsts.SOLR_SERVER.setMaxTotalConnections(100);
SysConsts.SOLR_SERVER.setFollowRedirects(false); // defaults to
SysConsts.SOLR_SERVER.setAllowCompression(true);
SysConsts.SOLR_SERVER.setMaxRetries(2);

  

八、查询方法

闭区间 [],开区间 {}: TO必须大写

 

prodlineid:13100 and indexnumber:[1497 TO 1499}

 

八、异常

    org.apache.solr.client.solrj.impl.HttpSolrServer$RemoteSolrException: Expected content type application/octet-stream  

  解决:链接地址 url写错了。

 

 

你可能感兴趣的:(Solr)