簡體   English   中英

在Solr組件准備方法中執行分布式搜索

[英]Performing a distributed search inside a Solr component prepare method

我正在編寫一個自定義的Solr組件。 在組件的prepare方法中,我正在執行作為自定義參數(在req.params )給出的查詢。 我沒有在prepare方法中運行q參數查詢,而是在自定義參數中定義了另一個輸入查詢。 我正在使用該自定義輸入查詢返回的文檔來進行prepare方法的一些准備工作。

問題在於,由於我的索引分布在多個分片中,因此自定義查詢返回的文檔只是駐留在其中一個分片上的文檔。 換句話說,在我的prepare方法中執行的搜索未分布,並且得到了部分結果。 這或多或少是我在prepare方法中執行搜索的方式:

rb.req.getSearcher().getDocList(customQuery, null, null, offset, len, 0);

有沒有辦法在prepare方法中進行分布式搜索並從所有分片中獲取匹配的文檔?


編輯:

我當前的解決方案是使用Solrj大致執行查詢,如下所示:

SolrServer server = new HttpSolrServer(url);
SolrQuery request = new SolrQuery(customQuery);
NamedList queryResponse = server.query(request).getResponse();

然后,我解析響應以獲取返回文檔的內容。 由於某些原因,我不喜歡我的解決方案。 原因之一是我必須解析響應。 但是主要原因是我必須將Solr服務器url作為參數傳遞。 我將URL放在solrconfig.xml文件中。 是否可以以某種方式構造SolrServer實例而無需明確說明Solr服務器url(也許通過ZooKeeper)?

簡單的方法

使用CloudSolrServer執行分布式查詢。 向其提供Zookeeper網址和集合名稱(在響應構建器中可用):

CoreDescriptor coreDescriptor = rb.req.getCore().getCoreDescriptor();
String collectionName = coreDescriptor.getCloudDescriptor().getCollectionName();    
ZkController zkController = coreDescriptor.getCoreContainer().getZkController();    
String zookeeperUrl = zkController.getZkServerAddress();

CloudSolrServer server = new CloudSolrServer(zookeeperUrl);
server.setDefaultCollection(collectionName);
server.connect();

SolrRequest request = ... //initialize the solr request to execute the query
NamedList<Object> solrResponse = server.request(solrRequest);
// do whatever you like with the returned response;
server.shutdown();

正確的方式

不要在prepare方法內執行分布式搜索。 不要在prepare方法中查詢索引。 您需要做的是首先確定要在哪個階段執行分布式查詢。 這些階段是STAGE_STARTSTAGE_PARSE_QUERYSTAGE_TOP_GROUPSSTAGE_EXECUTE_QUERYSTAGE_GET_FIELDSSTAGE_DONE 如果需要在兩個階段之間執行它,則創建一個新的中間階段(例如EXECUTE_PREPARING_QUERY )。

覆蓋distributedProcess方法並以如下方式實現它:如果當前階段是您的階段,則為分片請求設置正確的參數:

@Override public int distributedProcess(ResponseBuilder rb) {
    ...
    if (rb.stage == MY_STAGE) {
       ShardRequest sreq = new ShardRequest();
       sreq.purpose = ShardRequest.PURPOSE_PRIVATE;
       sreq.params = new ModifiableSolrParams();
       // set the parameters for the shard request
       rb.addRequest(this, sreq);
    }
    ...
}

現在,每個分片將執行由您在其自己的核心上設置的參數定義的請求。 這將在舞台MY_STAGE上發生。 您仍然必須處理分片的響應,將其組合並使用它們。 處理所有這些響應的正確位置是組件的handleResponses方法內。 因此,如果處於正確的階段,請覆蓋handleResponses並對碎片響應做任何您需要做的事情。 您可能需要將它們保存在某個位置,以便稍后可以在finishStage方法中引用它們。

@Override public void handleResponses(ResponseBuilder rb, ShardRequest sreq) {
   ...
   if (stage == MY_STAGE) {
      List<ShardResponse> responses = sreq.responses;
      for (ShardResponse response : responses) {
         //do something with the response, maybe save it somewhere
         rb.finished.remove(sreq);
      }
   }
   ...
}

現在,您必須重寫finishStage方法,並對合並的結果進行任何處理。

@Override public void finishStage(ResponseBuilder rb) {
   ...
   if (rb.stage == MY_STAGE) {
      // do whatever you need to do with the results
   }
   ...
}

重要的信息是使用響應構建器階段來控制該組件相對於其他組件的執行流程。 如果希望在執行實際查詢之前執行代碼,則不必將代碼放入prepare方法中。 您只需要創建或使用介於STAGE_STARTSTAGE_EXECUTE_QUERY中間的階段。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM