Solr Update插件自定义Update Chain按条件更新索引
背景:基于call客,来电和跟进记录等多个数据来源的用户文档,需要在更新是判断首来源的时间。
如对电话号码11xxxx来说,来电时间是今天,call客时间是昨天,而call客数据又可能因为网络原因晚上传上来,这样一来11xxxx这个用户document的来源时间需要更新成昨天。
分析:solr的默认update没有办法匹配业务的灵活的更新逻辑。更新逻辑如下,当更新来源时间的时候,如果新的来源时间比之前的来源时间晚,则保持之前的来源时间。
代码实现:
package custom.solr;
import java.io.IOException;
import org.apache.lucene.util.BytesRef;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.core.SolrCore;
import org.apache.solr.handler.component.RealTimeGetComponent;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.update.AddUpdateCommand;
import org.apache.solr.update.processor.UpdateRequestProcessor;
import org.apache.solr.update.processor.UpdateRequestProcessorFactory;
import org.apache.solr.util.RefCounted; public class ConditionUpdateProcessFactory extends UpdateRequestProcessorFactory
{
@Override
public UpdateRequestProcessor getInstance(SolrQueryRequest req, SolrQueryResponse rsp, UpdateRequestProcessor next)
{
return new ConditionalUpdateProcessor(req, rsp, next);
}
} class ConditionalUpdateProcessor extends UpdateRequestProcessor
{
public static final String ORIGIN_TIMESTAMP = "origin_timestamp";
public ConditionalUpdateProcessor(SolrQueryRequest req, SolrQueryResponse rsp, UpdateRequestProcessor next)
{
super(next);
core = req.getCore();
} private final SolrCore core; @Override
public void processAdd(AddUpdateCommand cmd) throws IOException
{
SolrInputDocument newDoc = cmd.getSolrInputDocument();
BytesRef indexedId = cmd.getIndexedId();
RefCounted<SolrIndexSearcher> newestSearcher = core.getRealtimeSearcher();
SolrIndexSearcher searcher;
long lookup;
searcher = (SolrIndexSearcher) newestSearcher.get();
lookup = searcher.lookupId(indexedId);
//if not exists
if (lookup < 0)
{super.processAdd(cmd);
}
SolrInputDocument oldDoc = RealTimeGetComponent.getInputDocument(core, indexedId);
Object newOriginTimestamp = newDoc.getFieldValue(ORIGIN_TIMESTAMP);
Object oldOriginTimestamp = oldDoc.getFieldValue(ORIGIN_TIMESTAMP);
if (newOriginTimestamp != null && oldOriginTimestamp != null)
{
if (Long.valueOf(oldOriginTimestamp.toString()) < Long.valueOf(newOriginTimestamp.toString()))
{
newDoc.setField(ORIGIN_TIMESTAMP, oldOriginTimestamp);
}
}
// pass it up the chain
super.processAdd(cmd);
} }
1.将该类编译后生成jar包放到 /var/lib/solr/plugins目录下,或者你任意指定一个目录。
2.配置solrconfig.xml加载该jar包。(注意修改jar包或者solrconfig.xml之后要reload collection)
<lib dir="/var/lib/solr/plugins" />
3.配置solrconfig.xml的默认update用哪个chain名字。
<requestHandler name="/update" class="solr.UpdateRequestHandler">
<!-- See below for information on defining
updateRequestProcessorChains that can be used by name
on each Update Request
-->
<lst name="defaults">
<str name="update.chain">condition</str>
</lst>
</requestHandler>
以及solrconfig.xml chain的流程。
<updateRequestProcessorChain name="condition">
<processor class="solr.LogUpdateProcessorFactory" />
<processor class="solr.DistributedUpdateProcessorFactory" />
<processor class="custom.solr.ConditionUpdateProcessFactory" />
<processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>
*关于为什么放在DistibutedUpdateProcessFactory之后。
https://wiki.apache.org/solr/Atomic_Updates
2017.01.12优化:
如下场景时,上面代码会出现问题:
老的数据没有立即commit,还保存在TLog中,此时RealTimeGetComponet.getInputDocument方法获取不到老数据,导致处理逻辑不符合期望,来源时间不正确。
代码优化如下:
SolrInputDocument oldDoc = RealTimeGetComponent.getInputDocumentFromTlog(core, indexedId);
if (oldDoc == null)
{
oldDoc = RealTimeGetComponent.getInputDocument(core, indexedId);
}
Solr Update插件自定义Update Chain按条件更新索引的更多相关文章
- [jQuery]jQuery DataTables插件自定义Ajax分页实现
前言 昨天在博客园的博问上帮一位园友解决了一个问题,我觉得有必要记录一下,万一有人也遇上了呢. 问题描述 园友是做前端的,产品经理要求他使用jQuery DataTables插件显示一个列表,要实现分 ...
- 【JAVA】FOR UPDATE 和 FOR UPDATE NOWAIT 区别 (转)
1.for update 和 for update nowait 的区别:首先一点,如果只是select 的话,Oracle是不会加任何锁的,也就是Oracle对 select 读到的数据不会有任何限 ...
- [转]oracle for update和for update nowait的区别
1概念小结:(针对以下引用区域内容) 1.1 普通select语句不加锁. 1.2 for update和for update nowait都试图将符合条件的数据加上行级锁.用于排斥其他针对这个表的写 ...
- Oracle 中 for update 和 for update nowait 的区别
原文出处http://bijian1013.iteye.com/blog/1895412 一.for update 和 for update nowait 的区别 首先一点,如果只是select 的话 ...
- oracle for update和for update nowait
原文地址:http://www.cnblogs.com/quanweiru/archive/2012/11/09/2762223.html 1.for update 和 for update nowa ...
- sql: oracle, for update和for update nowait的区别
1. oracle for update和for update nowait的区别 http://www.cnblogs.com/quanweiru/archive/2012/11/09/276222 ...
- oracle for update和for update nowait(for update wait)的区别
1.for update 和 for update nowait 的区别: 1.oracle 中执行select 操作读取数据不会有任何限制,当另外一个进程在修改表中的数据,但是并没有commit,所 ...
- oracle for update和for update nowait的区别 - 转
1.for update 和 for update nowait 的区别: 首先一点,如果只是select 的话,Oracle是不会加任何锁的,也就是Oracle对 select 读到的数据不会有任何 ...
- oracle for update和for update nowait 的区别
原文地址:http://www.cnblogs.com/quanweiru/archive/2012/11/09/2762223.html 1.for update 和 for update nowa ...
随机推荐
- C#获取本机Sql Serverserver名
private void Form2_Load(object sender, EventArgs e) { listBox1.Items.Clear(); SQLDMO.Application SQL ...
- 使用powershell来设置时间
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/set-date?view=powers ...
- tflearn中num_epoch含义就是针对所有样本的一次迭代
In tensorflow get started code: import tensorflow as tf import numpy as np features = [tf.contrib.la ...
- scws
SCWS 是 Simple Chinese Word Segmentation 的首字母缩写(即:简易中文分词系统). 这是一套基于词频词典的机械式中文分词引擎,它能将一整段的中文文本基本正确地切分成 ...
- Oracle 字符拼接
使用的是ORACLE中的cast函数: 官方链接: https://docs.oracle.com/cd/E11882_01/server.112/e41084/functions023.htm#SQ ...
- 多线程通信(wait/notify)
线程通信概念:线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体的必用方式之一.当线程存在通信指挥,系统间的交互性会更强大,在提高CPU利用率的同时就 ...
- C - Between the Offices
Problem description As you may know, MemSQL has American offices in both San Francisco and Seattle. ...
- ListView(2)最简单的上拉刷新、下拉刷新代码
效果 最简单的上拉刷新和下拉刷新,当listview滚动到底部时向上拉刷新数据.当listview滚动到最顶部时下拉刷新. 图1,上拉刷新 图2,下拉刷新 1.设置lisview 加载he ...
- jQuery 对象转成 DOM 对象
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- Run as ant build每次都执行两次-问题解决
在Eclipse里面,运行ant,整个测试流程总是执行两遍,其几天试了下在DOS命令行直接调用ant, 结果发现只执行了一次,并且内存消耗好像也没那么大了,估计是eclipse自己的问题.问题解决了, ...