FileNet 批量搜索和更新
FileNet Bulk Search and Update
我有一个要求,我必须更新对象库中数百万文档的文档元数据。所以我用下面的方法
写了一个简单的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 进行查询时,我发现大约 70 万个文档符合条件,并希望所有这些文档都能得到更新。当我 运行 程序时,它更新了大约 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
有没有更好的方法来实现这个?此外,我将在生产中使用组件队列 运行 这个工具。
您实际上有 2 个更好的选择,可以使用基于脚本的批量操作或扫描。
批量操作
您可以对查询的搜索结果应用批量操作。这些操作的应用发生在查询 运行s 期间或查询 运行s.
之后
- 在管理控制台中访问对象存储搜索
- 在 SQL 视图选项卡上,输入适当的查询。
- 在批量操作选项卡上、select 启用。
- 在脚本部分,select 运行 脚本。
- 在脚本字段中输入您的 Java脚本代码。有关详细信息,请参阅下面的示例。
- 单击运行。管理控制台 运行 查询和 Java 脚本操作。
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
自定义扫描作业
或者,您可以使用自定义扫描作业。扫描是后台服务的一个实例,您配置它来处理数据库中的对象 table。
如果对象满足配置的条件,则扫描对该对象执行操作。
扫描包含一个 扫描操作 和一个 扫描作业
- 在域导航窗格中,单击 对象存储。在对象中
商店导航窗格,右键单击扫一扫管理>扫一扫
Actions 文件夹并单击 New Sweep Action。
- Select 操作类型。对于这个例子,让 select Java 脚本,下面列出了一个例子,然后完成向导。
- 在域导航窗格中,select 对象存储。
在对象存储导航窗格中,select 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();
}
有关扫描作业的更多信息,请查看 link here
我有一个要求,我必须更新对象库中数百万文档的文档元数据。所以我用下面的方法
写了一个简单的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 进行查询时,我发现大约 70 万个文档符合条件,并希望所有这些文档都能得到更新。当我 运行 程序时,它更新了大约 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
有没有更好的方法来实现这个?此外,我将在生产中使用组件队列 运行 这个工具。
您实际上有 2 个更好的选择,可以使用基于脚本的批量操作或扫描。
批量操作
您可以对查询的搜索结果应用批量操作。这些操作的应用发生在查询 运行s 期间或查询 运行s.
之后- 在管理控制台中访问对象存储搜索
- 在 SQL 视图选项卡上,输入适当的查询。
- 在批量操作选项卡上、select 启用。
- 在脚本部分,select 运行 脚本。
- 在脚本字段中输入您的 Java脚本代码。有关详细信息,请参阅下面的示例。
- 单击运行。管理控制台 运行 查询和 Java 脚本操作。
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
自定义扫描作业
或者,您可以使用自定义扫描作业。扫描是后台服务的一个实例,您配置它来处理数据库中的对象 table。 如果对象满足配置的条件,则扫描对该对象执行操作。 扫描包含一个 扫描操作 和一个 扫描作业
- 在域导航窗格中,单击 对象存储。在对象中 商店导航窗格,右键单击扫一扫管理>扫一扫 Actions 文件夹并单击 New Sweep Action。
- Select 操作类型。对于这个例子,让 select Java 脚本,下面列出了一个例子,然后完成向导。
- 在域导航窗格中,select 对象存储。 在对象存储导航窗格中,select 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();
}
有关扫描作业的更多信息,请查看 link here