solr索引操作(包括新增 更新 删除 提交 合并等)相关UML图如下

从上面的类图我们可以发现,其中体现了工厂方法模式及责任链模式的运用

UpdateRequestProcessor相当于责任链模式中的处理器角色,我们通过如下的对象图也许更能反映多个UpdateRequestProcessor类型的处理器的活动行为

UpdateRequestProcessorChain为请求处理器链,供客户端调用(内部依赖处理器工厂数组生成不同的处理器)

public final class UpdateRequestProcessorChain implements PluginInfoInitialized
{
private UpdateRequestProcessorFactory[] chain;
private final SolrCore solrCore; public UpdateRequestProcessorChain(SolrCore solrCore) {
this.solrCore = solrCore;
} public void init(PluginInfo info) {
List<UpdateRequestProcessorFactory> list = solrCore.initPlugins(info.getChildren("processor"),UpdateRequestProcessorFactory.class,null);
if(list.isEmpty()){
throw new RuntimeException( "updateRequestProcessorChain require at least one processor");
}
chain = list.toArray(new UpdateRequestProcessorFactory[list.size()]);
} public UpdateRequestProcessorChain( UpdateRequestProcessorFactory[] chain , SolrCore solrCore) {
this.chain = chain;
this.solrCore = solrCore;
} public UpdateRequestProcessor createProcessor(SolrQueryRequest req, SolrQueryResponse rsp)
{
UpdateRequestProcessor processor = null;
UpdateRequestProcessor last = null;
for (int i = chain.length-1; i>=0; i--) {
processor = chain[i].getInstance(req, rsp, last);
last = processor == null ? last : processor;
}
return last;
} public UpdateRequestProcessorFactory[] getFactories() {
return chain;
}
}

UpdateRequestProcessorFactory为请求处理器抽象工厂类,用于实例化请求处理器(UpdateRequestProcessor),而具体的实例化过程延迟到子类实现

/**
* A factory to generate an UpdateRequestProcessor for each request.
*
* If the factory needs access to {@link SolrCore} in initialization, it could
* implement {@link SolrCoreAware}
*
* @since solr 1.3
*/
public abstract class UpdateRequestProcessorFactory implements NamedListInitializedPlugin
{
public void init( NamedList args )
{
// could process the Node
} abstract public UpdateRequestProcessor getInstance(
SolrQueryRequest req, SolrQueryResponse rsp, UpdateRequestProcessor next );
}

请求处理器抽象类UpdateRequestProcessor,持有对自身类型的引用(责任链模式的体现)

/**
* This is a good place for subclassed update handlers to process the document before it is
* indexed. You may wish to add/remove fields or check if the requested user is allowed to
* update the given document...
*
* Perhaps you continue adding an error message (without indexing the document)...
* perhaps you throw an error and halt indexing (remove anything already indexed??)
*
* By default, this just passes the request to the next processor in the chain.
*
* @since solr 1.3
*/
public abstract class UpdateRequestProcessor {
protected final Logger log = LoggerFactory.getLogger(getClass()); protected final UpdateRequestProcessor next; public UpdateRequestProcessor( UpdateRequestProcessor next) {
this.next = next;
} public void processAdd(AddUpdateCommand cmd) throws IOException {
if (next != null) next.processAdd(cmd);
} public void processDelete(DeleteUpdateCommand cmd) throws IOException {
if (next != null) next.processDelete(cmd);
} public void processMergeIndexes(MergeIndexesCommand cmd) throws IOException {
if (next != null) next.processMergeIndexes(cmd);
} public void processCommit(CommitUpdateCommand cmd) throws IOException
{
if (next != null) next.processCommit(cmd);
} /**
* @since Solr 1.4
*/
public void processRollback(RollbackUpdateCommand cmd) throws IOException
{
if (next != null) next.processRollback(cmd);
} public void finish() throws IOException {
if (next != null) next.finish();
}
}

具体工厂类RunUpdateProcessorFactory及具体请求处理器RunUpdateProcessor

/**
* Pass the command to the UpdateHandler without any modifications
*
* @since solr 1.3
*/
public class RunUpdateProcessorFactory extends UpdateRequestProcessorFactory
{
@Override
public UpdateRequestProcessor getInstance(SolrQueryRequest req, SolrQueryResponse rsp, UpdateRequestProcessor next)
{
return new RunUpdateProcessor(req, next);
}
} class RunUpdateProcessor extends UpdateRequestProcessor
{
private final SolrQueryRequest req;
private final UpdateHandler updateHandler; public RunUpdateProcessor(SolrQueryRequest req, UpdateRequestProcessor next) {
super( next );
this.req = req;
this.updateHandler = req.getCore().getUpdateHandler();
} @Override
public void processAdd(AddUpdateCommand cmd) throws IOException {
cmd.doc = DocumentBuilder.toDocument(cmd.getSolrInputDocument(), req.getSchema());
updateHandler.addDoc(cmd);
super.processAdd(cmd);
} @Override
public void processDelete(DeleteUpdateCommand cmd) throws IOException {
if( cmd.id != null ) {
updateHandler.delete(cmd);
}
else {
updateHandler.deleteByQuery(cmd);
}
super.processDelete(cmd);
} @Override
public void processMergeIndexes(MergeIndexesCommand cmd) throws IOException {
updateHandler.mergeIndexes(cmd);
super.processMergeIndexes(cmd);
} @Override
public void processCommit(CommitUpdateCommand cmd) throws IOException
{
updateHandler.commit(cmd);
super.processCommit(cmd);
} /**
* @since Solr 1.4
*/
@Override
public void processRollback(RollbackUpdateCommand cmd) throws IOException
{
updateHandler.rollback(cmd);
super.processRollback(cmd);
}
}

