65.9K
CodeProject 正在变化。 阅读更多。
Home

高级 Microsoft Content Management Server 开发:第 5 章:使用 SharePoint 搜索 MCMS

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.58/5 (16投票s)

2005年12月14日

48分钟阅读

viewsIcon

80492

在本章中,我们将讨论MCMS开发人员为网站添加搜索功能可用的几种选项。我们还将深入探讨SharePoint Portal Server内置的搜索功能,以及如何将其用作MCMS站点的后端搜索引擎。

标题 高级Microsoft内容管理服务器开发
作者 Lim Mei Ying, Stefan Goßner, Andrew Connell, Angus Logan
出版社 Packt Publishing Ltd.
出版日期 2005年11月
ISBN 1904811531
价格 53.99美元
页数 512

引言

只要以内容为中心的网站存在,就需要搜索内容。许多成功的dot-com企业都是像Yahoo!和Google这样的搜索引擎。每隔几个月,一个新的搜索引擎就会开业,其中许多可以同时搜索多个站点。另一方面,许多网站所有者需要一个搜索功能,只能返回其特定站点的结果。

Microsoft内容管理服务器(MCMS)虽然是一个非常强大的内容管理解决方案,但本身不提供任何搜索功能。然而,仅仅因为你有一个MCMS网站,并不意味着你就无法使用搜索功能。

MCMS搜索选项

有几种方法可以在MCMS网站上实现搜索,每种方法都有不同的成本、实现复杂度和限制。一如既往,每种选择都有其优缺点。 Google 提供了一个免费的Web服务API供您提交查询,但每天只能搜索1000次,并且在徽标放置方面有一些许可要求。 Coveo 为其企业搜索产品提供了免费的、不过期的许可证,但仅限于搜索5000个文档(搜索超过5000个文档需要从Coveo购买许可证)。 Mondosoft 的MondoSearch无缝集成到MCMS中,并为我们提供了强大的功能集,但它不是免费的。

Microsoft的企业门户解决方案SharePoint Portal Server 2003(SPS)包含一个功能强大且可自定义的搜索引擎。SPS创建的索引可以通过Web服务提交Microsoft SQL全文查询来访问。如果您的组织已经部署或计划部署SPS,那么您可以将其用作MCMS搜索引擎。请注意,如果您的网站是公开访问的,此解决方案可能不太有吸引力,因为需要SharePoint外部连接器许可证。因此,SharePoint搜索解决方案通常只适用于基于内网的MCMS站点。

在本章中,我们将利用SPS的搜索功能为我们的Tropical Green MCMS站点提供强大的搜索能力。在此过程中,我们将配置SharePoint以索引我们的Tropical Green站点。我们还将尝试一些免费组件,您可以在MCMS站点中使用它们来执行针对SharePoint索引的搜索查询。

Microsoft SharePoint Portal Server搜索

为了充分利用SharePoint Portal Server搜索的优势,您需要了解它的工作原理以及如何进行配置。在解释其工作原理之前,有几个关键组件需要理解。

  • 内容源包含将被索引的信息。内容源可以是外部网站、文件共享、Windows SharePoint Services站点、Microsoft Exchange公用文件夹或其他提供SharePoint搜索协议处理程序的系统,例如Lotus Notes。
  • 索引文件包含来自一个或多个内容源的已爬取内容。聚合和编目来自不同内容源的内容可以使未来的搜索查询更有效。索引文件也可以复制或传播到SharePoint Web服务器以进行更有效的搜索。创建新门户时,默认会创建两个索引:Portal_ContentNon_Portal_Content。正如预期的那样,前者包含存储在门户中的所有内容,而后者包含门户外部的内容。
  • 搜索范围用于为最终用户提供对内容源的逻辑分组。例如,一家公司可能有多个内部文件共享和网站。寻找特定文档的员工不在乎它是在站点A还是文件共享B中,他们只知道它在那里。管理员可以创建多个内容源并将它们组合在一个用户可以搜索的搜索范围内。此外,搜索范围可以配置为仅包含网站的特定部分,从而提供对用户可以索引和搜索的内容的更精细控制。
  • SharePoint爬虫程序负责爬取所有内容源,提取内容,删除噪声词(例如“and”、“a”、“the”、“or”等等……噪声词文件是可自定义的,您可以添加自己的噪声词),并创建将在执行搜索查询时使用的索引文件。

爬虫程序是MSSearch服务的一部分,该服务执行内容爬取并创建索引文件。此服务按计划运行,您可以通过SharePoint Central Administration工具进行配置。MSSearch服务根据指定的计划时间表激活爬虫程序,该爬虫程序生成用于搜索查询的主索引。

最终用户使用搜索范围来选择要查询的内容源集合。SharePoint查看包含内容源的目录,并确定与搜索查询匹配的最佳候选项。

准备MCMS站点以进行索引

在配置SharePoint以索引我们的MCMS站点之前,我们需要执行一些步骤以使索引更有效和有用。首先,检查您的站点是否启用了MCMS选项“将通道名称映射到主机头名称”。如果已启用,您需要禁用它,因为我们提供的两个选项之一(使用MCMS连接器)不支持主机头名称。在本章的其余部分,我们将假设我们的站点存在于顶级通道TropicalGreen中。

如果您的站点使用“将通道名称映射到主机头名称”选项,您可能需要重命名顶级通道以反映我们在本示例中使用的通道(即TropicalGreen)。

此外,我们的示例假定您已按照附录A“在同一虚拟服务器上设置MCMS和SPS”进行配置。如果您的MCMS Web入口点和SharePoint门户不在同一个虚拟服务器上,此要求可能不适用于您。

其次,我们将配置我们的站点以允许访客访问。我们的Tropical Green站点的大部分内容将供任何匿名访问者浏览。虽然我们有一个受限制的部分,但我们将设置一个新帐户,该帐户将拥有访问我们整个站点的读取权限,供SharePoint在爬取站点时使用。然后,我们将过滤结果,以确保运行搜索的用户只能看到他/她有权访问的搜索结果中的项目。

接下来,我们需要处理MCMS和输出缓存如何响应发布请求。MCMS的默认页面呈现行为不利于SPS搜索。因为所有MCMS请求都返回HTTP状态码200,SharePoint将始终执行站点的完整爬取,而不是增量爬取。我们已经在第4章“准备发布内容以供搜索索引”中详细解释了每次索引爬取请求会发生什么,并实现了一个解决方案。

最后,我们将向模板添加一个控件(随MCMS Connector for SharePoint Technologies提供),该控件使额外的元数据属性可供索引爬虫程序使用,为搜索我们站点的用户提供额外的信息。

禁用通道名称到主机头名称的映射

本章中我们将介绍的一个示例是使用MCMS Connector for SharePoint Technologies。MCMS Connector附带的搜索控件不支持主机头映射功能,因此我们无法启用将通道名称映射到主机头名称。如果您的站点使用了此选项,您需要禁用它。此外,我们应该将顶级通道www.tropicalgreen.net重命名为TropicalGreen,这会更方便,因为这现在将成为URL路径的一部分。

MCMS Connector for SharePoint Technologies需要.NET Framework 1.1。它在运行.NET Framework 1.0版本的站点上无法正常工作。

此更改可能会导致我们站点中的某些用户控件出错,因为它们引用了不再存在的通道路径。检查以下文件,确保将任何对/Channels/www.tropicalgreen.net/的引用更改为/Channels/TropicalGreen/

  • /Login.aspx
  • /UserControls/RightMenu.aspx
  • /UserControls/SiteMapTree.aspx
  • /UserControls/TopMenu.aspx

您可能希望在我们网站的根目录下添加一个额外的文件,该文件会自动将用户重定向到我们站点的通道。将文件命名为default.aspx,它应该包含以下行:

<% Response.Redirect("/TropicalGreen/")%>

http://www.tropicalgreen.net的任何请求现在都将重定向到http://www.tropicalgreen.net/TropicalGreen/

如果您的解决方案需要“将通道名称映射到主机头名称”功能,则MCMS Connector搜索解决方案将不适合您的需求。但是,您可以按照本章稍后详细介绍的方法构建自己的自定义搜索解决方案。

分配搜索帐户

我们的Tropical Green站点既有公共部分,也有会员专区。如果匿名用户或访客执行搜索,他们只能看到站点公共部分的结果。但是,如果已认证用户执行搜索查询,他们应该能够看到公共和私有部分的结果。

