solrj-WiKi
solrj是一个访问solr的客户端,它提供了一个接口,用于添加、更新、删除索引数据.
solrj跨版本兼容
solrj一般保持向后兼容,所以你可以使用新版本的solrj访问老版本的solr服务,也可以使用老版本的solrj访问新版本的solr.
如果混合了1.x和以后的主版本,那么你必须设置响应解析器XML:
server.setParser(new XMLResponseParser());
3.x和4.x或者以后的版本混合的solr工作正常,只要不更改这个请求writer为二进制格式.
有一个例外情况是javabin格式,兼容方式在主版本之间已经改变.
设置类路径
solrj需要的最小jar包集合:
/dist:
apache-solr-solrj-*.jar
/dist/solrj-lib:
- commons-codec-1.3.jar
- commons-httpclient-3.1.jar
- commons-io-1.4.jar
- jcl-over-slf4j-1.5.5.jar
- slf4j-api-1.5.5.jar
/lib:
slf4j-jdk14-1.5.5.jar
Maven
在官方maven仓库中solrj是可以使用的,加入一下依赖到pom.xml中:
<dependency>
<artifactId>solr-solrj</artifactId>
<groupId>org.apache.solr</groupId>
<version>4.7.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
如果使用EmbeddedSolrServer,加入一下依赖:
<dependency>
<artifactId>solr-core</artifactId>
<groupId>org.apache.solr</groupId>
<version>4.7.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
同样,如果使用了EmbeddedSolrServer,注意Servlet API的依赖:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0</version>
</dependency>
如果碰到NoClassDefFoundError 异常,加入一下依赖:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.6</version>
</dependency>
HttpSolrServer
HttpSolrServer使用Apache Commons HTTP Client连接solr. 注意:在solr4.0中, CommonsHttpSolrServer 改成了 HttpSolrServer ,StreamingUpdateSolrServer 改成了ConcurrentUpdateSolrServer.
String url = "http://localhost:8983/solr";
/*
* HttpSolrServer线程安全,如果使用下面构造器,必须对所有的请求重用相同的实例.如果实例在运行中创建的,它可能会导致连接泄漏.
* 推荐的做法就是保持每个solr服务url的HttpSolrServer的静态实例,所有的请求都共享这个实例.
* 参考https://issues.apache.org/jira/browse/SOLR-861查看更多细节.
*/
SolrServer server = new HttpSolrServer(url);
具体可以参考:HttpSolrServer-采用静态工厂方法,创建HttpSolrServer单实例.如果你有更好的方法,可以回复一下,互相交流.
修改其他的Connection设置:
String url = "http://localhost:8983/solr";
HttpSolrServer server = new HttpSolrServer(url);
server.setMaxRetries(1); // defaults to 0. > 1 not recommended.
server.setConnectionTimeout(5000); // 5 seconds to establish TCP
// 下面的设置被完整的提供,它们一般不是必须选择的,最好是在查阅java文档之后来确认它们是否必须使用.
server.setSoTimeout(1000); // socket read timeout
server.setDefaultMaxConnectionsPerHost(100);
server.setMaxTotalConnections(100);
server.setFollowRedirects(false); // defaults to false
// 允许压缩默认为false.
// Server side must support gzip or deflate for this to have any effect.
server.setAllowCompression(true);
使用
首先创建一个服务的实例:
SolrServer server = new HttpSolrServer("http://HOST:8983/solr/");
删除所有索引数据:
server.deleteByQuery( "*:*" );
构造一个document:
SolrInputDocument doc1 = new SolrInputDocument();
doc1.addField( "id", "id1", 1.0f );
doc1.addField( "name", "doc1", 1.0f );
doc1.addField( "price", 10 );
构造另外一个document,最好是批量处理document,因为每次调用solrServer,就是一次http调用.
SolrInputDocument doc2 = new SolrInputDocument();
doc2.addField( "id", "id2", 1.0f );
doc2.addField( "name", "doc2", 1.0f );
doc2.addField( "price", 20 );
创建一个document的集合:
Collection<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
docs.add( doc1 );
docs.add( doc2 );
添加集合到solrServer,并提交.
server.add( docs );
server.commit()
为了在添加documents之后立刻提交,可以这样使用:
UpdateRequest req = new UpdateRequest();
req.setAction( UpdateRequest.ACTION.COMMIT, false, false );
req.add( docs );
UpdateResponse rsp = req.process( server );
更新文档流(streamimg documents)
大多数情况下,ConcurrentUpdateSolrServer就可以满足需要.作为一种选择,下面给出的解决方法可以应用。
这是一个在一个请求里更新所有文档的最优化的方案:
HttpSolrServer server = new HttpSolrServer();
Iterator<SolrInputDocument> iter = new Iterator<SolrInputDocument>(){
public boolean hasNext() {
boolean result ;
// set the result to true false to say if you have more documensts
return result;
} public SolrInputDocument next() {
SolrInputDocument result = null;
// construct a new document here and set it to result
return result;
}
};
server.add(iter);
也可以使用addBeans(Iterator<?> beansIter)来索引对象.
直接添加POJO到Solr
使用注解创建一个java bean.@Field可以用到字段(field)或者是方法(setter)上.如果索引字段名称和bean的字段名称不相同,可以使用别名来做一个映射,
import org.apache.solr.client.solrj.beans.Field; public class Item {
@Field
String id; @Field("cat")
String[] categories; @Field
List<String> features; }
或者是在setter方法中添加:
@Field("cat")
public void setCategory(String[] c){
this.categories = c;
}
获取SolrServer实例:
SolrServer server = getSolrServer();
创建bean实例:
Item item = new Item();
item.id = "one";
item.categories = new String[] { "aaa", "bbb", "ccc" };
添加到solr:
server.addBean(item);
添加bean集合:
List<Item> beans ;
//add Item objects to the list
server.addBeans(beans);
solr事务处理
solr在服务器级别实现事务处理.也就是说每次commit, optimize, or rollback都应用到了所有的请求中.更新solr最恰当的方式就是使用单独的进程来处理,以避免在提交或者是回滚时产生的竞争冲突.同样,最好是使用批处理来索引,因为提交和优化都是高消耗的程序.
读数据--数据库
import java.io.IOException;
import java.net.MalformedURLException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection; import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.common.SolrInputDocument; public class Test
{
private static int fetchSize = 1000;
private static String url = "http://localhost:8983/solr/core1/";
private static HttpSolrServer solrCore; public Test() throws MalformedURLException
{
solrCore = new HttpSolrServer(url);
} /**
* Takes an SQL ResultSet and adds the documents to solr. Does it in batches
* of fetchSize.
*
* @param rs
* A ResultSet from the database.
* @return The number of documents added to solr.
* @throws SQLException
* @throws SolrServerException
* @throws IOException
*/
public long addResultSet(ResultSet rs) throws SQLException,
SolrServerException, IOException
{
long count = 0;
int innerCount = 0;
Collection<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
ResultSetMetaData rsm = rs.getMetaData();
int numColumns = rsm.getColumnCount();
String[] colNames = new String[numColumns + 1]; /**
* JDBC numbers the columns starting at 1, so the normal java convention
* of starting at zero won't work.
*/
for (int i = 1; i < (numColumns + 1); i++)
{
colNames[i] = rsm.getColumnName(i);
/**
* If there are fields that you want to handle manually, check for
* them here and change that entry in colNames to null. This will
* cause the loop in the next section to skip that database column.
*/
// //Example:
// if (rsm.getColumnName(i) == "db_id")
// {
// colNames[i] = null;
// }
} while (rs.next())
{
count++;
innerCount++; SolrInputDocument doc = new SolrInputDocument(); /**
* At this point, take care of manual document field assignments for
* which you previously assigned the colNames entry to null.
*/
// //Example:
// doc.addField("solr_db_id", rs.getLong("db_id")); for (int j = 1; j < (numColumns + 1); j++)
{
if (colNames[j] != null)
{
Object f;
switch (rsm.getColumnType(j))
{
case Types.BIGINT:
{
f = rs.getLong(j);
break;
}
case Types.INTEGER:
{
f = rs.getInt(j);
break;
}
case Types.DATE:
{
f = rs.getDate(j);
break;
}
case Types.FLOAT:
{
f = rs.getFloat(j);
break;
}
case Types.DOUBLE:
{
f = rs.getDouble(j);
break;
}
case Types.TIME:
{
f = rs.getDate(j);
break;
}
case Types.BOOLEAN:
{
f = rs.getBoolean(j);
break;
}
default:
{
f = rs.getString(j);
}
}
doc.addField(colNames[j], f);
}
}
docs.add(doc); /**
* When we reach fetchSize, index the documents and reset the inner
* counter.
*/
if (innerCount == fetchSize)
{
solrCore.add(docs);
docs.clear();
innerCount = 0;
}
} /**
* If the outer loop ended before the inner loop reset, index the
* remaining documents.
*/
if (innerCount != 0)
{
solrCore.add(docs);
}
return count;
}
}
设置RequestWriter
solrj允许使用XML和二进制两种格式上传内容,默认设置是XML.下面使用的是二进制上传内容,solrj获取结果采用相同的格式.并且这样极大的提高了性能,因为它减少了XML编组开销.
server.setRequestWriter(new BinaryRequestWriter());
注意:确定solrconfig.xml中同样开启"BinaryUpdateRequestHandler"的功能:
<requestHandler name="/update/javabin" class="solr.BinaryUpdateRequestHandler" />
Solr中读取查询内容
获取一个solrServer实例:
SolrServer server = getSolrServer();
构造SolrQuery:
SolrQuery query = new SolrQuery();
query.setQuery( "*:*" );
query.addSortField( "price", SolrQuery.ORDER.asc );
执行查询:
QueryResponse rsp = server.query( query );
获取结果:
SolrDocumentList docs = rsp.getResults();
获取bean对象的结果集,bean类必须采用注解.
List<Item> beans = rsp.getBeans(Item.class);
高级使用方式
SolrJ提供了一个API来创建查询,而不是手工编码查询.下面是一个分面查询的例子:
SolrServer server = getSolrServer();
SolrQuery solrQuery = new SolrQuery().
setQuery("ipod").
setFacet(true).
setFacetMinCount(1).
setFacetLimit(8).
addFacetField("category").
addFacetField("inStock");
QueryResponse rsp = server.query(solrQuery);
高亮--Highlighting
设置高亮参数的方式和其他常用参数的设置方式一样:
SolrQuery query = new SolrQuery();
query.setQuery("foo"); query.setHighlight(true).setHighlightSnippets(1); //set other params as needed
query.setParam("hl.fl", "content"); QueryResponse queryResponse = getSolrServer().query(query);
这样取回高亮结果集:
Iterator<SolrDocument> iter = queryResponse.getResults().iterator(); while (iter.hasNext()) {
SolrDocument resultDoc = iter.next(); String content = (String) resultDoc.getFieldValue("content");
String id = (String) resultDoc.getFieldValue("id"); //id is the uniqueKey field if (queryResponse.getHighlighting().get(id) != null) {
List<String> highlightSnippets = queryResponse.getHighlighting().get(id).get("content");
}
}
负载均衡查询
当你有多个Solr的服务器可以处理查询时,虽然你肯定喜欢选择使用的外部负载平衡器,但是solrj提供了一个简单的内置的轮询负载均衡功能LBHttpSolrServer.
使用SolrCloud
SolrJ包含了SolrCloud的一个敏捷的客户端,也就是ZooKeeper.这就意味着你的java应用程序只需要知道Zookeeper实例,并不知道你的solr实例在什么地方,因为这些可以从ZooKeeper中获取.
为了和SolrCloud交互,需要使用CloudSolrServer的实例,并且传入你得ZooKeeper主机地址(一个或者多个).除了CloudSolrServer的实例化不一样外,其他的处理方式都是一样的:
import org.apache.solr.client.solrj.impl.CloudSolrServer;
import org.apache.solr.common.SolrInputDocument; CloudSolrServer server = new CloudSolrServer("localhost:9983");
server.setDefaultCollection("collection1");
SolrInputDocument doc = new SolrInputDocument();
doc.addField( "id", "1234");
doc.addField( "name", "A lovely summer holiday");
server.add(doc);
server.commit();
翻译:http://wiki.apache.org/solr/Solrj,
solrj-WiKi的更多相关文章
- 五、SolrJ、Request Handler
什么是SolrJ 既然Solr是以单独的WebApp形式存在的,那么Solr理应提供与Solr通信的Api吧,对的,这就是SolrJ,既然与solr通信是通过url,那么其实我们也可以不用SolrJ, ...
- solrj-solr Guide 4.7
solrj是一个很容易使java应用程序和solr进行交互的一个API,solrj隐藏了很多连接Solr的细节,允许你的应用程序使用简单的高级方法和solr互动交流. solrj的核心就是 org.a ...
- Solr JAVA客户端SolrJ 4.9使用示例教程
http://my.oschina.net/cloudcoder/blog/305024 简介 SolrJ是操作Solr的JAVA客户端,它提供了增加.修改.删除.查询Solr索引的JAVA接口.So ...
- [solr] - SolrJ增删查
使用SolrJ进行对Solr的增.删.查功能. 参考引用: http://wiki.apache.org/solr/Solrj Eclipse中新建一个项目:TestSolr 其中SorlJ的Lib包 ...
- 【Solr专题之九】SolrJ教程
一.SolrJ基础 1.相关资料 API:http://lucene.apache.org/solr/4_9_0/solr-solrj/ apache_solr_ref_guide_4.9.pdf:C ...
- Solr Wiki文档
相比ElasticSearch,Solr的文档详尽丰富,同时也显得冗余啰嗦. Solr的官方文档有两个地方: Solr官方教程 Solr社区维基 本文主要列出一些Solr Wiki中的主要讨论主题,方 ...
- Solr系列四:Solr(solrj 、索引API 、 结构化数据导入)
一.SolrJ介绍 1. SolrJ是什么? Solr提供的用于JAVA应用中访问solr服务API的客户端jar.在我们的应用中引入solrj: <dependency> <gro ...
- SolrJ API 官方文档最佳实践
以下内容译自Solr Wiki官方文档,版权没有,随意转载. Solrj 是一个访问solr的Java客户端.它提供了一个java接口用于添加更新和查询solr索引.本页面介绍SolrJ最新版本1.4 ...
- JAVAEE——Solr:安装及配置、后台管理索引库、 使用SolrJ管理索引库、仿京东的电商搜索案例实现
1 学习回顾 1. Lucene 是Apache开源的全文检索的工具包 创建索引 查询索引 2. 遇到问题? 文件名 及文件内容 顺序扫描法 全文检索 3. 什么是全文检索? 这种先创建索引 再 ...
- SOLR企业搜索平台 三 (schema.xml配置和solrj的使用)
标签:solrj 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://3961409.blog.51cto.com/3951409/8 ...
随机推荐
- ntpdate server时出错原因及解决
错误1.Server dropped: Strata too high 在ntp客户端运行ntpdate serverIP,出现no server suitable for synchronizati ...
- JS初识(着重讲解Date函数)
查看类型:typeof() 转换为int类型:parseInt() isNaN() 函数用于检查其参数是否是非数字值. NaN,是Not a Number的缩写.一种计算机用语.NaN 用于处理计算中 ...
- 30几个HTML5经典动画应用回顾 让你大饱眼福
周末大放送,让我们来回顾一下HTML5经典动画应用,一定会让你大饱眼福. 1.HTML5 Canvas画板画图工具 可定义笔刷和画布 HTML5 Canvas还有一个比较实用的应用,那就是网络画板,这 ...
- HDU 3920Clear All of Them I(状压DP)
HDU 3920 Clear All of Them I 题目是说有2n个敌人,现在可以发n枚炮弹,每枚炮弹可以(可以且仅可以)打两个敌人,每一枚炮弹的花费等于它所行进的距离,现在要消灭所有的敌人 ...
- 2013-2014集训之DP
第一周: 经过漫长的时间,终于有时间来写一下结题报告. 地址http://acm.hust.edu.cn/vjudge/contest/view.action?cid=36180#overview A ...
- Spring4.0+Hibernate4.0+Struts2.3整合包括增删改查案例,解决整合中出现的异常
源码下载:http://download.csdn.net/detail/cmcc_1234/7034775 ======================Application.xml======== ...
- SVN安装与使用
来自:http://www.cnblogs.com/xiaobaihome/archive/2012/03/20/2407610.html SVN服务器搭建和使用(一) Subversion是优秀的版 ...
- c语言-格式控制字符 %XXd 用法
d格式字符 用来输出十进制整数,有以下几种用法: 1. %d, 按整型数据的实际长度输出. 2. %md,m为指定输出的整型位数的宽度,如果整型数据的实际位数小于m,则左端补以空格,如果大于m,则按 ...
- C++ 中 int,char*,string,CString之间相互转换-整理
<多字符集下> #include <string> //使用C++标准库的string类时, 定义时 std::string str; using namespace std; ...
- git filename to long问题解决
在.git/config 下面编辑 [core] longpaths = true