3

我想遍历(可能很大)Lotus Domino 数据库中的每个文档,如果处理中断(网络连接错误、应用程序重新启动等),则能够从最后一个文档继续。我没有对数据库的写访问权限。

我正在寻找一种方法,我不必从服务器上下载那些已经处理过的文档。所以,我必须将一些启动信息传递给服务器,哪个文档应该是(可能重新启动的)处理中的第一个文档。

  1. 我检查了AllDocuments属性和DocumentColletion.getNthDocument方法,但是这个属性是未排序的,所以我猜两个调用之间的顺序可以改变。

  2. 另一个想法是使用公式查询,但这些查询似乎无法进行排序。

  3. 第三个想法是Database.getModifiedDocuments相应的方法Document.getLastModified。看起来不错,但在我看来,返回集合的顺序没有记录,并且基于创建时间而不是最后修改时间。

    以下是基于官方示例的示例代码:

    System.out.println("startDate: " + startDate);
    final DocumentCollection documentCollection = 
            database.getModifiedDocuments(startDate, Database.DBMOD_DOC_DATA);
    
    Document doc = documentCollection.getFirstDocument();
    while (doc != null) {
        System.out.println("#lastmod: " + doc.getLastModified() + 
                    " #created: " + doc.getCreated());
        doc = documentCollection.getNextDocument(doc);
    }
    

    它打印以下内容:

    startDate: 2012.07.03 08:51:11 CEDT
    #lastmod: 2012.07.03 08:51:11 CEDT #created: 2012.02.23 10:35:31 CET
    #lastmod: 2012.08.03 12:20:33 CEDT #created: 2012.06.01 16:26:35 CEDT
    #lastmod: 2012.07.03 09:20:53 CEDT #created: 2012.07.03 09:20:03 CEDT
    #lastmod: 2012.07.21 23:17:35 CEDT #created: 2012.07.03 09:24:44 CEDT
    #lastmod: 2012.07.03 10:10:53 CEDT #created: 2012.07.03 10:10:41 CEDT
    #lastmod: 2012.07.23 16:26:22 CEDT #created: 2012.07.23 16:26:22 CEDT
    

    (我这里没有使用任何AgentContext访问数据库。数据库对象来自session.getDatabase(null, databaseName)调用。)

有没有办法用 Lotus Domino Java API 可靠地做到这一点?

4

4 回答 4

4

如果您有权更改数据库,或者可以要求某人这样做,那么您应该创建一个按唯一键或修改日期排序的视图,然后将“指针”存储到最后处理的文档。

除此之外,您必须自己维护以前处理的文档列表。在这种情况下,您可以使用 AllDocuments 属性并遍历它们。使用 GetFirstDocument 和 GetNextDocument,因为据报道它们比 GetNthDocument 快。

或者,您可以进行两次传递,一次收集您将存储的所有文档的 UNID 列表,然后进行第二次传递以处理您拥有的 UNID 列表中的每个文档(使用 GetDocumentByUNID 方法)。

于 2012-10-22T22:39:50.280 回答
3

我不使用 Java API,但在 Lotusscript 中,我会这样做:

找到显示数据库中所有文档的视图。如果您希望代理非常快,请创建一个新视图。第一列应该排序并且可以包含文档的通用 ID。其他列包含您要在代理中读取的所有值,在您的示例中,这将是创建日期和最后修改日期。

然后,您的代码可以像这样简单地遍历视图:

lastSuccessful = FunctionToReadValuesSomewhere() ' Returns 0 if empty
Set view = thisdb.GetView("MyLookupView")
Set col = view.AllEntries
Set entry = col.GetFirstEntry
cnt = 0
Do Until entry is Nothing
    cnt = cnt + 1
    If cnt > lastSuccessful Then
        universalID = entry.ColumnValues(0)
        createDate = entry.ColumnValues(1)
        lastmodifiedDate = entry.ColumnValues(2)
        Call YourFunctionToDoStuff(universalID, createDate, lastmodifiedDate)
        Call FunctionToStoreValuesSomeWhere(cnt, universalID)
    End If
    Set entry = col.GetFirstEntry    
Loop
Call FunctionToClearValuesSomeWhere()

只需将最后成功的值和通用 ID 存储在数据库中的文本文件或环境变量甚至配置文件文档中。当您重新启动代理时,有一些代码检查值是否为空(然后返回 0),否则返回最后一个成功的值。

于 2012-10-22T22:39:19.610 回答
2

代理已经保留了一个字段来描述他们尚未处理的文档,并且这些文档会通过正常处理自动更新。

做你想做的事情的更好方法可能是将搜索结果存储在配置文件文档中。但是,如果您尝试关联数据库中您没有写入权限的文档,您唯一能做的就是保留您已经处理的文档链接的列表(以及您需要保留的有关这些文档的任何信息)文档),或者一个姐妹数据库为每个文档链接保存一个文档以及与您对它们进行的处理相关的多个字段。然后,传输 ID 列表并在客户端执行匹配以执行每个文档的查找。

于 2013-07-18T04:20:20.787 回答
1

Lotus Notes/Domino 数据库设计为在复制环境中跨客户端和服务器分布。在一般情况下,您无法保证从给定的创建或模组时间开始会为您带来一致的结果。

如果您 100% 确定没有创建目标数据库的副本,那么您可以使用 getModifiedDocuments 然后编写一个排序例程将 (modDateTime,UNID) 对放入 SortedSet 或其他合适的数据结构中。然后您可以通过 Set 进行处理,如果遇到错误,您可以将尝试处理的元素的 modDateTime 保存为重新启动点。但是,如果有多个文档具有完全相同的 modDateTime 标记,则可能需要制定一些额外的细节以避免重复。

我想说最后一句话。我知道您问的是 Java,但如果您正在为合规性目的开发备份或归档系统,Lotus C API 具有您真正应该查看的特殊功能。

于 2012-10-22T23:06:52.957 回答