solr搜索提示,将词添加到词库中

2019-03-27 01:16|来源: 网路

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

     实现对搜索时关键字的提示,同时扩展,将词库中未有的关键词添加到词库中,目前不支持去重功能。

一、solrconfig.xml 配置

     在solrconfig.xml配置文件中添加 “关键词提示” 组件

	<searchComponent name="suggest" class="com.netboy.demo.function.SpellCheckAndLoadComponent">  
	  <lst name="spellchecker">  
	    <str name="name">suggest</str>  
	    <str name="classname">org.apache.solr.spelling.suggest.Suggester</str>  
	    <str name="lookupImpl">org.apache.solr.spelling.suggest.tst.TSTLookup</str>  
	    <str name="field">title</str>
	    <str name="sourceLocation">stopwords.txt</str>
	    <str name="size">4</str>
	    <!-- <float name="threshold">0.005</float> -->
	     <str name="buildOnCommit">true</str>
	  </lst>  
	</searchComponent> 

	<requestHandler name="/suggest" class="org.apache.solr.handler.component.SearchHandler">  
	 <lst name="defaults">  
	   <str name="spellcheck">true</str>
	   <str name="spellcheck.dictionary">suggest</str>  
	   <str name="spellcheck.count">5</str>  
	   <str name="spellcheck.onlyMorePopular">true</str>  
	   <str name="spellcheck.collate">true</str>      
	 </lst>  
	 <arr name="components">  
	   <str>suggest</str>  
	 </arr>
	</requestHandler>

stopwords.txt内容如下:

jetty
netty
淘宝
taobao
水杯
章法
天龙八部
虚竹
木婉清
段誉
章
人
人 民
嫁了人

可以在关键词后面加上权重,tab键+数字,数值越大权重越大。


二、 扩展SpellCheckComponent

自定义类SpellCheckAndLoadComponent类,实现:  solr搜索提示,将词添加到词库中


代码如下:

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Set;

import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.SolrCore;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SpellCheckComponent;
import org.apache.solr.request.SolrQueryRequest;
import org.eclipse.jetty.util.ConcurrentHashSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 返回已经有的提示词,如果没有则将该词添加到词库中
 * 
 * @author 2013-7-13下午10:09:36
 */
public class SpellCheckAndLoadComponent extends SpellCheckComponent {
	private static final Logger logger = LoggerFactory.getLogger(SpellCheckAndLoadComponent.class);

	private static ConcurrentHashSet<String> spellSet = new ConcurrentHashSet<String>();
	private BufferedWriter out;
	private int size = 99;
	private String field;

	@Override
	public void init(NamedList args) {
		super.init(args);
		Object o = args.get("spellchecker");
		String fileStr = null;
		if(o != null && o instanceof NamedList) {
			NamedList temp = (NamedList) o;
			fileStr = (String) temp.get("sourceLocation");
			String sizeStr = (String) temp.get("size");
			field = (String) temp.get("field");

			if(sizeStr != null) {
				size = Integer.parseInt(sizeStr);
			}
			logger.info("the dictionary is " + fileStr);

		}
		synchronized(this) {
			if(fileStr != null) {
				try {
					out = new BufferedWriter(new FileWriter(fileStr, true));
				} catch(FileNotFoundException e) {
					e.printStackTrace();
				} catch(IOException e) {

					e.printStackTrace();
				}
			}
		}

	}

	@Override
	public void inform(SolrCore solrCore) {
		super.inform(solrCore);
		synchronized(this) {
			if(spellSet == null) {
				spellSet = new ConcurrentHashSet<String>();
			}
		}
	}

	@Override
	public void process(ResponseBuilder rb) {
		String words = null;
		try {
			super.process(rb);
			SolrQueryRequest sqr = rb.req;
			SolrParams param = sqr.getParams();
			words = param.get("q").trim();
			
			String[] subString = words.split(":");
			if(subString[0].equals(field)) {
				words = subString[1].trim();
				synchronized(this) {
					spellSet.add(words);
					if(spellSet.size() >= size) {
						pushFile(spellSet);
						spellSet.clear();
					}
				}
			}

		} catch(IOException e) {

			logger.warn("spellCheck had some error" + e);
		}
	}

	public void pushFile(Set<String> set) {
		for(String str : set) {
			if(str != null) {
				try {
					out.write(str);
					out.newLine();
					out.flush();

				} catch(IOException e) {
					logger.warn("error in writing dictionary" + e);
				}
			}
		}
	}

	@Override
	public void finishStage(ResponseBuilder rb) {
		super.finishStage(rb);
		pushFile(spellSet);
		synchronized(out) {
			try {
				out.close();
			} catch(IOException e) {
				logger.info("close the FileOutputStream" + e);
			}
		}

		spellSet.clear();
	}
}

三、运行


第一次运行:http://127.0.0.1:8989/auction/suggest?q=title:%E4%BA%BA&spellcheck=on&spellcheck.build=true

返回结果:


如果词库中没有关键词如: http://127.0.0.1:8989/auction/suggest?q=title:电子科大&spellcheck=on&spellcheck.build=true

     返回结果: 



第二次运行: http://127.0.0.1:8989/auction/suggest?q=title:电&spellcheck=on&spellcheck.build=true

返回结果:



四、客户端连接

