成长日记--2008-0506

本文介绍了一种改进Domino服务器上文档搜索体验的方法。通过优化代理程序和利用文档ID及序列号,实现了用户在不丢失搜索结果的情况下查看文档详情。最终方案解决了原有机制中刷新页面导致搜索结果消失的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:设A服务器提供资料内容。为了速度和效率,Domino这边用户搜索时,只从A服务器取关键信息生成只含有少量关键信息的"小"文档。只有当用户打开具体文档时,才从服务器取所有信息。以前的机制是:用户点小文档时,直接通过小文档的webqueryopen中运行的代理来取具体内容并生成文档。这种机制的限制是,代理生成文档后想将文档展现给用户,只能通过更新当前文档的html head来进行。而一刷新当前页面,用户之前的搜索结果便不见了。这样的做法显然任何用户都无法接受,太不友好了。


   为了解决这个问题,想了很多辙。关键是得到当前用户点击的文档的id,根据文档id取服务器取具体内容。为了得到这个“当前ID”,费尽了脑汁。直接新窗口打开一个代理固然可以,但是由于这个代理没有context doc,没法定位用户当前选中的文档。几番周折,第一个方案如下:
   首先在展现文档的表格中加入了一列checkbox,其值就指定为当前文档的ID。
   "<td><input type=checkbox name=secheck value='"+@Text(@DocumentUniqueID)+"'></input></td>"
   但用户不会点击一个checkbox来打开文档,而是点击表中另一列的超链接。于是设置用户点行中的任意一处时,当前行的checkbox发出click事件。
   "<tr οnclick=/"this.all.secheck.click();/">"
   checkbox的click事件调用表单中js header中的函数,该函数用checkbox的值,也就是当前选中文档的uniqid刷新当前页的一个域DOCID,然后调用一个代理来取文件具体内容。这样做的原因是这个代理就有了context doc,而且它的context doc中的docid就是它去服务器取具体内容的关键依据。这样DOCID就得到了。
function opencurdoc(check){
with(window.document.forms[0]){
curseldocID.value=check.value;
//seldocsubject.value=seldocsubject.value
      document.forms[0].deletedoc.click();
}
}
deletedoc按钮的click事件就是运行agent“createsearchmail”。

createsearchmail代理取得文档具体内容后生成文档存放于某个数据库,然后用户点击链接时就直接打开这个数据库中对应的文档就可。

urlsubject:=@ReplaceSubstring(subject; " "; "%20");
"<td><a href=/"+@WebDbName+"/vSearchcurdoc/"+urlsubject+"?OpenDocument target=/"_blank/">"+fr+"</a></td>"
(插曲:由于含有空格的字符串在url中会被腰斩,用到了@ReplaceSubstring(subject; " "; "%20");解决。)

问题初现曙光,向我的目标迈进。但问题是,用户点击链接打开新页面的速度很快,后台代理还没做完事情,新页面已经打开了,然后就是有时候正常有时候不正常。

想通过延时打开新页面解决,没有满意的方案,然后尝试把费时间的事情分开做,设法让用户打开链接时,链接稍微等待一下下。这个过渡中的方案就不说了,不过需要说明的是这个方案启发了最终的完美方案。

第二套方案:

     必须保证用户点击链接前,已有可用docid,一拍脑袋发现,其实很简单啊,在search生成文档和刷新搜索结果视图A的时候,对应生成一个简单的文档,该文档存储对应文档的id和subject等,保存在一个试图B中。然后,通过A和B共享的一个关键字,通过打开B的文档来做事就可以啊。


   共享关键字插曲:开始共享subject,测试环境下没问题。但猛然想到,用subject作key不合适,subject重复的情况很正常,到时候就会出现混淆了。改用文档的uniqid做沟通,结果莫名其妙,拿不到邮件body。从本质上说subject和unicid都是一样的,都是字符串阿。但是后来看url链接,觉得是domino可能是遇到和文档ID格式一致的字符串,就当文档ID处理,而不再把其当作一个普通的列值来看待。再思虑一下,对每对文档生成相同的序列号,通过这个序列号来配对访问文档。问题解决。
   要说的一点是,想用domino第一列的列值打开文档,需要把这一列设置成排序列才可以。

共享文档序列号后,在搜索结果视图A中,用户的链接就设置如下:
"<td><a href=/"+@WebDbName+"/B/"+tmpseqno+"?OpenDocument target=/"_blank/">"+fr+"</a></td>"
这样就在新窗口中打开了,原窗口的搜索结果还乖乖躺在那里。而在B中打开文档时,又通过webqueryopen做动作,在这里去生成真正要打开的文档。因为webqueryopen的逻辑是在打开文档前发生,所以要它运行完,页面才会打开。

webqueryopen运行的关键代码:

Document contextdoc = agentContext.getDocumentContext();   
       String seldocID=contextdoc.getItemValueString("docID");//取到关键文档ID
   Document curdoc = curdb.getDocumentByUNID(seldocID); //访问关键文档
……(根据关键文档取具体内容,生成真正的文档)
searchDoc.save(true,true); //并保存

 然后利用如下语句打开目标文档:                
 strTemp = "<script language='javascript'>var url='/mail/"
      + curdb.getFileName() + "/($All)/"
      + searchDoc.getUniversalID()
      + "?opendocument';location.href=url</script>";
    contextdoc.replaceItemValue("$$HTMLHead", strTemp);   

前面的方案是通过一个唯一序列号来做事,每次新搜索的时候把之前的搜索结果清除,然后再执行新的搜索。后来想想,这样子用户体验方面还是有点问题,尤其是现在邮件是在新窗口中打开。用户很可能在新的窗口中执行搜索,然后看到就窗口中自己刚才搜的东西完全有可能也点进去看看。但是这个时候由于新的搜索覆盖了旧的搜索,用户点击旧的搜索就会出现异常。

  因此,每次搜索覆盖前面的搜索不太合理。想了想,用文档的有各关键字做文章,这个关键字是一个hashcode,在系统环境中时绝对唯一的。每次搜索的时候,根据这个关键字判断是否已有相关文档,没有才新生成,有的话直接利用。这样的话,用户就可以新旧搜索结果同时利用。而这些暂时性的文档,则考虑用定时代理定时删除。这样用户访问旧搜索结果出现异常的可能性就非常小,而这样的异常(搜索结果过期)是合理的正常的可以接受的。

最终的解决方案和开始的思路相去甚远,但是是前面一步一步的摸索才启发出了最后的方案。最后的方案简单完美,恩,不错不错。

每天做一点让自己感到充实有成就感的事才好!

    每次解决问题的过程中,都会搜到好多有用的资料,本来想整理放到这里的,发现问题解决后来整理,还真不容易。就罢了吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值