Script 更新處理器

ScriptUpdateProcessorFactory 允許在 Solr 文件更新處理期間使用 Java 腳本引擎,從而在索引之前,在表達自訂文件處理邏輯方面具有極大的彈性。

它有連接到提交、刪除、回滾等索引動作的掛鉤,但是新增是最常見的用法。它作為 UpdateProcessor 實作,放置在 UpdateChain 中。

這以前稱為 StatelessScriptingUpdateProcessor,並已重新命名以澄清此更新處理器的關鍵面向是它啟用腳本編寫。

腳本可以使用 JVM 支援的任何腳本語言(例如 JavaScript)編寫,並動態執行,因此不需要預先編譯。

能夠在索引管道中執行您選擇的腳本是一個非常強大的工具,我偶爾稱之為 脫離困境 的卡片,因為您可以透過這種方式解決一些您無法以任何其他方式解決的問題。但是,您正在引入一些潛在的安全性漏洞。

模組

這透過 scripting Solr 模組 提供,使用前需要啟用。

啟用 ScriptingUpdateProcessor 和腳本引擎

Java 11 和舊版本附帶一個名為 Nashorn 的 JavaScript 引擎,但 Java 12 將要求您新增自己的 JavaScript 引擎。其他支援的腳本引擎(如 JRuby、Jython、Groovy)都需要您將 JAR 檔案新增到 Solr。

深入瞭解如何將任何其他需要的 JAR 檔案(取決於您的腳本引擎)新增到 Solr 的 Lib 目錄

設定

<updateRequestProcessorChain name="script">
   <processor class="org.apache.solr.scripting.update.ScriptUpdateProcessorFactory">
     <str name="script">update-script.js</str>
   </processor>
   <!--  optional parameters passed to script
     <lst name="params">
       <str name="config_param">example config parameter</str>
     </lst>
   -->
   <processor class="solr.LogUpdateProcessorFactory" />
   <processor class="solr.RunUpdateProcessorFactory" />
 </updateRequestProcessorChain>
處理器支援其配置的預設值/附加值/不變值概念。然而,也可以跳過這一層,直接在 <processor> 標籤下設定參數。

以下列出每個配置參數及其含義

script

必要

預設值:無

腳本檔案名稱。腳本檔案必須放在 conf/ 目錄中。可以指定一個或多個 "script" 參數;多個腳本會按照指定的順序執行。

engine

選用

預設值:無

可選用指定要使用的腳本引擎。只有在腳本檔案的副檔名不是標準的腳本引擎映射時才需要此項。例如,如果您的腳本檔案是用 JavaScript 編寫的,但檔案名稱為 update-script.foo,則使用 javascript 作為引擎名稱。

params

選用

預設值:無

傳遞到腳本執行環境中的可選參數。這被指定為具有巢狀型別參數的具名列表 (<lst>) 結構。如果指定了此項,腳本環境將會獲得一個 "params" 物件,否則將不會有 "params" 物件可用。

腳本執行環境

每個腳本都會提供一些變數給它。

logger

Logger (org.slf4j.Logger) 實例。這對於從腳本記錄資訊很有用。

req

SolrQueryRequest 實例。

rsp

SolrQueryResponse 實例。

params

來自配置的 "params" 物件(如果有的話)。

試試看

有一個 JavaScript 範例 update-script.js 作為 "techproducts" 配置集的一部分。

要試用腳本功能,請在檔案 ./server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml 中啟用 <updateRequestProcessorChain name="script"> 配置。然後透過 bin/solr start -e techproducts -Dsolr.modules=scripting 啟動 Solr。

INFO: update-script#processAdd: id=1

您可以在 Solr 記錄 UI 中看到記錄的訊息。

範例

processAdd() 和其他腳本方法可以返回 false 以跳過文件的後續處理。所有方法都必須定義,儘管通常 processAdd() 方法是執行操作的地方。

Javascript

