二十四画生的Blog


        ——开始学习Orchard框架
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

DNN中搜索引擎原理——如何获取SearchItem

Posted on 2005-08-18 16:27  二十四画生  阅读(3706)  评论(12编辑  收藏  举报
  上一篇《DNN中搜索引擎原理——数据库分析篇》讲到DotNetNuke(以下简称DNN)是将各模块的内容以SearchItem(查询条目)的形式存储到数据库中供检索,并通过索引关键字来加快对查询条目的检索。DNN是如和将形式各异的模块内容提取到SearchItem表中的呢?SearchWord(索引关键字)表的内容又是如何获得呢?
  首先,模块实现ISearchable接口是解决以上问题的基础。在DNN中定义了一个ISearchable接口(ISearchable.vb文件中),该接口中的GetSearchItems方法就提供了获取查询条目的途径。模块通过实现ISearchable接口的GetSearchItems方法,并以SearchItemInfoCollection形式返回自身内容的查询条目集合。这样就使千变万化的模块内容统一成一种形式的SearchItem。以大家最熟悉的Text/HTML模块为例,以下是它实现ISearchable接口的方法:
' 实现ISearchable接口
Public Function GetSearchItems(ByVal ModInfo As Entities.Modules.ModuleInfo) As Services.Search.SearchItemInfoCollection Implements Entities.Modules.ISearchable.GetSearchItems

      
Dim SearchItemCollection As New SearchItemInfoCollection

      
Dim HtmlText As HtmlTextInfo = GetHtmlText(ModInfo.ModuleID)

      
If Not HtmlText Is Nothing Then
          
'DesktopHTML is encoded in the Database so Decode before Indexing
          Dim strDesktopHtml As String = HttpUtility.HtmlDecode(HtmlText.DeskTopHTML)

          
'Get the description string,获取描述字符串
          Dim strDescription As String = HtmlUtils.Shorten(HtmlUtils.Clean(strDesktopHtml, False), MAX_DESCRIPTION_LENGTH, "")
      
'构造了一个查询条目对象
      Dim SearchItem As SearchItemInfo = New SearchItemInfo(ModInfo.ModuleTitle, strDescription, HtmlText.CreatedByUser, HtmlText.CreatedDate, ModInfo.ModuleID, "", strDesktopHtml, "", Null.NullInteger)
          SearchItemCollection.Add(SearchItem)
      
End If
      
Return SearchItemCollection

End Function

  其中SearchItemInfo类中Content属性是关键,它决定了可以被检索到的内容,如果不能很好的给出这个属性的内容就不能得到预期的查询效果。比如Links模块,它提供的查询条目的Content属性是链接的描述信息。很多人在添加链接时都没有写描述信息,那么这个链接就会搜索不到,如果用链接的“标题+描述信息”作为Content属性的内容就很好了。另外,需要强调一点:没有实现ISearchable接口的模块内容是不能被检索到的。
  知道各个模块是如何提供查询条目的了,那么DNN是如何来收集这些条目信息的呢?DNN收集这些条目信息的方法有两种:
1、通过调度(Schedule)的方式,定期自动收集查询条目。在“主机管理->调度管理”中可看见相关的调度信息。
2、通过重建索引,手动收集。在“主机管理->搜索管理”。

  这也就是说,如果刚刚添加的内容是不能马上每检索到,只有重建索引后才能。无论哪种方法,它们都将调用SearchEngine类中的IndexContent()方法。顺着这条线走下去,大家就会明白,内容太多就不详细写了。
  值得一提的是两个抽象的Provider,利用反射的原理动态的创建web.config中设置的默认用到的子类:(是一个反射工厂模式)
1、IndexingProvider:检索制定站点可以被查询到的内容,具体的实现类是ModuleIndexer(ModuleIndexer.vb)
2、SearchDataStoreProvider:向数据库中存/取制定的查询内容,具体的实现类是SearchDataStore(SearchDataStore.vb)
程序架构上来看编写新的Provider子类应该可以改进查询的方式,具体如何操作没有想到。

  DNN中的搜索功能对中文不是很有效,主要是出在获取索引关键字上。在SearchDataStore类中的AddIndexWords方法中可以看出,关键字是由查询条目中Content属性的内容用空格分割开来的。老外的文章里面空格随处可以,可是我们的文章中空格就不那么多了。总不能要求大家每输入一个词就空一格吧。如果连续超过100字都没有空格,那么这段文字就不能被作为索引关键字,即便是用like '%' + @Word+'%'的临时解决方案也无法查出。临时解决方案在《DNN中搜索引擎原理——数据库分析篇》提到过,这是一种牺牲性能换结果的方法,因为用like '%%'将不能使用索引,其效果还是全表搜索,当SearchWord表中内容很多的时候是会有很大的性能差异的。
以上问题在这篇文章中也有提到:http://www.cnblogs.com/henry_zjk/archive/2005/03/23/123843.html

  另外大家还可以看看CanIndexWord方法,它用来判断一个单词是否可以做为关键字。常用字(如:a,can等)、数字、过长单词、过短单词这些都可以设置为不能作为关键字。具体设置可在“主机管理->搜索管理”中进行。

  本来还想画几幅UML图的,怎奈这方面的水平有限(以后加强学习),画出来怕反到误导了大家。不知本文说清楚了没有,如有错误或遗漏之出还望大家指出,以免误导他人。

更多相关内容>>