FileNet 批量搜索和更新

Posted

技术标签:

【中文标题】FileNet 批量搜索和更新【英文标题】:FileNet Bulk Search and Update 【发布时间】:2017-05-22 17:12:41 【问题描述】:

我有一个要求,我必须更新对象存储中数百万个文档的文档元数据。所以我用下面的方法写了一个简单的java单机

SearchSQL documentSearchSQL = new SearchSQL();
String selectQuery = "Id ";
String classSymbolicName="Document_Class_Name";
String myAlias1 = "r";
String whereClause="r.Document_Type_Code='DIRMKTGDOC'and VersionStatus=1"
boolean subClassesToo=false;
documentSearchSQL.setSelectList(selectQuery);
documentSearchSQL.setFromClauseInitialValue(classSymbolicName, myAlias1, subClassesToo);
documentSearchSQL.setWhereClause(whereClause);

UpdatingBatch updatingBatch =null;
SearchScope searchScope = new SearchScope(p8ObjectStore);
RepositoryRowSet rowSet = searchScope.fetchRows(documentSearchSQL, new Integer(10000), null, new Boolean(true));
PageIterator pageIterator = rowSet.pageIterator();
RepositoryRow row;
Document document = null;

while(pageIterator.nextPage())
Object[] rowArray = pageIterator.getCurrentPage();
updatingBatch = UpdatingBatch.createUpdatingBatchInstance(p8ObjectStore.get_Domain(),RefreshMode.NO_REFRESH); 
for (int i = 0; i < rowArray.length; i++) 
row= (RepositoryRow)rowArray[i];
Properties documentProps = row.getProperties();
document = Factory.Document.fetchInstance(p8ObjectStore, documentProps.getIdValue("Id"), null);
// I have the metadata symbolic name and its values within HashMap. So iterating Map to set the values
for(Map.Entry<String, ArrayList<String>> documentMetadata : documentMetadataValues.entrySet())
document.getProperties().putObjectValue(documentMetadata.getKey(), documentMetadata.getValue().get(1));

updatingBatch.add(document, null);

updatingBatch.updateBatch();

当我在 docVersion 上运行查询时,我发现大约 700K 文档符合条件,并且希望所有文档都能得到更新。当我运行程序时,它更新了大约 390k 文档,然后报错

com.filenet.api.exception.EngineRuntimeException: FNRCA0031E: API_UNABLE_TO_USE_CONNECTION: The URI for server communication cannot be determined from the connection object http://server:port/wsi/FNCEWS40MTOM. Message was: Connection refused: connect

有没有更好的方法来实现这一点?另外,我将使用组件队列在生产环境中运行此工具。

【问题讨论】:

如果您使用的是 5.2.1,您可能需要查看“扫描” 我同意@ChristopherPowell,你最好使用扫描或批量操作 【参考方案1】:

实际上,您有 2 个更好的选择来执行此操作,即使用基于脚本的批量操作或扫描。


批量操作

您可以对查询的搜索结果应用批量操作。这些操作的应用发生在查询运行时或查询运行之后。

    在管理控制台中访问对象存储搜索SQL 视图选项卡上,输入适当的查询。 在批量操作标签上,选择启用。 在脚本部分,选择运行脚本。 在脚本字段中输入您的 javascript 代码。有关详细信息,请参阅下面的示例。 点击运行。管理控制台运行查询和 JavaScript 操作。

importClass(Packages.com.filenet.api.property.Properties);
importClass(Packages.com.filenet.api.constants.RefreshMode);

function OnCustomProcess(CEObject) 
  CEObject.refresh();
  CEObject.getProperties().putValue("DocumentTitle", "Test1");
  CEObject.save(RefreshMode.REFRESH);

关于这方面的更多信息,您可以查看知识中心here


自定义扫描作业

或者,您可以使用自定义扫描作业。扫描是您配置为处理数据库表中的对象的后台服务的一个实例。 如果对象满足配置的条件,则扫描会对对象执行操作。 扫描由扫描动作扫描作业

组成
    在域导航窗格中,单击对象存储。在对象 店铺导航栏,右键扫一扫管理>扫一扫 Actions 文件夹,然后点击 New Sweep Action。 选择操作类型。对于此示例,让我们选择 Java 脚本,下面列出了一个示例,然后完成向导。 在域导航窗格中,选择对象存储。 在对象存储导航窗格中,选择 Sweep Management > Job Sweeps > Custom Jobs 文件夹并单击 New,参考我们刚刚创建的操作,完成向导。 现在你们都准备好了!运行扫描作业

importPackage(Packages.com.filenet.api.core);
importPackage(Packages.com.filenet.api.constants);
importPackage(Packages.com.filenet.api.exception);
importPackage(Packages.com.filenet.api.sweep);
importPackage(Packages.com.filenet.api.engine);

// Implement for custom job and queue sweeps.
function onSweep(sweepObject, sweepItems) 
  var hcc = HandlerCallContext.getInstance();
  hcc.traceDetail("Entering CustomSweepHandler.onSweep");
  hcc.traceDetail("sweepObject = " +
    sweepObject.getProperties().getIdValue(PropertyNames.ID) +
    "sweepItems.length = " + sweepItems.length);

  // Iterate the sweepItems and change the class.
  idx = 0;
  for (idx = 0; idx < sweepItems.length; idx++) 
    // At the top of your loop, always check to make sure 
    // that the server is not shutting down. 
    // If it is, clean up and return control to the server.
    if (hcc != null && hcc.isShuttingDown()) 
      throw new EngineRuntimeException(ExceptionCode.E_BACKGROUND_TASK_TERMINATED,
        this.constructor.name + " is terminating prematurely because the server is shutting down");
    

    var item = sweepItems[idx].getTarget();
    String msg = "sweepItems[" + idx + "]= " + item.getProperties().getIdValue("ID");
    hcc.traceDetail(msg);

    try 
      var CEObject = Document(item);
      CEObject.getProperties().putValue("DocumentTitle", "Test1");
      CEObject.save(RefreshMode.NO_REFRESH);

      // Set outcome to PROCESSED if item processed successfully.
      sweepItems[idx].setOutcome(SweepItemOutcome.PROCESSED,
        "item processed by " + this.constructor.name);
    
    // Set failure status on objects that fail to process.
    catch (ioe) 
      sweepItems[idx].setOutcome(SweepItemOutcome.FAILED, "CustomSweepHandler: " +
        ioe.rhinoException.getMessage());
    
  
  hcc.traceDetail("Exiting CustomSweepHandler.onSweep");


/* 
 * Called automatically when the handler is invoked by a custom sweep job 
 * or sweep policy. Specify properties required by the handler, if any.
 * If you return an empty array, then all properties are fetched.
 */
function getRequiredProperties() 
  var pnames = ['Id', 'DocumentTitle'];
  return pnames.toString();

有关扫地工作的更多信息,请查看链接here

【讨论】:

以上是关于FileNet 批量搜索和更新的主要内容,如果未能解决你的问题,请参考以下文章

Filenet 用户缓存刷新

在 FileNet ContentEngine 中搜索文件夹并检索其类

如何将 Filenet 文档的内容从 word 文档更新为 pdf..?

在 FileNet P8 中更新 Creator 属性

如何在不更改版本的情况下更新 Filenet 文档的内容?

FileNet ContentElement 签出