为了让SharePoint能够索引我们整个站点,包括会员专区,我们需要创建一个新帐户,该帐户将有权访问整个站点。然后,我们将配置SharePoint在索引时使用此帐户。假设我们已经创建了一个名为MCMSBOOK\SearchCrawler的帐户。我们需要做的第一件事是配置SharePoint Portal Server在爬取内容时使用此帐户。

  1. 通过指向“开始”|“所有程序”|“SharePoint Portal Server”|“SharePoint Central Administration”来启动SharePoint Central Administration。
  2. 在“服务器配置”部分,单击“配置服务器场帐户设置”链接。
  3. 在“默认内容访问帐户”部分输入搜索爬虫帐户凭据,然后单击“确定”。

现在,我们需要授予我们的SearchCrawler帐户对整个Tropical Green网站的订阅者权限。

我们假设您已经安装了MCMS Connector for SharePoint Technologies,因为它的安装程序会在Site Manager中创建一个MCMS Search订阅者组,用于搜索我们的MCMS通道结构。有关安装MCMS Connector的帮助,请参阅附录B。

  1. 通过指向“开始”|“所有程序”|“Microsoft Content Management Server”|“Site Manager”来启动Site Manager。
  2. 在Site Manager左侧面板中,选择“用户角色”按钮。
  3. 选择“订阅者”用户角色。
  4. 然后右键单击“MCMS Search User Subscribers”角色,然后选择“属性”。
  5. 单击“组权限”选项卡,查看MCMS Search User角色拥有的所有通道、模板和资源的权限。所有通道、模板和资源都应被选中。
  6. 单击“组”选项卡,然后单击“修改”按钮。
  7. 输入我们上面添加的MCMSBOOK\SearchCrawler用户作为SharePoint爬取帐户,然后单击“确定”。
  8. 再次单击“确定”关闭属性窗口。

现在我们已经配置了SharePoint使用专用帐户爬取我们的站点,并授予该帐户访问Tropical Green站点中所有内容的权限。

启用Tropical Green的访客访问

由于我们的站点是公开可用的,我们需要确保它不会要求访问者登录。要配置我们的Tropical Green站点以允许访客浏览,我们需要启用访客访问。如果您希望了解如何完成此操作的详细信息,请参阅第一本书《使用Microsoft内容管理服务器构建网站》(Packt Publishing,2005年1月,ISBN 1-904811-16-7)中的完整说明。请参阅第18章中的“欢迎访客访问网站”部分。

如果您已经为访客访问配置了站点,则可以跳过此步骤。

为了让访客能够访问我们的站点,我们需要:

  1. 在域中或作为服务器上的本地用户创建新的MCMS访客帐户。
  2. 使用SCA,配置MCMS以允许访客,并使用步骤1中创建的帐户作为访客登录帐户。
  3. 现在MCMS已配置为允许访客访问站点,请将步骤1中创建的帐户添加到订阅者权限组,并授予该权限组对站点中所有现有通道、资源库和模板库的访问权限,但排除“花园”频道下的“会员”频道。

我们选择启用对站点的访客访问是为了简化。但是,SharePoint也可以使用表单或Windows身份验证来索引我们的站点。对于表单身份验证,我们需要创建一个特殊的首页,该首页会自动使用预定义的帐户登录用户以访问站点,以便SharePoint可以开始爬取。我们必须授予SharePoint爬虫帐户适当的订阅者权限组的权限。

如果您选择创建备用首页以自动登录SharePoint访问您的站点,请记住,任何用户都可以使用此页面访问您的站点。如果使用此方法,应采取特殊措施,例如限制此页面的IP地址,以便只有SharePoint服务器可以访问它。

发布内容的输出缓存和最后修改日期

ASP.NET在生成HTTP状态码方面并不特别复杂,它为每个请求返回HTTP状态码200(OK),而不是发送Last-Modified HTTP头。当SharePoint Portal Server执行增量索引爬取时,它会为站点上找到的每个页面发送HTTP GET请求。如果页面已被索引并且返回了Last-Modified头,SharePoint Portal Server会发送一个条件HTTP GET请求,其中包含一个If-Modified-Since HTTP头,其日期是之前在Last-Modified HTTP头中返回的。如果响应是HTTP状态码304(未修改),SharePoint将不会再次索引该页面。但是,由于ASP.NET始终返回状态码200,因此站点永远不会被SPS增量爬取,并且每次执行爬虫程序时都将有效地进行一次完整的索引。由于MCMS模板文件实际上是特殊的ASP.NET Web窗体,这也影响基于这些模板文件的发布内容。有关如何解决此问题,请参阅第4章“准备发布内容以供搜索索引”。

需要考虑的一点是通道渲染脚本和包含指向其他发布的动态链接的发布内容。虽然这些脚本和发布内容自上次索引以来可能未更改,但由这些脚本生成的内容在每次调用发布内容之间可能会有所不同。如果这是您希望搜索的内容,您应该确保包含这些控件的发布内容始终被索引,方法是不要返回Last-Modified HTTP头。

Connector SearchMetaTagGenerator控件

我们需要进行的最后一次修改是添加一个与MCMS Connector for SharePoint Technologies一起提供的控件。SearchMetaTagGenerator输出标准和/或自定义页面属性。此外,我们可以使用它来控制输出哪些属性,甚至添加我们自己的自定义属性。将SearchMetaTagGenerator控件添加到模板非常简单。让我们将其添加到我们的Plant.aspx模板中。

  1. 在设计视图中打开Plant.aspx文件。
  2. 在工具箱中,选择“内容管理服务器”选项卡,然后将SearchMetaTagGenerator拖到模板的顶部。

    如果您在工具箱中看不到SearchMetaTagGenerator,并且已安装MCMS Connector for SharePoint Technologies,请右键单击工具箱并选择“添加/删除项”。在“自定义工具箱”对话框中,单击“浏览”,导航到Microsoft Content Management Server\Server\bin\目录,然后选择Microsoft.ContentManagement.SharePoint.WebControls.dll程序集。最后,在“自定义工具箱”对话框中单击“确定”。现在您应该能在工具箱中看到其他控件。

    如果您尚未安装MCMS Connector for SharePoint Technologies,请参阅附录B,“MCMS Connector for SharePoint Technologies”,了解下载和安装信息。

  3. 单击我们刚刚添加的SearchMetaTagGenerator控件,然后在属性窗口中,选择以下PropertyType之一:
    • CustomProperties:生成自定义页面属性的META标签。
    • StandardProperties:生成标准页面属性(如DisplayNameDisplayPath)的META标签。
    • CustomAndStandardProperties:为自定义和标准页面属性生成META标签(默认)。
    • PropertiesFromXMLFile:为SearchPropertyCollection.xml文件中指定的属性生成META标签。稍后将详细介绍。
  4. 现在,让我们选择CustomAndStandardProperties属性类型。

  5. 由于Visual Studio .NET设计器不允许我们将控件放入页面的<head></head>部分,因此我们需要将SearchMetaTagGenerator控件的代码声明从页面正文移到头部。切换到HTML视图,找到我们刚刚添加的SearchMetaTagGenerator控件,并将其移到<head></head>标签之间。
  6. 与任何更改一样,我们现在应该重新构建Tropical Green项目。
  7. 打开浏览器,浏览到站点中的植物目录部分的一个植物发布内容。花点时间查看您浏览到的发布内容的源代码。注意已添加的所有额外的META标签。例如:

请注意META标签顶部列出的FIRSTSAVEDBY属性。这是已添加到发布内容中的自定义属性。将其添加到META标签是因为我们在SearchMetaTagGenerator控件中选择了CustomAndStandardProperties属性类型。其他META标签是SearchMetaTagGenerator控件生成的标准属性。

渲染时,任何使用Plant模板实现的发布内容都将在页面<HEAD>部分包含页面自定义属性和标准属性的META标签。

PropertyType字段中,我们可以使用的项目之一是PropertiesFromXMLFile。此选项允许我们使用位于Microsoft Content Management Server\Server\IIS_CMS\WssIntegration\SearchPropertyCollection.xml的XML文件来精确指定将作为META标签导出的属性。

在指定要使用的属性(包括您添加的自定义属性)后,您需要告诉SharePoint在爬取中索引这些属性。MCMS Connector随附的控制台应用程序SearchPropertiesSetup.exe将告知SharePoint有关更新的XML文件的信息。使用以下语法运行它:

