1

嗨,我有 3 级树结构中的数据。当用户搜索第三级节点时,我可以使用 SOlr JOIN 来获取根节点吗?

例如 -

    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

我想搜索一个 CODE_ITEM 并返回与代码项搜索条件匹配的所有患者。如何才能做到这一点。是否可以执行两次连接。第一个连接给出了 code_item 搜索的所有文档,下一个连接给出了所有 Patient。

类似于 SQL 查询中的内容 -

select * from patients where docID (select DOCID from DOCUMENTS where CODEID IN (select CODEID from CODE_ITEMS where CODE LIKE '%SEARCH_TEXT%'))
4

2 回答 2

2

我真的不知道 Solr 连接内部是如何工作的,但是知道 RDB 多重连接在大型数据集上效率极低,我可能最终会编写自己的org.apache.solr.handler.component.QueryComponent之后进行正常搜索,获取根父(当然,这种方法要求每个子文档都有对其根患者的引用)。

如果您选择走这条路,我将发布一些示例。在我之前的一个 Solr 项目中,我遇到了类似的(更复杂的本体)问题。

更简单的方法(在解决这个问题时更简单,而不是整个方法)是完全扁平化架构的这一部分并将所有信息(文档和代码项)存储到其父患者中,然后进行常规搜索。这更符合 Solr(您必须以不同的方式查看 Solr 架构。它与您的常规 RDB 规范化架构完全不同,Solr 鼓励数据冗余,因此您可以在没有连接的情况下快速搜索)。

第三种方法是对代表性数据集进行一些连接测试,看看搜索性能如何受到影响。

最后,这实际上取决于您的整个设置和要求(当然还有测试结果)。

编辑1: 我在几年前做过,所以你必须弄清楚事情是否同时发生了变化。

1.创建自定义请求处理程序

要完成完全干净的工作,我建议您通过简单地复制以开头的整个部分来定义自己的请求处理程序(在 solrconfig.xml 中)

<requestHandler name="/select" class="solr.SearchHandler"> ... ... </requestHandler>

然后更改name为对您的用户有意义的内容,例如/searchPatients. 另外,在里面添加这个部分:

    <arr name="components">
            <str>patients</str>
            <str>facet</str>
            <str>mlt</str>
            <str>highlight</str>            
            <str>stats</str>
            <str>debug</str>
    </arr>

2.创建自定义搜索组件

将此添加到您的 solrconfig:

<searchComponent name="patients" class="org.apache.solr.handler.component.PatientQueryComponent"/>

创建 PatientQueryComponent 类:
以下源可能有错误,因为我在文本编辑器中编辑了我的原始源并在没有测试的情况下发布了它,但重要的是你得到的是配方,而不是完成的源,对吗?我抛弃了缓存、延迟加载、准备方法,只留下了基本逻辑。您必须查看性能将如何受到影响,然后在需要时调整源。我的表现很好,但我的索引中总共有几百万个文档。

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 );
    }
}
于 2012-07-28T00:59:15.040 回答
1

看看这篇文章:http: //blog.griddynamics.com/2013/12/grandchildren-and-siblings-with-block.html

实际上你可以在 SOLR 4.5 中做到这一点

于 2013-12-29T14:29:35.960 回答