public class SpellCheckTest {
	public static void main(String[] args) {
		SolrServer solrServer = new HttpSolrServer("http://127.0.0.1:8989/auction");

		// http://127.0.0.1:8989/auction/suggest?q=人&spellcheck=on&spellcheck.build=true 
		SolrQuery params = new SolrQuery();

		String token = "人";
		params.set("qt", "/suggest");
		params.set("q", token);
		params.set("spellcheck", "true");
		params.set("spellcheck.build", "true");

		QueryResponse response = null;

		try {
			response = solrServer.query(params);
		} catch(SolrServerException e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
		} catch(Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
		} finally {
			solrServer.shutdown();
		}

		SpellCheckResponse spellCheckResponse = response.getSpellCheckResponse();
		if(spellCheckResponse != null) {
			List<Suggestion> suggestionList = spellCheckResponse.getSuggestions();
			for(Suggestion suggestion : suggestionList) {
				System.out.println("Suggestions NumFound: " + suggestion.getNumFound());
				System.out.println("Token: " + suggestion.getToken());
				System.out.print("Suggested: ");
				List<String> suggestedWordList = suggestion.getAlternatives();
				for(String word : suggestedWordList) {
					System.out.println(word);
				}
				System.out.println();
			}

			System.out.println("查询耗时:" + response.getQTime());
			solrServer.shutdown();
		}
	}
}

运行结果:


Suggestions NumFound: 1
Token: 人
Suggested: 人 民

查询耗时:6




转自:http://blog.csdn.net/yeshenrenjin/article/details/9324387

相关问答

更多
  • 使用LocalParams类来表示Solr中的LocalParams : solr.Query(new LocalParams { {"type", "spatial"}, {"lat", "-51.5224"}, {"long", "-2.6257"}, {"radius", "10000"}, {"unit", "km"}, {"calc", "arc"}, {"threadCount", "2"}, } + Query.Field("text") ...
  • 胡萝卜告诉你它需要阅读该资源。 您需要将其上传到DSE搜索,以便可以选择它。 上传根据您的方便调整: curl -s --data-binary @ -H 'Content-type:text/xml; charset=utf-8' http://:8983/solr/resource//clustering/carrot2/default-attributes.xml 确保上传到DSE搜索所需的所有资源。 DSE Search不会从 ...
  • 你有没有对它进行整理或复制? 如果您不知道,请阅读此内容 。 1)通过solr在内部同步分片或复制,因此应在两个核心中对其进行分割或添加。 2)无论哪一个,solr为你做这件事,你只需要让zooKeeper准备接受并平衡每个核心之间的请求。 3)如果您要将数据添加到复制的核心,则不能,但如果您正在分析核心,我认为这是可能的,它在这里得到了回答: 如何使用solrj索引特定分片中的数据 Did you shard it or was it replicated? Read this if you don't ...
  • 错误: 未知字段'parent' 通常意味着您的schema.xml中没有名为parent的字段。 解决方案非常简单,包括添加此类字段。 The error: unknown field 'parent' normally means that you don't have a field called parent in your schema.xml. The solution is very simple and consists in adding such field.
  • 使用solrj客户端,您可以创建SolrInputDocument对象并将它们发布到SolrServer实例,无论它是HttpSolrServer还是EmbeddedSolrServer。 SolrInputDocument是一个名称值对集合,它将等同于您要发布的json。 如https://wiki.apache.org/solr/Solrj#Adding_Data_to_Solr所述 如果你真的想把JSON发送到Solr服务器,你可以使用类似HTTPClient的东西将JSON发布到http://sol ...
  • 首先要检查的是服务器端日志,并查找有关提交的消息。 在解析每个文件后,您可能正在进行硬提交。 这太贵了。 您可以查看软提交或commitWithin params以稍后显示文件。 其次,您似乎向Solr发送请求以获取您的文件并在其上运行Tika提取。 所以,这可能每次都会在Solr内重新启动Tika。 你将无法按照其他答案的建议进行批量处理。 但是你可以在你的客户端本地运行Tika并初始化它并保留它。 然后,可以更灵活地构建SolrInputDocument,然后可以批量处理。 First thing to ...
  • 您可以使用同义词文件。 看看这个文档站点 (solr.SynonymFilterFactory):
  • 它只允许将一个文件作为附件附加。 Solr确实允许对zip文件建立索引( 补丁 ),这将索引文件的内容。 因此,您可以将文件打包成zip并将其提供给Solr,它将被索引为Single文档。 It just allows one file to be attached as an attachment. Solr does allow zip files to be indexed (patch), which would index the contents for the files. So you ca ...
  • 您可以将sharedLib参数添加到solr.xml文件中。 此参数指定将在所有核心之间共享的公共库目录的路径。 此目录中的任何JAR文件都将添加到Solr插件的搜索路径中。 此路径相对于顶级容器的Solr Home。 我是这样做的。 /opt/shared-lib
    如果要对delta查询使用时间字段(例如“lastModified”),请确保在创建新行时也设置该字段。 例如,如果您的表有4列id,name,updatedOn,addedOn,并且您在data-config.xml文件中使用updatedOn来标识已更改的行,那么请确保您的updatedOn对于新行不为null。 If you are using a temporal field (such as 'lastModified') for the delta query, make sure you al ...