SearchPropertiesSetup.exe –file "<path to file>\SearchPropertyCollection.xml"

SearchPropertiesSetup.exe实用工具可以在以下位置找到:<install drive>:\Program Files\MCMS 2002 Connector for SharePoint Technologies\WSS\bin\

继续并按照上述方式执行SearchPropertiesSetup.exe实用工具,因为我们的自定义搜索解决方案将使用它生成的其中一个META标签。

如果您更改了SearchPropertyCollection.xml文件,则需要重新执行SearchPropertiesSetup.exe实用工具。

MCMS Connector for SharePoint Technologies包含一个帮助文件,其中包含有关如何修改XML文件的说明。请注意,存在一篇Microsoft支持知识库文章,其中涉及帮助文件说明中的错误。MSKB文章:“将SearchMetaTagGenerator控件添加到Content Management Server 2002 Connector for SharePoint Technologies的模板时出现问题”(#872932)包含已更正的说明。

我们的Tropical Green站点现在已配置为允许访客访问,我们的模板已修改为更适合SPS搜索,并且我们在所有呈现的发布内容的<HEAD>部分中包含了额外的元数据。现在,让我们继续在SharePoint中创建一个内容源来索引我们的站点。

配置SharePoint Portal Server搜索

当我们的MCMS站点准备好进行索引时,我们现在转向SPS。首先,我们将配置SharePoint以索引我们的Tropical Green站点。创建索引后,我们将创建一个包含内容源的源组。源组用于将内容源逻辑地分组在一起。在这种情况下,我们将有一个源组中的单个内容源。当我们将在Tropical Green站点中创建搜索逻辑时,我们将引用源组。

接下来的几个步骤假定您已在SPS中创建了门户。有关如何创建门户的说明,请参阅附录A,“在同一虚拟服务器上设置MCMS和SPS”。

虽然附录A详细介绍了如何配置一个虚拟服务器以同时托管MCMS站点和SharePoint门户,但本章中我们不这样做。我们需要两个虚拟服务器,一个用于www.tropicalgreen.net MCMS站点,另一个用于SharePointportal.tropicalgreen.net站点。附录A详细介绍了如何创建新的虚拟服务器和新的SharePoint Portal Server门户。

创建新的内容源

配置SPS搜索的第一步是创建内容源。一种方法是使用MCMS Connector随附的SearchSetup.exe命令行工具。该实用工具可在MCMS 2002 Connector for SharePoint Technologies\WSS\bin文件夹中找到。SearchSetup.exe实用工具在SharePoint中创建必要的内容源以及所有站点规则,以包含您站点层次结构中的根通道和所有顶级通道,以便包含和排除适当的内容。有关SearchSetup.exe实用工具的更多信息,请参阅MCMS Connector附带的帮助。

为了使用MCMS Connector搜索控件SearchInputControlSearchResultControl,您需要使用SearchSetup.exe实用工具在您的SharePoint门户中创建内容源和源组。这是因为MCMS Connector搜索控件是硬编码的,需要查找名为“CMSChannels”的特定SharePoint搜索组。要完成本章中的两个搜索示例,请按照本节中的步骤使用SearchSetup.exe实用工具创建两组内容源,并通过手动创建内容源。

使用MCMS Connector实用工具创建内容源

让我们使用MCMS Connector的SearchSetup.exe命令行实用工具来创建一个新的内容源和源组。

  1. 打开命令提示符,并将当前目录更改为以下MCMS Connector默认实用工具目录:
    cd "C:\Program Files\MCMS Connector for SharePoint Technologies\WSS\Bin"
  2. 输入以下命令以创建一个将索引我们的Tropical Green网站的新内容源,使用MCMS访客帐户来爬取内容,并在创建内容源后立即启动爬取(将用户和密码凭据替换为您的MCMS访客帐户凭据):
    searchsetup.exe -url "http://www.tropicalgreen.net/TropicalGreen/"

下表描述了每个可能的开关。

Switch

描述

url

SharePoint将用作爬取起点的MCMS URL。

crawl

指示SharePoint在创建内容源后是否立即执行爬取。

值为“1”指示SharePoint立即执行爬取。否则,将其设置为“0”以停止SharePoint爬取站点。

用户

具有MCMS内容访问权限以供索引的用户帐户。

密码

用户帐户的密码。

portalurl

将包含内容源的SharePoint门户服务器的URL。

您只需运行此命令行程序一次,而不是每次更新站点时都运行。如果您需要再次执行站点的完整爬取,可以通过重置内容源并执行完整爬取来完成。有关详细信息,请参阅SharePoint Portal Server文档。

现在我们已经创建了一个新的内容源,让我们创建一个新的搜索范围,以便更容易地测试我们的搜索结果。

创建新的搜索范围

在SharePoint索引我们的站点时,我们应该继续创建搜索范围。

  1. 通过浏览到您的门户并单击右上角的“站点设置”链接来打开“常规内容设置和索引状态”页面。在“搜索设置和索引内容”部分,单击“配置搜索和索引”链接。然后单击“管理搜索范围”链接。
  2. 在“管理搜索范围”页面上,单击“新建搜索范围”按钮。当提示创建新的搜索范围时,请输入以下内容:

    字段

    名称

    TropicalGreen.net (SearchSetup.exe)

    主题和区域

    在此范围内不包含任何主题或区域

    内容源组

    将范围限制为以下内容源组:CMSChannels

  3. 单击“确定”后,SharePoint将返回到“管理搜索范围”页面,其中包含我们的新范围。
  4. 让我们回到搜索配置页面。单击“管理搜索范围”页面标题中的“站点设置”链接。然后在“搜索设置和索引内容”部分下单击“配置搜索和索引”链接。
  5. 此时,我们应该确保一切都已正确配置。我们创建了一个内容源,并将其添加到新的站点组中。此时,SharePoint应该已经完成了对我们站点的索引(除非您添加了数百个发布内容)。查看“非门户内容”列。如果您看到错误、警告或零个文档已索引,请检查日志—某些错误可能根本不是错误,而其他错误可能表示MCMS站点本身存在错误。

    一个常见的错误“找不到地址”通常是由指向未配置使用通道渲染脚本的空通道的链接引起的。由于我们期望访客在浏览站点时遇到此错误,因此SharePoint爬虫程序遇到相同的问题并不奇怪。这不是SharePoint索引的问题,而是站点结构的问题:空通道应具有通道渲染脚本或隐藏在导航中。

  6. 如果没有问题,我们可以测试我们的索引。单击门户导航中的“主页”链接以进入主页。在右上角,在下拉列表中选择TropicalGreen.net(SearchSetup.exe)(由于下拉列表宽度的设计限制,可能不会显示完整名称),在搜索框中输入ficus,然后单击绿色箭头执行搜索。搜索结果应找到植物目录中的发布内容。

    您的搜索结果可能与上图所示不符,因为您的发布内容最近可能已被修改。

现在我们已经创建了一个SharePoint搜索范围并正在索引我们的Tropical Green站点。虽然可以在门户中使用此搜索范围来搜索我们的站点,但我们将通过MCMS站点中的SPS查询服务Web服务来使用它,为我们的用户提供搜索功能。

手动创建内容源

另一种选择是手动在SharePoint中创建内容源,而不是让SearchSetup.exe实用工具为我们创建。我们将逐步介绍这些步骤,以便您了解在SharePoint门户中创建内容源和源组涉及的内容。

尽管我们解释了如何使用SearchSetup.exe实用工具和手动创建内容源,但使用相同的名称,您必须选择一种方法,因为不可能创建两个名称相同的内容源。

让我们开始在我们的SharePoint门户中创建Tropical Green网站的索引。

有关创建门户的步骤,请参阅附录A。

  1. 通过指向“开始”|“所有程序”|“SharePoint Portal Server”|“SharePoint Central Administration”来启动SharePoint Central Administration。
  2. 在“门户站点和虚拟服务器配置”部分下,单击“列表和管理门户站点”。
  3. “管理门户站点”页面包含SharePoint场中所有门户的列表。将鼠标光标移到列表的右侧,然后单击鼠标光标悬停在门户上时出现的下拉箭头,然后选择“管理门户站点属性”(如下图所示)。

  4. 在“搜索设置和索引内容”部分下,单击“配置搜索和索引”链接。

    以下说明假定您未启用SharePoint的高级搜索管理模式。基本模式和高级模式之间的主要区别在于,高级模式允许您直接使用内容索引。基本模式在创建内容源时创建内容索引。在本例中,基本模式已足够。

现在我们将创建内容源。

  1. 在“常规内容设置和索引状态”部分下,单击“添加内容源”链接。
  2. 在“添加内容源”页面上,选择“网页”或“网站”,然后单击“下一步”。

  3. 选择要创建外部网站索引后,在“添加内容源:网页或网站”页面上输入以下信息。填写完表单后,单击“完成”。

    字段

    地址

    http://www.tropicalgreen.net/TropicalGreen/

    描述

    Tropical Green网站

    爬取配置

    此站点 – 跟踪此站点上的所有页面

    参与自适应更新

    Checked

    如果您打算将手动创建的内容源与MCMS Connector控件一起使用,则需要将内容源命名为“CMSChannels”,因为此名称在连接器控件中是硬编码的。

    在本例中,作为我们Tropical Green网站的MCMS Web入口点的虚拟服务器处理对http://www.tropicalgreen.net/的请求。如果您已将Tropical Green网站设置在https:///上,此示例仍然有效,您只需在步骤中进行适当的更改以指向正确的域。

  4. 单击上一步中的“完成”后,SharePoint将创建内容源并显示确认页面。在“已创建网页或网站内容源”的底部,“启动更新”部分,选中“启动完全更新”选项,然后单击“确定”。这将触发爬虫程序开始构建Tropical Green网站的索引。

手动创建内容源后,请按照上面“创建新的搜索范围”部分下的说明,使用下表中设置来创建一个新的源组。

字段

名称

TropicalGreen.net

主题和区域

在此范围内不包含任何主题或区域

内容源组

将范围限制为以下内容源组:

Tropical Green网站

MCMS应用程序池帐户的搜索权限

SharePoint门户通常不允许匿名用户访问站点,用户必须登录。MCMS Connector中包含的SearchResultControl(我们稍后将使用它)使用从触发搜索查询的MCMS站点的应用程序池标识帐户来访问SharePoint搜索服务。

  1. 打开Internet Explorer,浏览到我们之前创建的门户,并导航到http://portal.tropicalgreen.net。然后,单击右上角的“站点设置”。
  2. 在“常规设置”部分下,选择“管理安全性和其他设置”。
  3. 在“管理站点组”页面上,单击“添加站点组”。当提示输入有关新组的信息时,请输入以下值:

    属性

    站点组名

    仅搜索

    描述

    此站点组授予用户查询搜索索引的权限。

    权限

    搜索 – 搜索门户站点和所有相关内容

    当您选择“搜索 – 搜索门户站点和所有相关内容”时,SharePoint会自动选中“查看页面 – 查看区域中的页面”选项。选中“搜索”选项后,取消选中“查看页面”选项。

  4. 在“管理站点组”页面上,单击我们新组的名称“仅搜索”。
  5. 在““仅搜索”成员”页面上,单击“添加成员”。添加已配置为运行MCMS站点的应用程序池的标识的帐户。选择帐户后,单击“确定”。

    要查找运行MCMS站点的应用程序池的标识,请打开Internet Information Services。展开本地计算机 | 应用程序池节点。查找已配置为使用MCMS站点的应用程序池,并查看其属性。标识列在“标识”选项卡下。

  6. 选择帐户后,在“添加用户”页面上,确保在“第2步:选择站点组”部分下选中“仅搜索”,然后单击“确定”。

  7. 在最后一页,当SharePoint要求您确认您要添加的帐户的详细信息时,请确保取消选中“发送以下电子邮件以告知这些用户他们已被添加”选项,然后单击“完成”。

我们的MCMS站点现在具有登录门户并执行搜索所需的权限。

向MCMS站点添加搜索页面

我们有两种选项可以为我们的Tropical Green站点实现搜索功能:

  • 利用MCMS Connector for SharePoint Technologies中包含的ASP.NET服务器控件,这些控件允许执行搜索查询。
  • 创建我们自己的解决方案。

MCMS Connector包含以下三个控件,它们通过利用SharePoint搜索范围来协助您为MCMS站点实现搜索功能:

  • SearchInputControl:用于创建用于提交搜索的搜索表单输入。
  • SearchResultControl:获取在SearchInputControl中输入的搜索条件,通过SPS搜索Web服务执行搜索,并在列表中显示结果。
  • SearchMetaTagGenerator:根据PropertyType设置创建HTML META标签。生成的META标签可以包括标准页面属性以及自定义属性。

您可以在同一页面或不同的页面上使用这三个控件。这非常方便,因为您可能希望在站点上的所有页面上包含一个小的搜索关键字输入框,该输入框将搜索提交到单独的结果页面,但您可能也希望在搜索结果页面上提供搜索输入。

创建了一个可用的搜索页面后,我们将创建一个自定义解决方案,该解决方案不包含MCMS Connector提供的任何内容。我们的解决方案将包括一个针对我们站点的自定义搜索,以及一个自定义的搜索结果列表。

这两个选项都有其独特的优缺点。您将在MCMS站点上实现的选项将完全取决于您的需求、自定义需求和可用的开发时间。下表概述了使用MCMS Connector控件和自己构建解决方案的一些更突出的优缺点:

利用MCMS Connector控件实现搜索

优点

缺点

快速安装和集成到页面和模板中

不对搜索输入控件进行自定义

开箱即用,只需少量配置即可运行

不对搜索结果列表进行自定义

使用自定义解决方案实现搜索

优点

缺点

完全控制搜索输入表单的布局

需要额外的开发时间和测试

完全控制搜索结果列表

 

根据特定站点要求创建特殊的自定义搜索

 

使用MCMS SharePoint Connector进行搜索

为此,我们将首先在Tropical Green项目中创建一个新的搜索页面。此页面不是新的MCMS模板,而是常规的ASP.NET页面。您可以将其设为模板,但这并没有真正的优势,因为我们站点上只有一个搜索页面,没有额外的自定义内容。

  1. 在Visual Studio .NET中,右键单击Tropical Green项目,然后选择“添加Web窗体”。
  2. 将新的ASPX页面命名为Search.aspx,然后单击“打开”。
  3. 如果页面未在设计模式下加载,请单击左下角的“设计”。
  4. 将页面布局更改为FlowLayout
  5. 从解决方案浏览器将/Styles/styles.css/UserControls/TopMenu.ascx/UserControls/RightMenu.ascx文件拖到设计器上。
  6. 切换到HTML模式,并按如下方式修改body标签:
    <body topmargin="0" leftmargin="0" rightmargin="0">
  7. <form></form>标签之间添加以下代码,替换刚刚添加的两个用户控件:
    <form id="Form1" method="post" runat="server">
    <table width="100%" border="0" cellspacing="0" cellpadding="0">
      <tr>
        <td width="100%" colspan="2" valign="top" bgcolor="#ffcc00">
          <img src="/tropicalgreen/images/Logo.gif">
        </td>
        <td vAlign="top" rowSpan="10">&nbsp;</td>
      </tr>
      <tr bgColor="#66cc33">
        <td colSpan="2"><uc1:TopMenu id="TopMenu1" 
                runat="server"></uc1:TopMenu></td>
      </tr>
      <tr>
        <td vAlign="top" style="PADDING-RIGHT:30px; PADDING-LEFT:30px;
                                PADDING-BOTTOM:30px;">
          <p>&nbsp;</p>
          <table cellspacing="0" cellpadding="10" border="1"
                 bordercolor="#669900">
            <tr vAlign="top">
              <td>Tropical Green Search:</td>
            </tr>
            <tr>
              <td  XE "MCMS search:MCMS connector" vAlign="top">
              </td>
            </tr>
          </table>
        </td>
        <td class="RightMenuBar" width="20%" valign="top" height="100%"
            align="center" rowspan="2" bgcolor="#669900">
          <uc1:RightMenu id="RightMenu1" runat="server"></uc1:RightMenu>
        </td>
      </tr>
    </table>
    </form>

为什么我们将用户控件拖到页面上,然后再替换生成的HTML?

将用户控件拖到页面上会将<%@ Register %>行添加到ASPX文件,并添加用户控件的ASP.NET标签到HTML。然后我们只需要修改HTML以使其更具可读性。

现在,当你在设计模式下查看时,页面应该看起来像这样:

我们现在应该保存新的搜索页面,构建Tropical Green项目,并在浏览器中导航到它,以确保一切正常,然后再添加搜索输入和结果控件。

  1. 保存对search.aspx页面的所有更改。
  2. 右键单击TropicalGreen项目,然后选择“生成”。
  3. 如果没有生成错误,请打开浏览器并导航到:http://www.tropicalgreen.net/TropicalGreen/Search.aspx
  4. 如果存在任何问题,请回顾我们到目前为止所采取的步骤,解决错误,然后重试URL。

现在我们有了一个可用的搜索页面,我们需要为其添加一些功能。我们将添加两个MCMS Connector服务器控件,进行一些配置更改,构建解决方案,并测试我们的搜索页面。

  1. 如果search.aspx页面尚未打开,请在Visual Studio .NET中打开它,并切换到“设计”视图。
  2. 打开Visual Studio .NET工具箱,然后将SearchInputControlSearchResultsControl拖到“Tropical Green Search”单元格下的表格单元格中。有关放置位置,请参考下图:

  3. 选择我们添加到search.aspxSearchInputControl,并在Visual Studio .NET属性窗口中设置以下属性:

    属性

    SearchMode

    简单

    SearchResultPage

    /TropicalGreen/Search.aspx

  4. 选择我们添加到search.aspx页面的SearchResultControl,并使用Visual Studio .NET属性窗口设置以下属性:

    属性

    PortalUrl

    http://portal.tropicalgreen.net/

    SearchResultPageSize

    10

我们使用的是附录A中创建的门户URL。请将此URL替换为您在本章前面步骤中配置的内容源和搜索组的任何门户。

让我们看看我们的搜索是否有效。保存对search.aspx的所有更改,构建Tropical Green项目,并在浏览器中导航到http://www.tropicalgreen.net/TropicalGreen/Search.aspx。您应该看到一个类似于下图的页面:

输入一个您知道会在站点中找到的词,例如ficus。您将看到与在包含内容索引的门户中搜索相同字符串返回的结果列表。

如果您收到错误消息“加载输入控件时出现问题。系统返回的错误是:找不到路径的一部分c:\inetpub\wwwroot\tropicalgreen\cms\wssintegration\searchpropertycollection.xml”,请仔细检查您是否已在TropicalGreen Web应用程序中添加了CMS虚拟目录。

至此,我们已经通过MCMS Connector控件和SPS的搜索功能在我们的站点上实现了搜索功能。但是,此解决方案非常有限;例如,无法更改这些控件的外观和感觉,也无法配置结果页面中显示的属性,例如显示已返回文档的简短描述。

为了解决这个问题,我们将构建自己的搜索控件。

构建自定义搜索实现

如前所述,MCMS Connector搜索控件具有优缺点。最明显的是SearchResultControl不允许我们配置SPS搜索返回的结果。现在,我们将构建自己的搜索实现,它将利用SPS搜索Web服务,为我们的用户提供高级和专业搜索,并以可自定义的方式呈现结果。

关于SharePoint Portal Server查询服务

我们将要构建的一切都依赖于SPS中包含的Query Service Web Service,该服务将搜索功能公开给远程客户端,例如我们的网站。此Web服务接受Microsoft.Search.Query XML格式的请求,并以Microsoft.Search.Response XML格式返回响应。为了构建一个强大的解决方案,我们将提交的请求将使用Microsoft SQL语法进行全文搜索。Query Service提供的一种方法是QueryEx,我们将使用它,因为它以DataSet的形式返回结果。

有关Microsoft SharePoint Portal Server Query Service Web Service的更多信息和文档,请参阅MSDN文档

构建搜索输入控件

我们要做的第一件事是构建一个搜索输入控件,它会将搜索查询提交到一个页面进行处理。这个实现将允许我们快速地将一个小的搜索组件添加到我们所有的模板中。在提交搜索查询后,我们的用户控件将查询参数添加到查询字符串,并将请求重定向到结果页面。

首先,让我们开始创建一个新的用户控件。

  1. 在Visual Studio .NET中,右键单击Tropical Green项目中的User Controls文件夹,然后选择“添加”|“添加Web用户控件”。
  2. 将新控件命名为SearchInput.ascx
  3. 在设计模式下,将工具箱中的控件拖放到Web窗体上,并按如下方式排列:

    Control

    属性

    文本框

    ID = txtSearchInput

    Button

    ID = btnExecuteSearch

    Text = Go

    LinkButton

    ID = lnkAdvancedSearch

    Text = advanced search options

  4. 我们创建的LinkButton将用户带到搜索结果页面,我们稍后将在此页面添加一些自定义搜索功能。双击我们的LinkButton。Visual Studio .NET将为Click()事件创建一个空的事件处理程序。在此空事件处理程序中添加一行代码以将用户重定向到搜索结果页面。
    private void lnkAdvancedSearch_Click(object sender, System.EventArgs e)
    {
      Response.Redirect(Request.ApplicationPath + "/SearchResults.aspx");
    }
  5. 接下来,我们需要创建一个事件处理程序,用于用户单击“Go”按钮时。我们将获取在TextBox中输入的关键字,并将搜索请求发送到搜索结果页面。双击“Go”按钮,并向事件处理程序添加以下代码:

    private void btnExecuteSearch_Click(object sender, System.EventArgs e)
    {
      string keywords = this.txtSearchInput.Text;
      keywords = HttpUtility.UrlEncode(keywords);
      Response.Redirect(Request.ApplicationPath
                      + "/SearchResults.aspx?keywords="
                      + keywords);
    }

让我们看看我们新的搜索输入控件是否一切正常。保存更改并生成项目。如果您收到任何错误消息,请重做步骤,并确保没有拼写错误。

在使用此控件之前,我们需要将其添加到现有模板中。虽然我们理想情况下希望在所有页面上提供搜索(通常是通过将其添加到全局标题控件),但目前我们只将其添加到主页。

  1. 打开\Templates\HomePage.aspx模板,然后将我们的新SearchInput.ascx拖到顶部的单元格中,位于徽标的右侧。
  2. 切换到HTML视图,找到我们刚刚添加的控件。它可能有一个以uc1:SearchInput开头的标签。将此控件包装在一个HTMLDIV中,并将其对齐设置为right,如下面的代码所示:
    <td width="100%" colspan="2" valign="top" bgcolor="#ffcc00">
      <img src="/tropicalgreen/images/Logo.gif">&nbsp;
      <div align="right">
        <uc1:SearchInput id="SearchInput1" runat="server"></uc1:SearchInput>
      </div>
    </td>

HomePage.aspx模板现在应该看起来像这样:

高级搜索和结果页面

构建完搜索输入控件后,我们需要一个页面来执行针对SPS查询服务Web服务的搜索并显示结果。此外,像所有其他搜索结果页面一样,我们需要添加高级搜索选项,例如将搜索限制在Tropical Green植物目录。

在开始构建结果页面之前,我们需要添加对SPS查询服务Web服务的Web引用。

  1. 在Visual Studio .NET中,右键单击TropicalGreen项目,然后选择“添加Web引用”。
  2. 输入将检索搜索结果的Web服务的URL。查询服务的URL是http://[portal]/_vti_bin/search.asmx。在本例中,我们将使用附录A中创建的门户http://portal.tropicalgreen.net/_vti_bin/search.asmx。然后单击“转到”按钮。您可能会被提示输入用户ID和密码,因为这是SharePoint门户虚拟服务器的一部分,该服务器未配置为匿名访问。
  3. 一旦Web服务加载并显示了可用方法,“添加Web引用”对话框,单击“添加引用”按钮将Web服务添加到我们的项目中。

为简单起见,我们将创建的搜索结果页面不是CMS模板,而是Tropical Green项目根目录中的一个标准ASP.NET Web窗体。

  1. 右键单击项目,然后选择“添加”|“添加Web窗体”。
  2. 将新页面命名为SearchResults.aspx
  3. 在设计视图中,将Styles.css文件从解决方案浏览器拖到窗体上,以将样式表应用于页面。
  4. 将页面布局更改为FlowLayout
  5. 将以下用户控件拖到设计器中:
    • \UserControls\TopMenu.ascx
    • \UserControls\RightMenu.ascx
  6. 切换到HTML视图,并按如下方式修改body标签:
    <body topmargin="0" leftmargin="0">
  7. <form>标签之间添加以下HTML代码到页面,替换我们刚刚添加的两个控件:

    <form id="Form1" method="post" runat="server">
    <table width="100%" border="0" cellspacing="0" cellpadding="0">
      <tr>
        <td width="100%" colspan="2" valign="top" bgcolor="#ffcc00">
          <img src="/tropicalgreen/images/Logo.gif">
        </td>
        <td vAlign="top" rowSpan="10">
        </td>
      </tr>
      <tr bgColor="#66cc33">
        <td colSpan="2">
          <uc1:TopMenu id="TopMenu1" runat="server">
          </uc1:TopMenu>
        </td>
      </tr>
      <tr>
        <td vAlign="top" style="PADDING-RIGHT:30px; PADDING-LEFT:30px;
                                PADDING-BOTTOM:30px; PADDING-TOP:10px">
          <p>&nbsp;</p>
          <table cellspacing="0" cellpadding="10" border="1" 
                                                  bordercolor="#669900">
            <tr vAlign="top">
              <td>
                <b>Tropical Green Search:<b/>
              </td>
            </tr>
            <tr>
              <td vAlign="top">
                <b>Advanced Search</b>
                <p>
                <b>Search Results</b>
              </td>
            </tr>
          </table>
        </td>
        <td class="RightMenuBar" width="20%" valign="top" height="100%" 
                            align="center" rowspan="2" bgcolor="#669900">
          <uc1:RightMenu id="RightMenu1" runat="server">
          </uc1:RightMenu>
        </td>
      </tr>
    </table>
    </form>

现在我们已经为高级搜索和搜索结果页面有了基本布局,它看起来与其他站点模板相似。让我们添加一些控件以用于高级搜索。

  1. 在设计视图中,从工具箱拖动一个TextBox并将其放置在“高级搜索”文本下方。
  2. 在设计视图中,从工具箱拖动一个Button并将其放置在TextBox的右侧。
  3. 接下来我们需要添加一个DataGrid来包含搜索结果。在设计视图中,将一个DataGrid控件从工具箱拖到“在此处添加搜索结果”文本的正下方。我们稍后会处理格式化此控件,现在我们只需要一些东西来显示我们的数据。
  4. 根据下表设置我们刚刚添加的控件的属性:

    属性

    文本框

    ID = txtAdvancedSearch

    Button

    ID = btnAdvancedSearch

    Text = Go

    DataGrid

    ID = dgrSearchResults

现在,我们的高级搜索页面看起来应该像这样:

现在是时候开始编写我们的搜索逻辑了。首先,我们需要为高级搜索按钮添加一个事件处理程序。

  1. 在设计视图中,双击btnAdvancedSearch按钮以创建click事件处理程序。Visual Studio .NET将在代码隐藏文件中添加一个事件处理程序方法。
  2. btnAdvancedSearch_Click()事件处理程序添加以下代码:
    private void btnAdvancedSearch_Click(object sender, System.EventArgs e)
    {
      string keywords = this.txtAdvancedSearch.Text;
      keywords = HttpUtility.UrlEncode(keywords);
      Response.Redirect(Request.ApplicationPath 
                      + "/SearchResults.aspx?keywords="
                      + keywords);    
    }

接下来,我们需要在Page_Load()事件处理程序中检查查询字符串,看看是否有任何关键字是从我们的SearchInput.ascx控件或txtAdvancedSearchTextBox传递过来的。

添加以下代码以检查是否有任何关键字提供,如果有,则执行搜索:

private void Page_Load(object sender, System.EventArgs e)
{
  if (Request.QueryString["keywords"] != null
   && Request.QueryString["keywords"] != String.Empty)
  {
    string keywords = Request.QueryString["keywords"];
    DataSet ds = ExecuteSearch(keywords);
    this.dgrSearchResults.Visible = true;
    this.dgrSearchResults.DataSource = ds;
    this.dgrSearchResults.DataBind();

    // autofill the keyword input box with the search keywords
    this.txtAdvancedSearch.Text = keywords;  
  }
  else
  {
    this.dgrSearchResults.Visible = false;
  }
}

现在我们需要创建执行搜索针对SPS内容索引的方法。此方法将:

  1. 创建我们刚刚添加到项目中的Query Service Web服务的实例。
  2. 调用一个方法来构建MSQuery以提交给Query Service。
  3. 执行搜索。
  4. 将搜索结果绑定到DataGrid

SearchResults.aspx.cs文件中导入以下命名空间:

using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.ContentManagement.Publishing;

将以下方法添加到SearchResults.aspx.cs文件中的Page_Load()事件处理程序之后。此方法将确保当前线程在原始安全上下文中运行,而不考虑可能已调用的任何模拟。

// Get reference to the RevertToSelf method
[DllImport("ADVAPI32.DLL")]
public static extern int RevertToSelf();
 
/// <summary>
/// Builds the appropriate MSQuery,
/// submits the query to the SPS Query Service, 
/// and returns the results as a DataGrid.
/// </summary>
/// <param name="keywords">String of keywords to search for.</param>
/// <returns>DataSet of search results.</returns>
private DataSet ExecuteSearch(string keywords)
{
  // decode the list of keywords
  keywords = HttpUtility.UrlDecode(keywords);

  // create reference to the Query Service Web service
  net.tropicalgreen.portal.QueryService spsQueryService = 
                           new net.tropicalgreen.portal.QueryService();

  // use the current application pool identity to login
  // to the SharePoint Query Service Web service
  WindowsIdentity CurrentUser = WindowsIdentity.GetCurrent();

  try
  {
    // use the Application Pool account to do access the 
    // SharePoint Search Services
    RevertToSelf();
    spsQueryService.Credentials = CredentialCache.DefaultCredentials;
  }
  catch(System.Exception exception)
  {
    throw new System.Exception( XE "MCMS search:search" + 
        " and results page, advanced" exception.Message);
  }
  finally
  {
    // ensure that the original user is being impersonated again
    CurrentUser.Impersonate();
    CurrentUser = null;
  }

  // build MSQuery XML string to send to the Query Service
  // - change the content source to "CMSChannels" if you used SearchSetup.exe
  string msQuery = BuildMSQuery(keywords, "Tropical Green website");

  // execute the query and return the dataset
  return spsQueryService.QueryEx(msQuery);
}

如果您使用了SearchSetup.exe程序来创建内容源,则应在上面的代码中使用内容源组“CMSChannels”,而不是“Tropical Green website”。

我们的ExecuteSearch()方法调用另一个名为BuildMsQuery()的方法,该方法构造MSQuery以发送到QueryEx() Web方法。MSQuery由XML标签组成,这些标签为Query Service提供指令,例如返回结果的数量,以及Microsoft SQL全文(MSSQLFT)查询。构建MSSQLFT查询和MSQuery可能是实现SharePoint搜索中最复杂的任务。我们将将其分解为两个任务:构建实际的MSSQLFT查询和构建MSQuery XML字符串。我们将首先构建MSQuery将在XML字符串的构造中使用的全文查询,该XML字符串将发送到Query Service。

构建Microsoft SQL全文查询

SPS的搜索过程使用全文索引和查询来快速查找关键字,以便及时响应最终用户。全文查询与Microsoft SQL Server中的常规T-SQL查询非常相似,但您可以使用其他函数或谓词来增强查询功能。在搜索SharePoint索引时,其中一个谓词是有用的,即FREETEXT。FREETEXT接受以空格分隔的单词列表,确定哪些单词和短语是重要的,并利用这些信息构建内部查询以高效地搜索目标数据。

首先,您需要了解查询中可用的各种字段或属性。SharePoint在其门户的“站点设置”管理页面上提供了此信息的列表。

  1. 打开一个新的Internet Explorer实例,并导航到我们的门户:http://portal.tropicalgreen.net
  2. 单击右上角的“站点设置”链接。
  3. 在“搜索设置和索引内容”部分下,单击“管理从已爬取文档的属性”链接。

对于每个已爬取的文档,“已爬取内容属性管理”页面列出了SharePoint可能包含索引数据的属性。就我们而言,我们只关注下面的两个字段,因为它们包含我们搜索结果页面的信息:

  • DAV:href
  • DAV:getlastmodified

请注意,urn:schemas.microsoft.com:htmlinfo: metainfo组下的某些字段与我们使用MCMS Connector的SearchMetaTagGenerator用户控件添加到模板META标签的字段相同。

我们还需要的是我们创建的搜索范围的名称、内容索引的名称以及我们的关键字。一旦我们拥有了所有这些信息,就将MSSQLFT查询构建到自己的方法中以提高可读性。我们将调用此方法BuildMssqlftQuery(),并将包含搜索关键字的字符串和要查询的搜索范围传递给它。将以下方法添加到SearchResults.aspx.cs页面的末尾:

/// <summary>
/// Builds the Microsoft SQL FullText query based on the parms.
/// </summary>
/// <param name="keywords">Keywords submitted for search.</param>
/// <param name="searchScope">SPS Search scope to filter.</param>
/// <returns>String of the MSSQLFT query.</returns>
private string BuildMSsqlftQuery(string keywords, string searchScope)
{
  StringBuilder mssqlftQuery = new StringBuilder();
  ArrayList whereClause = new ArrayList();

  #region FILTER: keywords
  // list of keywords to include
  if (keywords != null && keywords.Length >0)
  {
    // add the keyword filter, use a calculated weighted field 
    // just as SPS does
    whereClause.Add(string.Format(" {0} {1}",
      "WITH (\"DAV:contentclass\":0,"
    + "\"urn:schemas.microsoft.com:fulltextqueryinfo:description\":0,"
    + "\"urn:schemas.microsoft.com:fulltextqueryinfo:sourcegroup\":0,"
    + "\"urn:schemas.microsoft.com:fulltextqueryinfo:cataloggroup\":0,"
    + "\"urn:schemas-microsoft-com:office:office#Keywords\":1.0,"
    + "\"urn:schemas-microsoft-com:office:office#Title\":0.9,"
    + "\"DAV:displayname\":0.9,"
    + "\"urn:schemas-microsoft-com:publishing:Category\":0.8,"
    + "\"urn:schemas-microsoft-com:office:office#Subject\":0.8,"
    + "\"urn:schemas-microsoft-com:office:office#Author\":0.7,"
    + "\"urn:schemas-microsoft-com:office:office#Description\":0.5,"
    + "\"urn:schemas-microsoft-com:sharepoint:portal:profile:"
    + "PreferredName\":0.2,contents:0.1,*:0.05) "
    + "AS #WeightedProps",
      "FREETEXT(#WeightedProps, '" +keywords.ToString().Trim() +"')")
      );
  }
  #endregion

  #region FILTER: sps source group
  // filter source group
  whereClause.Add(string.Format(" {0}", 
    "(\"urn:schemas.microsoft.com:fulltextqueryinfo:Sourcegroup\" = '"
    + searchScope +"')"));
  #endregion

  //build search query
  mssqlftQuery.Append("SELECT ");
  mssqlftQuery.Append("\"DAV:href\",");
  mssqlftQuery.Append("\"DAV:getlastmodified\"");
  mssqlftQuery.Append(" FROM Non_Portal_Content..SCOPE()");


  mssqlftQuery.Append(" WHERE ");
  int i=0;
  foreach (string s in whereClause)
  {
    if (i > 0)
      mssqlftQuery.Append(" AND ");
    mssqlftQuery.Append(s);
    i++;
  }
  return mssqlftQuery.ToString();
}

请注意,我们添加了一个计算字段,用于为某些字段应用特定的权重。这就是SharePoint实际执行其搜索的方式。您可以配置属性权重,以便在查询中为特定属性赋予更高的权重。例如,您可能希望赋予页面标题或HTML META标签中存储的关键字比页面内容更高的权重。

现在我们有了这个方法,让我们继续创建MSQuery字符串。我们将使用此方法来构造我们将发送到Query Service的MSQuery字符串。

构建MSQuery XML字符串

我们知道SPS Query Service Web Service接受一个参数:MSQuery字符串。此字符串实际上是一个XML文档,但它作为字符串传递给Query Service。此字符串中的XML标签告诉Query Service它支持的响应类型、在结果中返回多少记录以及搜索结果的起始索引。<StartAt></StartAt>元素是您可以在结果集分页时使用的。我们不会将分页集成到我们的站点中,因为站点较小,但您可以轻松看到如何做到。

让我们开始,通过创建我们的BuildMsQuery()方法,该方法返回一个完整的MSQuery XML字符串,其中包含执行SharePoint索引查询所需的所有信息。将以下方法添加到SearchResults.aspx.cs页面的末尾:

/// <summary>
/// Builds an MSQuery with an embedded MSSQLFT query embedded 
/// for submission to SharePointPS Query Service.
/// </summary>
/// <param name="keywords">Keywords submitted for search.</param>
/// <param name="searchScope">SPS Search scope to filter.</param>
/// <returns>MSQuery</returns>
public string BuildMSQuery(string keywords, string searchScope)
{
  StringBuilder msQuery = new StringBuilder();

  // create the main header of the XML string
  msQuery.Append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
               + "<QueryPacket xmlns=\"urn:Microsoft.Search.Query\" "
               + "Revision=\"1000\">"
               + "<Query domain=\"QDomain\">"
               + "<SupportedFormats>"
               + "<Format>urn:Microsoft.Search.Response.Document.Document"
               + "</Format></SupportedFormats>");

  // create the actual full-text query
  msQuery.Append("<Context>"
               + "<QueryText language=\"en-US\" type=\"MSSQLFT\">"
               + "<![CDATA[" + this.BuildMSsqlftQuery(keywords, searchScope)
               + "]]></QueryText></Context>");
  
  // create the range, page, and number of results
  // to return 


  msQuery.Append("<Range><StartAt>1</StartAt><Count>20</Count>"
               + "</Range></Query></QueryPacket>");

  return msQuery.ToString();
}