命令参数

/** An index update command encapsulated in an object (Command pattern)
*
* @version $Id: UpdateCommand.java 1065312 2011-01-30 16:08:25Z rmuir $
*/
public class UpdateCommand {
protected String commandName; public UpdateCommand(String commandName) {
this.commandName = commandName;
} @Override
public String toString() {
return commandName;
}
}

AddUpdateCommand命令

/**
* @version $Id: AddUpdateCommand.java 1145201 2011-07-11 15:18:47Z yonik $
*/
public class AddUpdateCommand extends UpdateCommand {
// optional id in "internal" indexed form... if it is needed and not supplied,
// it will be obtained from the doc.
public String indexedId; // The Lucene document to be indexed
public Document doc; // Higher level SolrInputDocument, normally used to construct the Lucene Document
// to index.
public SolrInputDocument solrDoc; public boolean allowDups;
public boolean overwritePending;
public boolean overwriteCommitted; public Term updateTerm;
public int commitWithin = -1; /** Reset state to reuse this object with a different document in the same request */
public void clear() {
doc = null;
solrDoc = null;
indexedId = null;
} public SolrInputDocument getSolrInputDocument() {
return solrDoc;
} public Document getLuceneDocument(IndexSchema schema) {
if (doc == null && solrDoc != null) {
// TODO?? build the doc from the SolrDocument?
}
return doc;
} public String getIndexedId(IndexSchema schema) {
if (indexedId == null) {
SchemaField sf = schema.getUniqueKeyField();
if (sf != null) {
if (doc != null) {
schema.getUniqueKeyField();
Fieldable storedId = doc.getFieldable(sf.getName());
indexedId = sf.getType().storedToIndexed(storedId);
}
if (solrDoc != null) {
SolrInputField field = solrDoc.getField(sf.getName());
if (field != null) {
indexedId = sf.getType().toInternal( field.getFirstValue().toString() );
}
}
}
}
return indexedId;
} public String getPrintableId(IndexSchema schema) {
SchemaField sf = schema.getUniqueKeyField();
if (indexedId != null && sf != null) {
return sf.getType().indexedToReadable(indexedId);
} if (doc != null) {
return schema.printableUniqueKey(doc);
} if (solrDoc != null && sf != null) {
SolrInputField field = solrDoc.getField(sf.getName());
if (field != null) {
return field.getFirstValue().toString();
}
}
return "(null)";
} public AddUpdateCommand() {
super("add");
} @Override
public String toString() {
StringBuilder sb = new StringBuilder(commandName);
sb.append(':');
if (indexedId !=null) sb.append("id=").append(indexedId);
sb.append(",allowDups=").append(allowDups);
sb.append(",overwritePending=").append(overwritePending);
sb.append(",overwriteCommitted=").append(overwriteCommitted);
return sb.toString();
}
}

DeleteUpdateCommand命令

/**
* @version $Id: DeleteUpdateCommand.java 1235304 2012-01-24 15:39:17Z janhoy $
*/
public class DeleteUpdateCommand extends UpdateCommand {
public String id; // external (printable) id, for delete-by-id
public String query; // query string for delete-by-query
public boolean fromPending;
public boolean fromCommitted;
public int commitWithin = -1; public DeleteUpdateCommand() {
super("delete");
} @Override
public String toString() {
StringBuilder sb = new StringBuilder(commandName);
sb.append(':');
if (id!=null) sb.append("id=").append(id);
else sb.append("query=`").append(query).append('`');
sb.append(",fromPending=").append(fromPending);
sb.append(",fromCommitted=").append(fromCommitted);
sb.append(",commitWithin=").append(commitWithin);
return sb.toString();
}
}

---------------------------------------------------------------------------

本系列solr&lucene3.6.0源码解析系本人原创

转载请注明出处 博客园 刺猬的温驯

本人邮箱: chenying998179#163.com (#改为@)

本文链接http://www.cnblogs.com/chenying99/p/3501172.html

