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的更多相关文章

  1. 五、SolrJ、Request Handler

    什么是SolrJ 既然Solr是以单独的WebApp形式存在的,那么Solr理应提供与Solr通信的Api吧,对的,这就是SolrJ,既然与solr通信是通过url,那么其实我们也可以不用SolrJ, ...

  2. solrj-solr Guide 4.7

    solrj是一个很容易使java应用程序和solr进行交互的一个API,solrj隐藏了很多连接Solr的细节,允许你的应用程序使用简单的高级方法和solr互动交流. solrj的核心就是 org.a ...

  3. Solr JAVA客户端SolrJ 4.9使用示例教程

    http://my.oschina.net/cloudcoder/blog/305024 简介 SolrJ是操作Solr的JAVA客户端,它提供了增加.修改.删除.查询Solr索引的JAVA接口.So ...

  4. [solr] - SolrJ增删查

    使用SolrJ进行对Solr的增.删.查功能. 参考引用: http://wiki.apache.org/solr/Solrj Eclipse中新建一个项目:TestSolr 其中SorlJ的Lib包 ...

  5. 【Solr专题之九】SolrJ教程

    一.SolrJ基础 1.相关资料 API:http://lucene.apache.org/solr/4_9_0/solr-solrj/ apache_solr_ref_guide_4.9.pdf:C ...

  6. Solr Wiki文档

    相比ElasticSearch,Solr的文档详尽丰富,同时也显得冗余啰嗦. Solr的官方文档有两个地方: Solr官方教程 Solr社区维基 本文主要列出一些Solr Wiki中的主要讨论主题,方 ...

  7. Solr系列四:Solr(solrj 、索引API 、 结构化数据导入)

    一.SolrJ介绍 1. SolrJ是什么? Solr提供的用于JAVA应用中访问solr服务API的客户端jar.在我们的应用中引入solrj: <dependency> <gro ...

  8. SolrJ API 官方文档最佳实践

    以下内容译自Solr Wiki官方文档,版权没有,随意转载. Solrj 是一个访问solr的Java客户端.它提供了一个java接口用于添加更新和查询solr索引.本页面介绍SolrJ最新版本1.4 ...

  9. JAVAEE——Solr:安装及配置、后台管理索引库、 使用SolrJ管理索引库、仿京东的电商搜索案例实现

    1 学习回顾 1. Lucene  是Apache开源的全文检索的工具包 创建索引 查询索引 2. 遇到问题? 文件名 及文件内容  顺序扫描法  全文检索 3. 什么是全文检索? 这种先创建索引 再 ...

  10. SOLR企业搜索平台 三 (schema.xml配置和solrj的使用)

    标签:solrj 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://3961409.blog.51cto.com/3951409/8 ...

随机推荐

  1. Java(07)转化流

    查看API得知: public class OutputStreamWriter extends Writer public class InputStreamReader extends Reade ...

  2. UVa11997K Smallest Sums(优先队列)

    K Smallest Sums You're given k arrays, each array has k integers. There are kk ways to pick exactly ...

  3. NSInvocation Basics

    In this article I'm going to cover the basics and usages of NSInvocation. What is NSInvocation? Appl ...

  4. Android PHP 通过JSON进行数据交互

    一.首先是Android客户端解析PHP返回的JSON数据 1.PHP代码(这里用到了数据库,如果没有准备数据库的话,可以自定义字符串) <?php $link=mysql_connect(SA ...

  5. 图片懒加载 lazyload

    添加引用 <script type="text/javascript" src="lazyload/yahoo-dom-event.js">< ...

  6. TemplateBinding vs TemplatedParent【PluraSight】

    TemplateBinding:TemplateBinding是一个Markup Extension

  7. STL容器set()--->自定义数据类型

    set容器中不能插入重复的元素,需要其插入的元素有比较大小(<).相等(==) 的逻辑判断,这是因为set中的元素是有序排列, 默认从小到大排列 std::set<type,std::le ...

  8. 史上最全APP推广渠道

    群主做App推广的过程中,有过失败也尝过成功的甜头,渐渐地在APP推广尤其是渠道推广中积累了一些实战经验想同大家分享.如果各位有更好的推广建议,欢迎沟通分享哦!   一.应用商店推广   1.应用市场 ...

  9. C++的优秀特性1:引用

    (转载请注明原创于潘多拉盒子) 一本典型的C语言教科书的厚度大约是200页左右,而一本典型的C++教科书的厚度至少要500页.比如K&R的<The C Programming Langu ...

  10. Linq 学习

    聚合操作符                                                                                              说 ...