打开QueryPacket节点(QuerySupportedFormats)之后的MSQuery的两个节点不应修改。Context节点包含实际的搜索查询,您可以根据需要进行更改。最后一个节点Range包含用于告知SPS Query Service Web服务返回多少结果以及结果集的起始索引的指令。

例如,如果您每页显示20个结果,并且想要显示第三页的结果,则将StartAt节点设置为41,并将Count节点保留为20。

现在我们有了一个完整的MSQuery字符串,其中包含一个嵌入式全文查询。

让我们看看我们的搜索现在是否有效。构建Tropical Green项目并导航到http://www.tropicalgreen.net/。在搜索框中输入ficus,然后单击“Go”。您应该看到与下图类似的结果(我们稍后会使其更具可读性)。

优秀的搜索引擎提供的功能远不止关键词搜索。有些站点可以按主题过滤,有些则可以按产品过滤。在本例中,我们可以将所有搜索结果过滤到仅植物目录,排除网站的其他部分。使用 MCMS Connector 提供的控件,您将无法以用户友好的方式执行此操作。虽然了解情况的用户可能会意识到他们可以在“高级搜索”选项之一中输入 CMS 路径的一部分,但这对于普通网站访客来说并不直观。这就是您可以真正开始利用自定义搜索组件的地方。

