使用Solrj管理Solr索引

2023-12-05 22:58
文章标签 使用 管理 索引 solrj solr

本文主要是介绍使用Solrj管理Solr索引,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Solrj是Solr搜索服务器的一个比较基础的客户端工具,可以非常方便地与Solr搜索服务器进行交互,最基本的功能就是管理Solr索引,包括添加、更新、删除和查询等。对于一些比较基础的应用,用Solj基本够用,而且你可以非常容易地通过使用Solrj的API实现与Solr搜索服务器进行交互,实现对Solr的基本管理功能。如果你的应用比较复杂,可以扩展Solrj来满足需要。

下面是一个使用Solrj的API实现与Solr服务器交互的工具类SolrPostServer,能够实现索引的添加、更新、删除和查询功能。SolrPostServer类中两个内部类是与访问MongoDB的配置和工具。

在实际应用中,对于是否进行commit,可以有两种方式:

  • 一种是直接在客户端进行计算,亦即,进行索引时计算添加的文档数,满足设置的值则进行手动commit,这种方式比较灵活,你可以根据搜索服务器的运行状况选择合理的commit文档数量;
  • 另一种是,直接在Solr搜索服务器上进行配置,一般来说,对索引进行大批量更新,一般不会选择在搜索服务器业务繁忙的时候进行,所以能够自动进行commit也便利了对索引的管理,更新文档可以完全可以实现自动化处理。
在Solr服务器端进行配置有关commit的功能,可以在requestHandler中进行配置,示例如下:
	<requestHandler name="/update" class="solr.XmlUpdateRequestHandler"><maxPendingDeletes>10000</maxPendingDeletes><autoCommit><maxDocs>20</maxDocs><maxTime>86000</maxTime></autoCommit></requestHandler>
上面autoCommit中的maxDocs指定的pending多少个文档后执行一次commit,而maxTime指定了多长时间间隔进行一次commit,一般这两个选项只需要配置一个即可满足需要。另外,每次commit会将最近的更新生效,但是如果一次commit操作尚未完成,又达到了下一次commit的时刻,这样做会严重影响索引的吞吐量。
在Solr 4.0将会实现一种基于“软自动提交”(soft auto commit)的功能,它会根据当前的系统上下文决定是否提交(简单的情况就是,确保每次commit完成,也就是最近的索引数据更新已经更新同步到磁盘上之后再自动执行下一次commit)。

实现代码如下所示:

