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 ...
随机推荐
- IE8-模拟script onerror
利用VBScript 检测,有副作用,慎用! var loadScript = function () { var DOC = document, HEAD = document.getElement ...
- ilog
PCISV7-VHL [2015-11-13 13:51:36,038]>>>INFO>>>[ com.isoftstone.pcis.policy.app.pla ...
- java进程状态
A thread state. A thread can be in one of the following states: NEWA thread that has not yet started ...
- linux which 查看可执行文件的位置
我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索: which 查看可执行文件的位置. whereis 查看文件的位置. ...
- [转]Torch是什么?
Torch是一个广泛支持机器学习算法的科学计算框架.易于使用且高效,主要得益于一个简单的和快速的脚本语言LuaJIT,和底层的C / CUDA实现:Torch | Github 核心特征的总结:1. ...
- KVM 虚拟机命令行安装配置
KVM作为linux内核的一部分,有着无法比拟的优势,相信KVM的大范围企业应用指日可待. 一.KVM宿主服务器环境配置 1. 查看CPU是否支持VT技术 cat /proc/cpuinfo | eg ...
- Windows操作系统单文件夹下到底能存放多少文件及单文件的最大容量
本文是转自:http://hi.baidu.com/aqgjoypubihoqxr/item/c896921f8c2eaba5feded5f2 最近需要了解Windows中单个文件夹下 ...
- Mysql用户密码设置修改和权限分配
我的mysql安装在c:\mysql 一.更改密码 第一种方式: 1.更改之前root没有密码的情况 c:\mysql\bin>mysqladmin -u root password " ...
- Python int与string之间的转化
string-->int 1.10进制string转化为int int('12') 2.16进制string转化为int int('12', 16) int-->string 1.int转 ...
- 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配
垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己 ...