solr&lucene3.6.0源码解析(三)的更多相关文章

  1. solr&lucene3.6.0源码解析(四)

    本文要描述的是solr的查询插件,该查询插件目的用于生成Lucene的查询Query,类似于查询条件表达式,与solr查询插件相关UML类图如下: 如果我们强行将上面的类图纳入某种设计模式语言的话,本 ...

  2. solr&lucene3.6.0源码解析(二)

    上文描述了solr3.6.0怎么采用maven管理的方式在eclipse中搭建开发环境,在solr中,为了提高搜索性能,采用了缓存机制,这里描述的是LRU缓存,这里用到了 LinkedHashMap类 ...

  3. solr&lucene3.6.0源码解析(一)

      本文作为系列的第一篇,主要描述的是solr3.6.0开发环境的搭建   首先我们需要从官方网站下载solr的相关文件,下载地址为http://archive.apache.org/dist/luc ...

  4. AFNetworking2.0源码解析<三>

    本篇说说安全相关的AFSecurityPolicy模块,AFSecurityPolicy用于验证HTTPS请求的证书,先来看看HTTPS的原理和证书相关的几个问题. HTTPS HTTPS连接建立过程 ...

  5. AFNetworking (3.1.0) 源码解析 <三>

    今天要介绍的是Reachability文件夹下的AFNetworkReachabilityManager类.通过字面意思我们就可以知道AFNetworkReachabilityManager是用来监测 ...

  6. Heritrix 3.1.0 源码解析(三十七)

    今天有兴趣重新看了一下heritrix3.1.0系统里面的线程池源码,heritrix系统没有采用java的cocurrency包里面的并发框架,而是采用了线程组ThreadGroup类来实现线程池的 ...

  7. Celery 源码解析三: Task 对象的实现

    Task 的实现在 Celery 中你会发现有两处,一处位于 celery/app/task.py,这是第一个:第二个位于 celery/task/base.py 中,这是第二个.他们之间是有关系的, ...

  8. Android事件总线(二)EventBus3.0源码解析

    1.构造函数 当我们要调用EventBus的功能时,比如注册或者发送事件,总会调用EventBus.getDefault()来获取EventBus实例: public static EventBus ...

  9. apache mina2.0源码解析(一)

    apache mina是一个基于java nio的网络通信框架,为TCP UDP ARP等协议提供了一致的编程模型:其源码结构展示了优秀的设计案例,可以为我们的编程事业提供参考. 依照惯例,首先搭建a ...

随机推荐

  1. less预处理的好处,补充关于之前发表的rem单位的运用于计算

    我认识的less 优点:优雅,好用,简单,可复用性强, 缺点:less并其实不能为我们减少沉余css代码,还是要靠自己的CSS基础去判断哪些是沉余代码或者是可以合并的代码 之前发表的一篇文章一看就懂得 ...

  2. 在easyui中如何修改combobox的下拉框的高度为自适应高度

    在easyui中,有时候easyui下拉框的高度比较高,如果我们的值比较少,而下拉框的高度很高的话看起来不好看,修改前效果如下所示: 要修改下拉框的高度和我们的值自适应的 话,只要添加一个panelH ...

  3. 09-JAVA中的异常处理

    1. 程序执行结果: 也就是它根本就没抛出异常,更别提捕获异常了.那么,为什么会这样呢? 原来, 如上面程序展示,程序运行到k=i/j;的时候,就会直接终止,根本就不会运行到监视的程序,更不会运行到捕 ...

  4. Java浮点数float,bigdecimal和double精确计算的精度误差问题总结

    (转)Java浮点数float,bigdecimal和double精确计算的精度误差问题总结 1.float整数计算误差 案例:会员积分字段采用float类型,导致计算会员积分时,7位整数的数据计算结 ...

  5. php中ajax调用出错的问题

    最近用一些php,客户的使用jquery ajax的时候经常报错 ajax报错内容:readyState:4 status:"OK",statusText:"OK&quo ...

  6. 解决mac升级后,出现的 xcrun: error: invalid active developer path, missing xcrun 错误

    最近升级了mac系统,然后接着写代码就出问题了. 报错信息如下: xcrun: error: invalid active developer path (/Library/Developer/Com ...

  7. 第二章 Mybatis代码生成工具

    1.mybatis-generator作用 1).生成pojo 与 数据库结构对应 2).如果有主键,能匹配主键 3).如果没有主键,可以用其他字段去匹配 4).动态select,update,del ...

  8. 【Leetcode-Mysql】Trips and Users

    思路不总结了,看过题目自己尝试过之后,看下方代码应该能理解的 SELECT Request_at AS DAY, round( sum( CASE WHEN STATUS = 'completed' ...

  9. 摘记 pyinstaller 使用自定义 spec

    下面的是官网的文档, 我们可以用自定义spec的方式把想要的文件打包到目标文件夹里面 例如: 我们在程序中用了一个图标 test.ico, 如果我们只用 pyinstaller -w test.py ...

  10. 03-Swift常量&变量

    什么是常量和变量 在Swift中规定:在定义一个标识符时必须明确说明该标识符是一个常量还是变量 使用let来定义常量,定义之后不可以修改 使用var来定义变量,定义之后可以修改 常量和变量的基本使用 ...