原生的solr中有/get 的request handler实现(org.apache.solr.handler.component.RealTimeGetComponent),实现原理是,先到tlog的内存中去找记录,找不到再到indexSearch中去找。这样当用户利用solrj客户端提交到solr服务端之后,可以不需要等待服务端softcommit,就能立即从服务端中取得最新提交的记录信息。
这样可以避免数据脏写的问题,但是,collection的索引结构使用Nested Document,客户端提交一个Nested Document 记录之后,再使用solrj调用“getById”方法,只能返回parent document了。因为这个原因,在生产环境中,对同一条记录的两次业务操作时间间隔比soft commit的时间周期短,就会产生数据脏写的问题。
要解决这个问题,需要扩展solr的SearchComponent,实现通过Id,可以将文档的子文档(child docuemnt)全部加载。
import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.util.BytesRefBuilder; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.params.SolrParams; import org.apache.solr.core.SolrCore; import org.apache.solr.handler.component.RealTimeGetComponent; import org.apache.solr.handler.component.ResponseBuilder; import org.apache.solr.handler.component.SearchComponent; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.BasicResultContext; import org.apache.solr.response.ResultContext; import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.response.transform.DocTransformer; import org.apache.solr.schema.FieldType; import org.apache.solr.schema.IndexSchema; import org.apache.solr.schema.SchemaField; import org.apache.solr.search.ReturnFields; import org.apache.solr.search.SolrIndexSearcher; import org.apache.solr.search.SolrReturnFields; import org.apache.solr.util.RefCounted; public class NestRealtimeGetComponet extends SearchComponent { public static final String COMPONENT_NAME = "nestget"; @Override public void prepare(ResponseBuilder rb) throws IOException { SolrQueryRequest req = rb.req; SolrQueryResponse rsp = rb.rsp; SolrParams params = req.getParams(); if (!params.getBool(COMPONENT_NAME, false)) { return; } // Set field flags ReturnFields returnFields = new SolrReturnFields(rb.req); rb.rsp.setReturnFields(returnFields); } @Override public void process(ResponseBuilder rb) throws IOException { SolrQueryRequest req = rb.req; SolrQueryResponse rsp = rb.rsp; SolrParams params = req.getParams(); if (!params.getBool(COMPONENT_NAME, false)) { return; } String id = params.get("id"); SchemaField idField = req.getSchema().getUniqueKeyField(); FieldType fieldType = idField.getType(); BytesRefBuilder idBytes = new BytesRefBuilder(); fieldType.readableToIndexed(id, idBytes); SolrCore core = req.getCore(); SolrInputDocument doc = RealTimeGetComponent.getInputDocumentFromTlog( core, idBytes.get()); SolrDocumentList docList = new SolrDocumentList(); if (doc != null) { docList.add(convertDocument(doc)); docList.setNumFound(1); } else { RefCounted<SolrIndexSearcher> searchHolder = req.getCore() .getSearcher(); SolrIndexSearcher searcher = searchHolder.get(); // 取得transfer DocTransformer transformer = rsp.getReturnFields().getTransformer(); if (transformer != null) { ResultContext context = new BasicResultContext(null, rsp.getReturnFields(), null, null, req); transformer.setContext(context); } try { int docid = -1; long segAndId = searcher.lookupId(idBytes.get()); if (segAndId >= 0) { int segid = (int) segAndId; LeafReaderContext ctx = searcher.getTopReaderContext() .leaves().get((int) (segAndId >> 32)); docid = segid + ctx.docBase; } if (docid >= 0) { Document luceneDocument = searcher.doc(docid, rsp .getReturnFields().getLuceneFieldNames()); SolrDocument d = toSolrDoc(luceneDocument, core.getLatestSchema()); searcher.decorateDocValueFields(d, docid, searcher.getNonStoredDVs(true)); if (transformer != null) { transformer.transform(d, docid, 0); } docList.add(d); docList.setNumFound(1); } } finally { searchHolder.decref(); } } rb.rsp.addResponse(docList); } private static SolrDocument toSolrDoc(Document doc, IndexSchema schema) { SolrDocument out = new SolrDocument(); for (IndexableField f : doc.getFields()) { // Make sure multivalued fields are represented as lists Object existing = out.get(f.name()); if (existing == null) { SchemaField sf = schema.getFieldOrNull(f.name()); // don't return copyField targets if (sf != null && schema.isCopyFieldTarget(sf)) continue; if (sf != null && sf.multiValued()) { List<Object> vals = new ArrayList<>(); vals.add(f); out.setField(f.name(), vals); } else { out.setField(f.name(), f); } } else { out.addField(f.name(), f); } } return out; } protected SolrDocument convertDocument(SolrInputDocument doc) { SolrDocument sdoc = new SolrDocument(); for (String k : doc.getFieldNames()) { sdoc.setField(k, doc.getFieldValue(k)); } if (doc.hasChildDocuments()) { for (SolrInputDocument s : doc.getChildDocuments()) { sdoc.addChildDocument(convertDocument(s)); } } return sdoc; } }
solrconfig.xml中的配置:
<searchComponent name="nestget" class="com.dfire.tis.solrextend.handler.component.NestRealtimeGetComponet" /> requestHandler name="/select" class="solr.SearchHandler"> <lst name="defaults"> <str name="echoParams">explicit</str> <int name="rows">10</int> <str name="df">text</str> </lst> <arr name="last-components"> <str>nestget</str> </arr> </requestHandler>
客户端查询示例:
SolrQuery query = new SolrQuery(); query.setParam("nestget", true); query.set("id", pid); query.setQuery("id:0"); query.setFields("*", "[child parentFilter=type:p childFilter=\"{!terms f=id}" + cid + "\" limit=100]"); QueryResponse r = this.client.query(collection, pid, query); SolrDocumentList doclist = r.getResults(); for (SolrDocument d : doclist) { System.out.println(d.get("id")); System.out.println(); if (d.getChildDocumentCount() > 0) { for (SolrDocument c : d.getChildDocuments()) { StringBuffer f = new StringBuffer(); for (String key : c.getFieldNames()) { f.append(key).append(":").append(c.getFirstValue(key)); } System.out.println(f.toString()); } } }
相关推荐
基于Nested Logit模型的出行路线方式选择和时间价值计算,宗芳,祁文田,本文介绍了Nested Logit模型的效用最大化理论、选择树的建立以及其概率表达式;时间价值的基本计算公式。对人们由长春到吉林的出行路
基于Nested Logit的电动汽车分时租赁选择行为分析.pdf
嵌套阵列DOA估计matlab例程,基于Nested Arrays A Novel Approach to Array Processing With Enhanced Degrees of Freedom。
这里是Spring的一个Nested事务的代码及数据库文件,因为NESTED资源很少,这里作出了一个通俗易懂的 让需要者下载。
Weblogic9异常解决nested errors.txtWeblogic9异常解决nested errors.txtWeblogic9异常解决nested errors.txtWeblogic9异常解决nested errors.txtWeblogic9异常解决nested errors.txt
基于粒子群算法(Nested PSO)的电力系统经济调度,matlab平台 solve power system economic dispatch problem by Nested PSO algorithm.
learn_drf_nested_resources 介绍 创建该项目的目的是提供一个完整的示例,该示例说明如何使用在API上实现嵌套资源。 为了使项目尽可能真实,使用处理身份验证。 应用程序 该应用程序公开了一个用于管理博客文章和...
Laravel开发-laravel-nested 向雄辩模型添加嵌套集验证
java解决nested exception is java.lang.OutOfMemoryError Java heap space 解决OOM
java解决Handler processing failed; nested exception is java.lang.NoClassDefFoundError
1、基于springboot+mybatis实现的外卖订餐系统源码+项目说明(毕设).zip 2、该资源包括项目的全部源码,下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为...
内容概要:本电商系统主要使用ASP.NET技术+BootStrap前端框架+SQLServer数据库,通过对该系统的设计,简化代码实现过程,保留核心功能,可以在实践过程中掌握ASP.NET技术的部分使用方法,如对三层架构开发模式的熟悉...
Laravel开发-eloquent-nested-attributes 嵌套属性允许您通过父级保存关联记录的属性。默认情况下,嵌套属性更新被关闭,您可以使用$nested属性启用它。启用嵌套属性时,将在模型上定义属性编写器。
嵌套套 Go Nested Set是的实现。 该项目是的Go版本,它使用相同的数据结构设计,因此它与一起使用相同的数据。 实际上,原始设计就是为此而设计的,由我们的Rails应用程序中的管理的内容,还需要维护前端Go API。 这...
We develop a new edge detection algorithm, holistically-nested edge detection (HED), which performs image-to-image prediction by means of a deep learning model that leverages fully convolutional ...
as_nested_set:数据库的基于ecto的嵌套集实现
NULL 博文链接:https://ivan-yan.iteye.com/blog/1007671
Nested VM execution: new direction for KVM.
Laravel开发-laravel-nestedset Laravel的嵌套集模型
NEVE:基于ARM架构的嵌套虚拟化扩展 随着ARM服务器在云基础设施部署中的不断深入,在ARM上支持嵌套虚拟化是近年来随着ARM体系结构引入嵌套虚拟化支持而出现的一个关键因素。