让我们添加一个过滤器来仅搜索我们的植物目录

  1. 在“设计”视图中打开 SearchResults.aspx,然后将一个 CheckBox 拖到“高级搜索”文本框正下方,并为其分配以下属性

    属性

    CheckBox

    ID = chkFilterPlantCatalog

    Text = 仅搜索植物目录

  2. 打开 SearchResults.aspx 页面的代码隐藏文件,并将以下突出显示的代码添加到 btnAdvancedSearch_Click() 事件处理程序中
    private void btnAdvancedSearch_Click(object sender, System.EventArgs e)
    {
      string keywords = this.txtAdvancedSearch.Text;
      keywords = HttpUtility.UrlEncode(keywords);
    
      string filter = string.Empty;
      if (this.chkFilterPlantCatalog.Checked)
      {
        filter = "&filterPlantCatalog=1";
      }
    
      Response.Redirect(Request.ApplicationPath
                      + "/SearchResults.aspx?keywords=" + keywords + filter);
    }
  3. 将以下突出显示的代码添加到 BuildMSsqlftQuery() 方法中
    private string BuildMSsqlftQuery(string keywords, string searchScope)
    {
      System.Text.StringBuilder mssqlftQuery = 
                                            new System.Text.StringBuilder();
      ArrayList whereClause = new ArrayList();
    
      #region FILTER: keywords
      //  . . . code continues . . .
      #endregion
    
      #region FILTER: plant catalog
      // list of keywords to include
      if ( Request.QueryString["filterPlantCatalog"] != null
           && Request.QueryString["filterPlantCatalog"].ToString() == "1" )
      {
        whereClause.Add("(\"urn:schemas.microsoft.com:htmlinfo:metainfo:PATH"
                      + "\" LIKE '/channels/tropicalgreen/plantcatalog/%')");
      }
      #endregion
    
      //  . . . code continues . . .

    请注意,我们正在使用 urn:schemas.microsoft.com:htmlinfo:metainfo:PATH 索引属性,该属性由于 MCMS Connector 随附的 SearchPropertyCollection.xml 文件而映射到 CMS 频道路径。

  4. 让我们看看过滤器是如何工作的。保存更改并生成 Tropical Green 项目。生成完成后,打开浏览器并导航到 http://www.tropicalgreen.net/TropicalGreen/SearchResults.aspx。在文本框中输入 ficus,选中 仅搜索植物目录 CheckBox,然后单击“Go”按钮

太棒了!我们现在只看到 Tropical Green 植物目录中的记录!这很好地说明了过滤器的作用。我们可以按许多条件进行过滤,例如仅显示最近一个月或一周内更新的帖子。可能性几乎是无限的。

让我们看看是否可以通过删除 DataGrid 并用 Repeater 替换它来清理搜索结果。同时,我们将添加搜索结果过滤功能,以便用户只能看到他们有权访问的帖子。

尽管我们在全文查询中列出了许多 SharePoint 索引属性,但在主结果页面分析结果时,我们将仅使用 DAV:href 属性来获取对指定 MCMS 频道或帖子的引用,以确定用户是否有权浏览资源,以及确定并返回实际帖子的名称和描述。

  1. 在“设计”视图中打开 SearchResults.aspx 页面。删除 DataGrid
  2. 将一个 Repeater 对象拖到 DataGrid 所在的位置。为 Repeater 分配 IDrptSearchResults
  3. 在“设计”视图中,选择我们的新 Repeater 并打开“属性”窗口。在窗口顶部,单击“事件”按钮以显示我们可以使用的所有可能事件。双击 ItemDataBound 右侧的框,创建一个空事件处理程序,该处理程序将在每次将项绑定到 Repeater 时触发。
  4. 切换回 SearchResults.aspx 的 HTML 视图,然后滚动到我们的新 Repeater
  5. 将以下突出显示的标签添加到我们 RepeaterItemTemplate
    <asp:repeater id="rptSearchResults" runat="server">
    <ItemTemplate>
      <asp:Placeholder ID="phdSearchResult" Runat="server" visible="false">
        <p>
          <b><asp:HyperLink ID="hlkResultTitle" Runat="server" /></b>
          <br>
          <asp:Literal ID="litResultDescription" Runat="server" />
        </p>
      </asp:Placeholder>
    </ItemTemplate>
    </asp:repeater>

请注意我们为搜索结果添加的 ASP.NET Placeholder。我们将使用它来显示和隐藏用户有权查看或无权查看的结果。

现在我们有了一个 Repeater,其中包含一些内容占位符,我们需要修改我们的数据绑定,它仍然在使用 DataGrid

  1. 打开 SearchResults.aspx 的代码隐藏文件,找到 Page_Load() 事件处理程序,然后修改代码,如以下所示,将 DataSet 中唯一的 DataTable 绑定到 Repeater
    private void Page_Load(object sender, System.EventArgs e)
    {
      if (Request.QueryString["keywords"] != null 
       && Request.QueryString["keywords"].Length >0)
      {
        string keywords = Request.QueryString["keywords"];
        DataSet ds = ExecuteSearch(keywords);
        this.rptSearchResults.Visible = true;
        this.rptSearchResults.DataSource = ds.Tables[0].Rows;
        this.rptSearchResults.DataBind();
      }
      else
      {
        this.rptSearchResults.Visible = false;
      }
    }
  2. 在实现 ItemDataBound 事件之前,我们需要创建一个方法来尝试获取结果中返回的 URL 的 MCMS ChannellItem 引用。在刚才修改的 Page_Load() 事件处理程序之后添加以下方法
    private HierarchyItem GetResult(string url)
    {
      try
      {
        // check if it's a GUID based URL
        if (url.IndexOf("RDONLYRES") >= 0)
        {
          // try to get the GUID if it's a RDONLYRES URL
          string guidRegEx = "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-"
                           + "[a-fA-F0-9]{4}-[a-fA-F0-9]{12}";
          Regex regex = new Regex(guidRegEx);
          Match m = regex.Match(url);
          if (m.Success)
          {
            return CmsHttpContext.Current.Searches.GetByGuid("{"+m.Value+"}");
          }
    
    
        }
        else
        {
          // try to get the object via the URL
          return CmsHttpContext.Current.Searches.GetByUrl(url);
        }
        // if this point reached, unknown URL
        return null;
      }
      catch
      {
        return null;
      }
    }
  3. 现在,找到 rptSearchResults_ItemDataBound() 事件处理程序。我们需要捕获事件,当它将数据项绑定到 Repeater 中的 ItemTemplateAlternateItemTemplate 时。然后,我们将获取对绑定到模板的数据项的引用(在本例中为 DataRow),并获取我们添加到模板中的 ASP.NET 对象的引用。最后,我们将使用 DataRow 中的数据填充控件的属性。以下是我们完成的 ItemDataBound() 事件处理程序的外观
    private void rptSearchResults_ItemDataBound(object sender, 
                 System.Web.UI.WebControls.RepeaterItemEventArgs e)
    {
      if ( (e.Item.ItemType == ListItemType.AlternatingItem) 
        || (e.Item.ItemType == ListItemType.Item) )
      {
        // get a reference to the datarow being bound
        DataRow row = e.Item.DataItem as DataRow;
        HierarchyItem hi = GetResult(row[0].ToString());
    
        // get references to all the ASP.NET objects
        PlaceHolder resultContainer = e.Item.FindControl("phdSearchResult")
                                                 as PlaceHolder;
        HyperLink resultTitle = e.Item.FindControl("hlkResultTitle") 
                                                 as HyperLink;
        Literal resultDesc = e.Item.FindControl("litResultDescription") 
                                                 as Literal;
    
        // if the URL doesn't resolve to an MCMS resource, 
        // output it to the results
        if (hi != null)
        {
          // user has rights to this item so display it.
          resultContainer.Visible = true;
        
          // use values in DataRow to populate objects
          resultDesc.Text = hi.Description;
          if (hi is ChannelItem)
          {
            resultTitle.Text = (hi as ChannelItem).DisplayName;
            resultTitle.NavigateUrl = (hi as ChannelItem).Url;
          }
          else
          {
            if (hi is Resource)
              resultTitle.NavigateUrl = (hi as Resource).Url;
            resultTitle.Text = hi.Name;
          }
        }
      }
    }

最终结果看起来大致如此

您会发现描述字段可能不完全符合我们的预期,但这种技术使我们能够随心所欲地自定义搜索结果列表。您可以直接从索引值中提取帖子的描述,前提是您通过 SearchPropertyCollection.xml 文件公开了页面描述。或者,您可以在所有模板中有一个名为“搜索描述”的 HtmlPlaceholder,内容所有者可以使用它来输入一个描述,以便在帖子出现在搜索结果中时显示。因此,您会发现描述字段可能不完全符合我们的预期,但这种技术使我们能够随心所欲地自定义搜索结果列表。

摘要

在本章中,我们讨论了 MCMS 开发人员为其网站添加搜索功能可用的一些选项。我们接着深入研究了 SharePoint Portal Server 内置的搜索功能,以及如何将其用作 MCMS 网站的后端搜索引擎。在开始添加搜索功能之前,我们必须对我们的网站和模板进行一些更改,并使用 SharePoint 构建索引来抓取我们的网站。

一旦我们的网站配置为索引抓取,并且 SharePoint 配置为抓取我们的网站并构建索引,我们就详细探讨了使用 SharePoint 爬虫为 Tropical Green 网站添加搜索功能的两种选项

  • 首先,我们使用 MCMS Connector for SharePoint Technologies(一个开箱即用的解决方案)实现了搜索。
  • 然后,我们使用 SharePoint Query Service Web 服务和自定义全文 T-SQL 查询构建了自己的解决方案,以提供搜索过滤器和自定义结果。
© . All rights reserved.