Join 多层次连接解决方案
嗨,我有一个三级树结构的数据。当用户搜索第三级节点时,我可以使用SOlr JOIN获取根节点吗 例如—Join 多层次连接解决方案,join,solr,Join,Solr,嗨,我有一个三级树结构的数据。当用户搜索第三级节点时,我可以使用SOlr JOIN获取根节点吗 例如— PATIENT1 -> FirstName1 -> LastName1 -> DOCUMENTS1_1 -> document_type1_1 -> document_description1_1 -> document_value1_1
PATIENT1
-> FirstName1
-> LastName1
-> DOCUMENTS1_1
-> document_type1_1
-> document_description1_1
-> document_value1_1
-> CODE_ITEMS1_1_1
-> Code_id1_1_1
-> code1_1_1
-> CODE_ITEMS1_1_1
-> Code_id1_1_2
-> code1_1_2
-> DOCUMENTS1_2
-> document_type1_2
-> document_description1_2
-> document_value1_2
-> CODE_ITEMS1_2_1
-> Code_id1_2_1
-> code1_2_1
-> CODE_ITEMS1_2_2
-> Code_id1_2_2
-> code1_2_2
PATIENT2
-> FirstName2
-> LastName2
-> DOCUMENTS2_1
-> document_type2_1
-> document_description2_1
-> document_value2_1
-> CODE_ITEMS2_1_1
-> Code_id2_1_1
-> code2_1_1
-> CODE_ITEMS2_1_2
-> Code_id2_1_2
-> code2_1_2
我要搜索代码项并返回与代码项搜索条件匹配的所有患者。如何做到这一点。是否可以实现两次联接。第一个联接提供代码项搜索的所有文档,下一个联接提供所有患者
类似于SQL查询-
select * from patients where docID (select DOCID from DOCUMENTS where CODEID IN (select CODEID from CODE_ITEMS where CODE LIKE '%SEARCH_TEXT%'))
我真的不知道内部Solr连接是如何工作的,但知道RDB多个连接在大型数据集上效率极低,我可能最终会编写自己的连接,在完成正常搜索后,将获得根父级(当然,这种方法要求每个子文档都有一个对其根患者的引用) 如果你选择走这条路,我将发布一些例子。在我以前的一个Solr项目中,我遇到了类似的(更复杂的本体)问题 更简单的方法(解决此问题时更简单,而不是整个方法)是将模式的这一部分完全展平,并将所有信息(文档和代码项)存储到其父患者中,然后进行常规搜索。这更符合Solr(您必须以不同的方式看待Solr模式。它与常规RDB规范化模式完全不同,Solr鼓励数据冗余,以便您可以在没有连接的情况下快速搜索) 第三种方法是对具有代表性的数据集进行一些连接测试,看看搜索性能是如何受到影响的 最后,这实际上取决于您的整个设置和需求(当然还有测试结果) 编辑1: 我在几年前就这么做了,所以你必须弄清楚事情是否在这段时间发生了变化 1。创建自定义请求处理程序 为了完成完全干净的工作,我建议您定义自己的请求处理程序(在solrconfig.xml中),只需复制以
...
...
然后将名称
更改为对用户有意义的内容,例如/searchPatients
。
此外,将此部分添加到:
<arr name="components">
<str>patients</str>
<str>facet</str>
<str>mlt</str>
<str>highlight</str>
<str>stats</str>
<str>debug</str>
</arr>
患者
方面
mlt
突出
统计数据
调试
2。创建自定义搜索组件
将此添加到solrconfig:
<searchComponent name="patients" class="org.apache.solr.handler.component.PatientQueryComponent"/>
创建PatientQueryComponent类:以下源代码可能有错误,因为我在文本编辑器中编辑了我的原始源代码,并在未经测试的情况下发布了它,但重要的是您得到的是配方,而不是完成的源代码,对吗?我抛弃了缓存、延迟加载、prepare方法,只留下基本逻辑。您必须了解性能将如何受到影响,然后根据需要调整源代码。我的性能很好,但我的索引中总共有几百万个文档
公共类PatientQueryComponent扩展了SearchComponent{
...
@凌驾
公共无效进程(ResponseBuilder rb)引发IOException{
SolrQueryRequest req=rb.req;
SolrQueryResponse rsp=rb.rsp;
SolrParams params=req.getParams();
if(!params.getBool(组件名称,true)){
返回;
}
searcher=req.getSearcher();
//如果未设置,则将-1作为标志。
long-timeAllowed=(long)params.getInt(CommonParams.TIME_-ALLOWED,-1);
DocList initialSearchList=null;
solrindexearcher.QueryCommand cmd=rb.getQueryCommand();
cmd.setTimeAllowed(timeAllowed);
cmd.setSupersetMaxDoc(不限最大计数);
//消防标准查询
SolrIndexSearcher.QueryResult结果=新的SolrIndexSearcher.QueryResult();
searcher.search(结果,cmd);
initialSearchList=result.getDocList();
//设置用于保存患者ID的
List patientIds=new ArrayList();
DocIterator迭代器=initialSearchList.iterator();
int-id;
//循环搜索结果
while(iterator.hasNext()){
//添加您的if逻辑(单据类型,…)
id=iterator.nextDoc();
doc=searcher.doc(id);/,fields)您可以尝试惰性字段加载,只将patientID字段值加载到文档中
字符串patientId=doc.get(“patientId”)//位于子文档中并指向其根父级-patient的字段
patientIds.add(patientId);
}
//TermsFilter中所有唯一的患者ID
TermsFilter TermsFilter=新的TermsFilter();
任期;
for(字符串pid:patientIds){
term=新术语(“patient_ID”,pid);//对patient唯一(名称)并保存patientID的字段
术语过滤器。添加术语(术语);
}
//获取ID在TermsFilter中的所有患者
DocList patientsList=null;
patientsList=searcher.getDocList(new MatchAllDocsQuery(),searcher.convertFilter(termsFilter),null,0,1000);
long totalSize=initialSearchList.size()+patientsList.size();
logger.info(“总计:+totalSize”);
SolrDocumentList solrResultList=SolrPluginUtils.docListToSolrDocumentList(patientsList,searcher,null,null);
SolrDocumentList solrinitialist=SolrPluginUtils.docListToSolrDocumentList(initialSearchList,searcher,null,null);
//将患者添加到列表的末尾
for(SolrDocument父级:solrResultList){
solrinitialist.add(父级);
}
//替换初始结果作为响应
添加或替换结果(rsp,Solrinitialist);
addToLog(“hitsRef”,patientsList.size());
rb.setResult(result);
}
}
看看这篇文章:
实际上,您可以在SOLR 4.5中执行此操作,谢谢,我必须搜索3种类型的文档,因此最好是将其规范化并存储。你能更清楚地了解这家公司吗
public class PatientQueryComponent extends SearchComponent {
...
@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, true)) {
return;
}
searcher = req.getSearcher();
// -1 as flag if not set.
long timeAllowed = (long)params.getInt( CommonParams.TIME_ALLOWED, -1 );
DocList initialSearchList = null;
SolrIndexSearcher.QueryCommand cmd = rb.getQueryCommand();
cmd.setTimeAllowed(timeAllowed);
cmd.setSupersetMaxDoc(UNLIMITED_MAX_COUNT);
// fire standard query
SolrIndexSearcher.QueryResult result = new SolrIndexSearcher.QueryResult();
searcher.search(result, cmd);
initialSearchList = result.getDocList();
// Set which'll hold patient IDs
List<String> patientIds = new ArrayList<String>();
DocIterator iterator = initialSearchList.iterator();
int id;
// loop through search results
while(iterator.hasNext()) {
// add your if logic (doc type, ...)
id = iterator.nextDoc();
doc = searcher.doc(id); // , fields) you can try lazy field loading and load only patientID filed value into the doc
String patientId = doc.get("patientID") // field that's in child doc and points to its root parent - patient
patientIds.add(patientId);
}
// All all unique patient IDs in TermsFilter
TermsFilter termsFilter = new TermsFilter();
Term term;
for(String pid : patientIds){
term = new Term("patient_ID", pid); // field that's unique (name) to patient and holds patientID
termsFilter.addTerm(term);
}
// get all patients whose ID is in TermsFilter
DocList patientsList = null;
patientsList = searcher.getDocList(new MatchAllDocsQuery(), searcher.convertFilter(termsFilter), null, 0, 1000);
long totalSize = initialSearchList.size() + patientsList.size();
logger.info("Total: " + totalSize);
SolrDocumentList solrResultList = SolrPluginUtils.docListToSolrDocumentList(patientsList, searcher, null, null);
SolrDocumentList solrInitialList = SolrPluginUtils.docListToSolrDocumentList(initialSearchList, searcher, null, null);
// Add patients to the end of the list
for(SolrDocument parent : solrResultList){
solrInitialList.add(parent);
}
// replace initial results in response
SolrPluginUtils.addOrReplaceResults(rsp, solrInitialList);
rsp.addToLog("hitsRef", patientsList.size());
rb.setResult( result );
}
}