package org.shirdrn.solr.solrj;import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;import org.apache.commons.httpclient.HttpClient;
import org.apache.log4j.Logger;
import org.apache.lucene.document.Document;
import org.apache.solr.client.solrj.ResponseParser;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.SolrParams;import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;/*** Solr server for indexes operations.* * @author shirdrn* @date   2011-12-20*/
public class SolrPostServer {private static final Logger LOG = Logger.getLogger(SolrPostServer.class);private CommonsHttpSolrServer server; private ResponseParser responseParser;private MongoConfig mongoConfig;private String[] collectionNames;private  int maxCommitCount = 100;private boolean manualOptimize = true;private boolean manualCommit = false;private Collection<SolrInputDocument> docContainer = new ArrayList<SolrInputDocument>();private static int totalCount = 0;public SolrPostServer(String url, HttpClient httpClient, MongoConfig mongoConfig) {try {if(httpClient==null) {server = new CommonsHttpSolrServer(url);server.setSoTimeout(500000);  // socket read timeoutserver.setConnectionTimeout(5000);  server.setDefaultMaxConnectionsPerHost(10);  server.setMaxTotalConnections(100);server.setAllowCompression(true);  server.setMaxRetries(1); // defaults to 0.  > 1 not recommended. } else {server = new CommonsHttpSolrServer(url, httpClient);}} catch (MalformedURLException e) {e.printStackTrace();}this.mongoConfig = mongoConfig;initialize();}/*** Initialize the {@link CommonsHttpSolrServer}'s basic parameters.*/private void initialize() {if(responseParser!=null) {server.setParser(responseParser);} else {server.setParser(new XMLResponseParser());}}@SuppressWarnings("unchecked")public void postUpdate() {DBCursor cursor = null;try {for (String c : collectionNames) {LOG.info("MongoDB collection name: " + c);DBCollection collection = MongoHelper.newHelper(mongoConfig).getCollection(c);DBObject q = new BasicDBObject();cursor = collection.find(q);while(cursor.hasNext()) {try {Map<Object, Object> m = cursor.next().toMap();if(manualCommit) {add(m, true);} else {add(m, false);}++totalCount;LOG.info("Add fragment: _id = " + m.get("_id").toString());} catch (IOException e) {e.printStackTrace();}}cursor.close();}LOG.info("Add totalCount: " + totalCount);finallyCommit();optimize(manualOptimize);} catch (MongoException e) {e.printStackTrace();} catch (SolrServerException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/*** Detele lucene {@link Document} by IDs.* @param strings*/public void deleteById(List<String> strings) {try {server.deleteById(strings);} catch (SolrServerException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/*** Detele lucene {@link Document} by query.* @param query*/public void deleteByQuery(String query) {try {server.deleteByQuery(query);} catch (SolrServerException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/*** Query.* @param params* @param fields* @return*/public List<Map<String, Object>> query(SolrParams params, String[] fields) {List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();try {SolrDocumentList documents = server.query(params).getResults();Iterator<SolrDocument> iter = documents.iterator();while(iter.hasNext()) {SolrDocument doc = iter.next();Map<String, Object> map = new HashMap<String, Object>();for(String field : fields) {map.put(field, doc.getFieldValue(field));}results.add(map);}} catch (SolrServerException e) {e.printStackTrace();}return results;}/*** When controlling the committing action at client side, finally execute committing.* @throws SolrServerException* @throws IOException*/private void finallyCommit() throws SolrServerException, IOException {if(!docContainer.isEmpty()) {server.add(docContainer);commit(false, false);}}/*** Commit.* @param waitFlush* @param waitSearcher* @throws SolrServerException* @throws IOException*/public void commit(boolean waitFlush, boolean waitSearcher) {try {server.commit(waitFlush, waitSearcher);} catch (SolrServerException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/*** When controlling the optimizing action at client side, finally execute optimizing.* @param waitFlush* @param waitSearcher* @throws SolrServerException* @throws IOException*/public void optimize(boolean waitFlush, boolean waitSearcher) {try {server.optimize(waitFlush, waitSearcher);commit(waitFlush, waitSearcher);} catch (Exception e) {LOG.error("Encounter error when optimizing.",  e);try {server.rollback();} catch (SolrServerException e1) {e1.printStackTrace();} catch (IOException e1) {e1.printStackTrace();}}}/*** Optimize.* @param optimize* @throws SolrServerException* @throws IOException*/private void optimize(boolean optimize) {if(optimize) {optimize(true, true);}}/*** Add a {@link SolrInputDocument} or collect object and add to the a collection for batch updating* from a mongodb's recored, a Map object.* @param m* @param oneByOne* @throws SolrServerException* @throws IOException*/private void add(Map<Object, Object> m, boolean oneByOne) throws SolrServerException, IOException {SolrInputDocument doc = createDocument(m);if(oneByOne) {server.add(doc);} else {docContainer.add(doc);if(docContainer.size()>maxCommitCount) {server.add(docContainer);server.commit(false, false);docContainer = new ArrayList<SolrInputDocument>();}}}/*** Create a {@link SolrInputDocument} object.* @param record* @return*/private SolrInputDocument createDocument(Map<Object, Object> record) {String id = record.get("_id").toString();String articleId = (String) record.get("articleId");String title = (String) record.get("title");String url = (String) record.get("url");String spiderName = (String) record.get("spiderName");String fragment = makeFragment((BasicDBObject) record.get("fragment"));String word = (String) record.get("word");int pictureCount = (Integer) record.get("pictureCount");int selectedCount = (Integer) record.get("selectedCount");int fragmentSize = (Integer) record.get("fragmentSize");SolrInputDocument doc = new SolrInputDocument();doc.addField("_id", id, 1.0f);doc.addField("articleId", articleId, 1.0f);doc.addField("title", title, 1.0f);doc.addField("url", url, 1.0f);doc.addField("spiderName", spiderName, 1.0f);doc.addField("fragment", fragment, 1.0f);doc.addField("word", word, 1.0f);// Additional processing for lucene payload metadata.doc.addField("pictureCount", word + "|" + pictureCount);doc.addField("coverage", word + "|" + (float)selectedCount/fragmentSize);return doc;}@SuppressWarnings("unchecked")private String makeFragment(BasicDBObject fragment) {StringBuilder builder = new StringBuilder();Iterator<Map.Entry<Integer, String>> iter = fragment.toMap().entrySet().iterator();while(iter.hasNext()) {Map.Entry<Integer, String> entry = iter.next();builder.append(entry.getValue().trim()).append("<br>");}return builder.toString();}/*** Set {@link ResponseParser}, default value is {@link XMLResponseParser}.* @param responseParser*/public void setResponseParser(ResponseParser responseParser) {this.responseParser = responseParser;}/*** Pulling document resource from multiple collections of MongoDB.* @param collectionNames*/public void setCollectionNames(String[] collectionNames) {this.collectionNames = collectionNames;}public void setMaxCommitCount(int maxCommitCount) {this.maxCommitCount = maxCommitCount;}public void setManualCommit(boolean manualCommit) {this.manualCommit = manualCommit;}public void setManualOptimize(boolean manualOptimize) {this.manualOptimize = manualOptimize;}/*** Mongo database configuration.* * @author shirdrn* @date   2011-12-20*/public static class MongoConfig implements Serializable {private static final long serialVersionUID = -3028092758346115702L;private String host;private int port;private String dbname;private String collectionName;public MongoConfig(String host, int port, String dbname, String collectionName) {super();this.host = host;this.port = port;this.dbname = dbname;this.collectionName = collectionName;}@Overridepublic boolean equals(Object obj) {MongoConfig other = (MongoConfig) obj;return host.equals(other.host) && port==other.port&& dbname.equals(other.dbname) && collectionName.equals(other.collectionName);}}/*** Mongo database utility.* * @author shirdrn* @date   2011-12-20*/static class MongoHelper {private static Mongo mongo;private static MongoHelper helper;private MongoConfig mongoConfig;private MongoHelper(MongoConfig mongoConfig) {super();this.mongoConfig = mongoConfig;}public synchronized static MongoHelper newHelper(MongoConfig mongoConfig) {try {if(helper==null) {helper = new MongoHelper(mongoConfig);mongo = new Mongo(mongoConfig.host, mongoConfig.port);Runtime.getRuntime().addShutdownHook(new Thread() {@Overridepublic void run() {if(mongo!=null) {mongo.close();}}});}} catch (Exception e) {e.printStackTrace();}return helper;}			public DBCollection getCollection(String collectionName) {DBCollection c = null;try {c = mongo.getDB(mongoConfig.dbname).getCollection(collectionName);} catch (Exception e) {e.printStackTrace();}return c;}	}
}

下面,我们可以通过写一个测试用例测试一下。

首先,我的Solr搜索服务器已经部署好并启动成功,对应的url为http://192.168.0.197:8080/server/fragment/。测试用例如下所示:

package org.shirdrn.solr.solrj;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import junit.framework.TestCase;import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.MapSolrParams;
import org.shirdrn.solr.solrj.SolrPostServer.MongoConfig;@SuppressWarnings("deprecation")
public class TestSolrPostServer extends TestCase {SolrPostServer myServer;MongoConfig config;String url;String[] collectionNames;@Overrideprotected void setUp() throws Exception {url = "http://192.168.0.197:8080/server/fragment/";config = new MongoConfig("192.168.0.184", 27017, "fragment", "");myServer = new SolrPostServer(url, null, config);myServer.setMaxCommitCount(100);}@Overrideprotected void tearDown() throws Exception {super.tearDown();}public void testPostUpdate() {collectionNames = new String[] {"sina","lvping","daodao","go2eu","mafengwo","lotour","17u","sohu","baseSe","bytravel"};myServer.setCollectionNames(collectionNames);myServer.setManualCommit(true);myServer.setManualOptimize(false);myServer.postUpdate();}public void testPostDelete() {List<String> strings = new ArrayList<String>();strings.add("4ef051342c4117a38f63ee97");strings.add("4ef051322c4117a38f63ee36");strings.add("4ef051a42c4117a38f63fb51");strings.add("4ef050d92c4117a38f63dda4");strings.add("4ef051fe2c4117a38f640bc8");strings.add("4ef048ef2c4117a38f6207ce");strings.add("4ef049062c4117a38f620e13");strings.add("4ef046f12c4117a38f6185c0");myServer.deleteById(strings);myServer.commit(false, false);myServer.optimize(true, false);}@SuppressWarnings({ "rawtypes", "unchecked" })public void testQuery() {Map map = new HashMap();map.put(CommonParams.Q, "法国");map.put(CommonParams.START, "0");map.put(CommonParams.ROWS, "10");map.put(CommonParams.FQ, "word:卢浮宫");SolrParams params = new MapSolrParams(map);List<Map<String, Object>> results = myServer.query(params, new String[] {"_id", "title", "url"});assertEquals(10, results.size());}
}

在实际开发的过程中,使用Solrj客户端可以非常容易为测试做一些基本操作,如创建索引,测试Solr基本参数及其开发定制Solr相关接口(Retrieval、Highlighting、Faceted Search、Clustering等等)。


这篇关于使用Solrj管理Solr索引的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/459450

相关文章

python使用库爬取m3u8文件的示例

《python使用库爬取m3u8文件的示例》本文主要介绍了python使用库爬取m3u8文件的示例,可以使用requests、m3u8、ffmpeg等库,实现获取、解析、下载视频片段并合并等步骤,具有... 目录一、准备工作二、获取m3u8文件内容三、解析m3u8文件四、下载视频片段五、合并视频片段六、错误

gitlab安装及邮箱配置和常用使用方式

《gitlab安装及邮箱配置和常用使用方式》:本文主要介绍gitlab安装及邮箱配置和常用使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装GitLab2.配置GitLab邮件服务3.GitLab的账号注册邮箱验证及其分组4.gitlab分支和标签的

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

nginx启动命令和默认配置文件的使用

《nginx启动命令和默认配置文件的使用》:本文主要介绍nginx启动命令和默认配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录常见命令nginx.conf配置文件location匹配规则图片服务器总结常见命令# 默认配置文件启动./nginx

在Windows上使用qemu安装ubuntu24.04服务器的详细指南

《在Windows上使用qemu安装ubuntu24.04服务器的详细指南》本文介绍了在Windows上使用QEMU安装Ubuntu24.04的全流程:安装QEMU、准备ISO镜像、创建虚拟磁盘、配置... 目录1. 安装QEMU环境2. 准备Ubuntu 24.04镜像3. 启动QEMU安装Ubuntu4

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

Python常用命令提示符使用方法详解

《Python常用命令提示符使用方法详解》在学习python的过程中,我们需要用到命令提示符(CMD)进行环境的配置,:本文主要介绍Python常用命令提示符使用方法的相关资料,文中通过代码介绍的... 目录一、python环境基础命令【Windows】1、检查Python是否安装2、 查看Python的安

Python并行处理实战之如何使用ProcessPoolExecutor加速计算

《Python并行处理实战之如何使用ProcessPoolExecutor加速计算》Python提供了多种并行处理的方式,其中concurrent.futures模块的ProcessPoolExecu... 目录简介完整代码示例代码解释1. 导入必要的模块2. 定义处理函数3. 主函数4. 生成数字列表5.

Python中help()和dir()函数的使用

《Python中help()和dir()函数的使用》我们经常需要查看某个对象(如模块、类、函数等)的属性和方法,Python提供了两个内置函数help()和dir(),它们可以帮助我们快速了解代... 目录1. 引言2. help() 函数2.1 作用2.2 使用方法2.3 示例(1) 查看内置函数的帮助(