注意:請檢查 solrconfig.xml 並取消註解更新請求處理器定義以啟用此功能。

function processAdd(cmd) {

  doc = cmd.solrDoc;  // org.apache.solr.common.SolrInputDocument
  id = doc.getFieldValue("id");
  logger.info("update-script#processAdd: id=" + id);

// Set a field value:
//  doc.setField("foo_s", "whatever");

// Get a configuration parameter:
//  config_param = params.get('config_param');  // "params" only exists if processor configured with <lst name="params">

// Get a request parameter:
// some_param = req.getParams().get("some_param")

// Add a field of field names that match a pattern:
//   - Potentially useful to determine the fields/attributes represented in a result set, via faceting on field_name_ss
//  field_names = doc.getFieldNames().toArray();
//  for(i=0; i < field_names.length; i++) {
//    field_name = field_names[i];
//    if (/attr_.*/.test(field_name)) { doc.addField("attribute_ss", field_names[i]); }
//  }

}

function processDelete(cmd) {
  // no-op
}

function processMergeIndexes(cmd) {
  // no-op
}

function processCommit(cmd) {
  // no-op
}

function processRollback(cmd) {
  // no-op
}

function finish() {
  // no-op
}

Ruby

Ruby 支援是透過 JRuby 專案實作的。要使用 JRuby 作為腳本引擎,請將 jruby.jar 新增至 Solr。

以下是一個 JRuby 更新處理腳本範例(請注意,所有傳入的變數都需要加上 $ 前綴,例如 $logger

def processAdd(cmd)
  doc = cmd.solrDoc  # org.apache.solr.common.SolrInputDocument
  id = doc.getFieldValue('id')

  $logger.info "update-script#processAdd: id=#{id}"

  doc.setField('source_s', 'ruby')

  $logger.info "update-script#processAdd: config_param=#{$params.get('config_param')}"
end

def processDelete(cmd)
  # no-op
end

def processMergeIndexes(cmd)
  # no-op
end

def processCommit(cmd)
  # no-op
end

def processRollback(cmd)
  # no-op
end

def finish()
  # no-op
end

已知問題

以下在 JRuby 中無法如預期運作,但在 JavaScript 中可以正常運作

#  $logger.info "update-script#processAdd: request_param=#{$req.params.get('request_param')}"
#  $rsp.add('script_processed',id)

Groovy

從 Groovy 發行版的 lib/ 目錄新增 JAR 到 Solr。Groovy 發行版的所有 JAR 可能不是都必需的,但需要的不僅僅是主要的 groovy.jar 檔案(至少當使用 Groovy 2.0.6 測試時是如此)

def processAdd(cmd) {
  doc = cmd.solrDoc  // org.apache.solr.common.SolrInputDocument
  id = doc.getFieldValue('id')

  logger.info "update-script#processAdd: id=" + id

  doc.setField('source_s', 'groovy')

  logger.info "update-script#processAdd: config_param=" + params.get('config_param')

  logger.info "update-script#processAdd: request_param=" + req.params.get('request_param')
  rsp.add('script_processed',id)
}

def processDelete(cmd) {
 //  no-op
}

def processMergeIndexes(cmd) {
 // no-op
}

def processCommit(cmd) {
 //  no-op
}

def processRollback(cmd) {
 // no-op
}

def finish() {
 // no-op
}

Python

Python 支援是透過 Jython 專案實作的。將獨立 jython.jar (包含所有相依性的 JAR) 新增到 Solr 中。

def processAdd(cmd):
  doc = cmd.solrDoc
  id = doc.getFieldValue("id")
  logger.info("update-script#processAdd: id=" + id)

def processDelete(cmd):
    logger.info("update-script#processDelete")

def processMergeIndexes(cmd):
    logger.info("update-script#processMergeIndexes")

def processCommit(cmd):
    logger.info("update-script#processCommit")

def processRollback(cmd):
    logger.info("update-script#processRollback")

def finish():
    logger.info("update-script#finish")