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 ...
随机推荐
- html5 +css3 第一章学习和笔记
各位同学.身为本版的斑竹.,希望各位童鞋都能学到Html5 .特此没两天更新一个学习笔记和大家一起学习Html5.... 语法改变 1.新增的元素和废除的元素 2.新增的属性和 ...
- CSS单词换行and断词
背景 某天老板在群里反馈,英文单词为什么被截断了? 很显然,这是我们前端的锅,自行背锅.这个问题太简单了,css里加两行属性,分分钟搞定. 1 2 word–break: keep–all; wo ...
- Light oj 1100 - Again Array Queries (鸽巢原理+暴力)
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1100 给你n个数,数的范围是1~1000,给你q个询问,每个询问问你l到r之间 ...
- StructLayout特性
StructLayout特性 公共语言运行库利用 StructLayoutAttribute控制类或结构的数据字段在托管内存中的物理布局,即类或结构需要按某种方式排列.如果要将类传递 ...
- mvc4帮助类
@App @AppState @Ajax @Cache @Context @Culture @Html @IsPost @Layout @Model @Output @OutputStack @Pag ...
- 转载:CSS3 圆角(border-radius)
前缀 例1 例2:无边框 书写顺序 其它 支持性 值:半径的长度 前缀 -moz(例如 -moz-border-radius)用于Firefox -webkit(例如:-webkit-border-r ...
- PHP安装环境,服务器不支持curl_exec的解决办法
转自:http://jingyan.baidu.com/article/00a07f38909c6b82d028dc83.html windows下开启方法: 拷贝PHP目录中的libeay32.dl ...
- android布局太深导致的 java.lang.StackOverflowError
E/AndroidRuntime( 1900): java.lang.StackOverflowError E/AndroidRuntime( 1900): at android.graphi ...
- cocos2dx shader实现灰度图android后台切换回来导致图像偏移的问题
转自:http://www.tuicool.com/articles/U3URRrI 项目中经常会遇到将一张图像处理成灰色的需求,为了节省资源,一般不会让美术再做一套同样的灰度图,通常会通过代码处理让 ...
- IntervalZero RTX 2014
2692407267@qq.com,很多其它内容请关注http://user.qzone.qq.com/2692407267 IntervalZero RTX 2014 上图 watermark/ ...