在 Exchange 中将搜索筛选器与 EWS 配合使用

了解如何将搜索筛选器与 Exchange 中的 EWS 托管 API 或 EWS 配合使用。

搜索筛选器是在 EWS 托管 API 或 EWS 应用程序中表达搜索条件的主要工具。 建议使用搜索筛选器(而不是 查询字符串)执行以下操作:

  • 搜索特定属性或属性集。
  • 使用多个搜索条件进行搜索。

如果正在执行以下任一操作,则搜索筛选器是唯一的选项:

  • 搜索自定义属性。
  • 执行区分大小写的字符串搜索。
  • 执行前缀或完全匹配字符串搜索。
  • 执行位掩码搜索。
  • 搜索具有特定属性集的项,而不考虑值。
  • 搜索文件夹。
  • 创建搜索文件夹。

确定所需的搜索筛选器类型

在创建搜索筛选器之前,请先确定所需的筛选器类型。 筛选器类型在 EWS 托管 API 中作为 SearchFilter 类的后代类实现,并在 EWS 中作为 Restriction 元素的子元素实现。

表 1. 搜索筛选器的类型

筛选器类型 EWS 托管 API 类 EWS 元素 说明
包含筛选器
ContainsSubstring
Contains
用于字符串比较的最佳筛选器类型。 它允许你控制区分大小写、是否忽略空格并设置包含模式。
位掩码筛选器
ExcludesBitmask
不包括
允许将整数属性搜索为位掩码,并仅返回具有与指定位掩码对应的位取消设置的结果。
存在筛选器
Exists
Exists
返回具有指定属性的所有项,而不考虑值。
相等筛选器
IsEqualTo
IsNotEqualTo
IsEqualTo
IsNotEqualTo
将指定属性的值与指定的常量值或另一个属性的值进行比较,并返回在 IsEqualTo 筛选器) 的情况下具有相等值 (的所有项,或者在 IsNotEqualTo 筛选器) 的情况下 (非相等值的所有项。
关系测试筛选器
IsGreaterThan
IsGreaterThanOrEqualTo
IsLessThan
IsLessThanOrEqualTo
IsGreaterThan
IsGreaterThanOrEqualTo
IsLessThan
IsLessThanOrEqualTo
返回与指定常量值或其他属性的适当关系中具有指定属性值的所有项。 例如, IsGreaterThan 筛选器返回值大于指定属性中的指定值的所有项。
否定筛选器
Not
Not
求反其他筛选器的结果。
复合筛选器
SearchFilterCollection
And
Or
合并多个筛选器,允许使用更复杂的搜索条件。

包含筛选器

包含筛选器是搜索字符串属性的最佳选择。 使用包含筛选器,可以通过设置包含模式和比较模式来控制字符串匹配的各个方面,例如区分大小写和如何处理空格。

包含 EWS 托管 API 中的筛选器

如果使用 EWS 托管 API,请使用 ContainsSubstring 类的 ContainmentMode 属性设置包含模式,并使用 ContainsSubstring 类的 ComparisonMode 属性设置比较模式。 以下示例演示如何创建搜索筛选器,用于搜索子字符串“会议笔记”的项目主题字段。 此示例忽略大小写,但不忽略空格。

// Find all items with a subject that contain the substring
// "meeting notes", regardless of case.
// Matches include:
//   - meeting notes
//   - Meeting Notes
//   - Here are my meeting notes
SearchFilter.ContainsSubstring subjectFilter = new SearchFilter.ContainsSubstring(ItemSchema.Subject,
    "meeting notes", ContainmentMode.Substring, ComparisonMode.IgnoreCase);

包含 EWS 中的筛选器

在 EWS 中,通过使用 Contains 元素上的 ContainmentMode 属性来设置包含模式,并使用 Contains 元素上的 ContainmentComparison 属性来设置比较模式。 以下示例演示如何创建搜索筛选器,以搜索子字符串“会议笔记”的项目的主题字段。 此示例忽略大小写,但不忽略空格。

<t:Contains ContainmentMode="Substring" ContainmentComparison="IgnoreCase">
  <t:FieldURI FieldURI="item:Subject" />
  <t:Constant Value="meeting notes" />
</t:Contains>

位掩码筛选器

通过位掩码筛选器,可以将整数属性作为位掩码进行搜索,并返回未在指定属性的值中设置特定位的结果。

EWS 托管 API 中的位掩码筛选器

以下示例演示如何使用 EWS 托管 API 创建搜索筛选器,以返回在“示例:使用搜索筛选器查找项”中定义的 ItemIndex 自定义属性 (中具有值的所有项,本文的 EWS 托管 API 部分) 二进制) 中没有第二个位 (10。

// Find all items with a value of the custom property that does not
// have the second bit (0010) set.
// Matches include:
//   - Property not set
//   - 1 (0001)
//   - 4 (0100)
//   - 5 (0101)
//   - 8 (1000)
SearchFilter.ExcludesBitmask bit2NotSetFilter = 
    new SearchFilter.ExcludesBitmask(customPropDefinition, 2);

EWS 中的位掩码筛选器

以下示例演示如何使用 EWS 创建搜索筛选器,以返回在“示例:使用搜索筛选器查找项”中定义的 ItemIndex 自定义属性 (中具有值的所有项,本文的 EWS 托管 API 部分) 二进制) 中没有第二个位 (10。

<t:Excludes>
  <t:ExtendedFieldURI PropertySetId="aa3df801-4fc7-401f-bbc1-7c93d6498c2e" PropertyName="ItemIndex" PropertyType="Integer" />
  <t:Bitmask Value="2" />
</t:Excludes>

存在筛选器

通过存在筛选器,可以搜索具有特定属性的项,而不考虑值。

EWS 托管 API 中的存在筛选器

以下示例演示如何创建搜索筛选器以返回设置了 ItemIndex 自定义属性的所有项。

// Find all items that have the custom property set.
SearchFilter.Exists customPropSetFilter =
    new SearchFilter.Exists(customPropDefinition);

EWS 中的存在筛选器

以下示例演示如何创建搜索筛选器以返回设置了 ItemIndex 自定义属性的所有项。

<t:Exists>
  <t:ExtendedFieldURI PropertySetId="aa3df801-4fc7-401f-bbc1-7c93d6498c2e" PropertyName="ItemIndex" PropertyType="Integer" />
</t:Exists>

相等筛选器

通过相等筛选器,可以搜索指定属性值等于特定值或不等于特定值的所有项。 要比较的值可以是常量值,也可以是每个项上另一个属性的值。

EWS 托管 API 中的相等筛选器

以下示例演示如何使用 EWS 托管 API 创建搜索筛选器以返回尚未读取的所有项。

// Find all items that are not marked as read.
SearchFilter.IsEqualTo unreadFilter =
    new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false);

以下示例演示如何创建搜索筛选器,以返回 ItemIndex 属性中值不等于项大小的所有项。

// Find all items that are marked as read.
SearchFilter.IsNotEqualTo indexNotEqualToSizeFilter =
    new SearchFilter.IsNotEqualTo(customPropDefinition, ItemSchema.Size);

EWS 中的相等筛选器

以下示例演示如何使用 EWS 创建搜索筛选器以返回所有尚未读取的项目。

<t:IsEqualTo>
  <t:FieldURI FieldURI="message:IsRead" />
  <t:FieldURIOrConstant>
    <t:Constant Value="false" />
  </t:FieldURIOrConstant>
</t:IsEqualTo>

以下示例演示如何创建搜索筛选器,以返回 ItemIndex 属性中值不等于项大小的所有项。

<t:IsNotEqualTo>
  <t:ExtendedFieldURI PropertySetId="aa3df801-4fc7-401f-bbc1-7c93d6498c2e" PropertyName="ItemIndex" PropertyType="Integer" />
  <t:FieldURIOrConstant>
    <t:FieldURI FieldURI="item:Size" />
  </t:FieldURIOrConstant>
</t:IsNotEqualTo>

关系测试筛选器

通过关系测试筛选器,可以搜索指定属性中值大于 () > 、大于或等于 (>=) 、小于 (<) 或小于或等于 (<=) 指定值的所有项。 要比较的值可以是常量值,也可以是每个项上另一个属性的值。

EWS 托管 API 中的关系测试筛选器

以下示例演示如何使用 EWS 托管 API 创建搜索筛选器,以返回 ItemIndex 属性中具有与常量值 3 的指定关系的所有项。

// Find all items where the custom property value is > 3.
SearchFilter.IsGreaterThan greaterThanFilter =
    new SearchFilter.IsGreaterThan(customPropDefinition, 3);
// Find all items where the custom property value is >= 3.
SearchFilter.IsGreaterThanOrEqualTo greaterThanOrEqualFilter =
    new SearchFilter.IsGreaterThanOrEqualTo(customPropDefinition, ItemSchema.Size);
// Find all items where the custom property value is < 3.
SearchFilter.IsLessThan lessThanFilter =
    new SearchFilter.IsLessThan(customPropDefinition, 3);
// Find all items where the custom property value is <= 3.
SearchFilter.IsLessThanOrEqualTo lessThanOrEqualFilter =
    new SearchFilter.IsLessThanOrEqualTo(customPropDefinition, 3);

EWS 中的关系测试筛选器

以下示例演示如何使用 EWS 创建搜索筛选器,以返回 ItemIndex 属性中值大于常量值 3 的所有项。

<t:IsGreaterThan>
  <t:ExtendedFieldURI PropertySetId="aa3df801-4fc7-401f-bbc1-7c93d6498c2e" PropertyName="ItemIndex" PropertyType="Integer" />
  <t:FieldURIOrConstant>
    <t:Constant Value="3" />
  </t:FieldURIOrConstant>
</t:IsGreaterThan>

以下示例演示如何创建搜索筛选器,以返回 ItemIndex 属性中值大于或等于常量值 3 的所有项。

<t:IsGreaterThanOrEqualTo>
  <t:ExtendedFieldURI PropertySetId="aa3df801-4fc7-401f-bbc1-7c93d6498c2e" PropertyName="ItemIndex" PropertyType="Integer" />
  <t:FieldURIOrConstant>
    <t:Constant Value="3" />
  </t:FieldURIOrConstant>
</t:IsGreaterThanOrEqualTo>

以下示例演示如何创建搜索筛选器,以返回 ItemIndex 属性中值小于常量值 3 的所有项。

<t:IsLessThan>
  <t:ExtendedFieldURI PropertySetId="aa3df801-4fc7-401f-bbc1-7c93d6498c2e" PropertyName="ItemIndex" PropertyType="Integer" />
  <t:FieldURIOrConstant>
    <t:Constant Value="3" />
  </t:FieldURIOrConstant>
</t:IsLessThan>

以下示例演示如何创建搜索筛选器,以返回 ItemIndex 属性中值小于或等于常量值 3 的所有项。

<t:IsLessThanOrEqualTo>
  <t:ExtendedFieldURI PropertySetId="aa3df801-4fc7-401f-bbc1-7c93d6498c2e" PropertyName="ItemIndex" PropertyType="Integer" />
  <t:FieldURIOrConstant>
    <t:Constant Value="3" />
  </t:FieldURIOrConstant>
</t:IsLessThanOrEqualTo>

否定筛选器

使用否定筛选器可以否定另一个筛选器并获取相反的搜索结果。 当其他筛选器返回与特定条件匹配的结果时,否定筛选器返回的结果与应用该筛选器所指定的条件不匹配。

EWS 托管 API 中的否定筛选器

以下示例演示如何使用 EWS 托管 API 创建搜索筛选器,以返回主题中没有子字符串“会议笔记”的所有项目。

SearchFilter.ContainsSubstring subjectFilter = new SearchFilter.ContainsSubstring(ItemSchema.Subject,
    "meeting notes", ContainmentMode.Substring, ComparisonMode.IgnoreCase);
SearchFilter.Not subjectNotFilter =
    new SearchFilter.Not(subjectFilter);

在 EWS 中否定筛选器

以下示例演示如何创建搜索筛选器以返回主题中没有子字符串“会议笔记”的所有项目。

<t:Not>
  <t:Contains ContainmentMode="ExactPhrase" ContainmentComparison="IgnoreCase">
    <t:FieldURI FieldURI="item:Subject" />
    <t:Constant Value="meeting notes" />
  </t:Contains>
</t:Not>

复合筛选器

使用复合筛选器可以组合多个筛选器来创建更复杂的搜索条件。 可以使用逻辑运算符 AND 或 OR 组合条件。 通过这种方式,可以执行“来自萨迪·丹尼尔斯的所有邮件,主题中包含'会议笔记'”之类的搜索。

EWS 托管 API 中的复合筛选器

以下示例演示如何使用 EWS 托管 API 创建搜索筛选器,该筛选器返回从 Sadie Daniels 发送的所有项目,并在主题中包含“会议笔记”。

SearchFilter.ContainsSubstring subjectFilter = new SearchFilter.ContainsSubstring(ItemSchema.Subject,
    "meeting notes", ContainmentMode.Substring, ComparisonMode.IgnoreCase);
EmailAddress manager = new EmailAddress("sadie@contoso.com");
SearchFilter.IsEqualTo fromManagerFilter =
    new SearchFilter.IsEqualTo(EmailMessageSchema.Sender, manager);
SearchFilter.SearchFilterCollection compoundFilter =
    new SearchFilter.SearchFilterCollection(LogicalOperator.And, subjectFilter, fromManagerFilter);

EWS 中的复合筛选器

以下示例演示如何使用 EWS 创建搜索筛选器,该筛选器返回从 Sadie Daniels 发送的所有项目,并在主题中包含“会议笔记”。

<t:And>
  <t:Contains ContainmentMode="Substring" ContainmentComparison="IgnoreCase">
    <t:FieldURI FieldURI="item:Subject" />
    <t:Constant Value="meeting notes" />
  </t:Contains>
  <t:IsEqualTo>
    <t:FieldURI FieldURI="message:Sender" />
    <t:FieldURIOrConstant>
      <t:Constant Value="sadie@fourthcoffee.com" />
    </t:FieldURIOrConstant>
  </t:IsEqualTo>
</t:And>

示例:使用搜索筛选器和 EWS 托管 API 查找项

以下 EWS 托管 API 方法使用搜索筛选器:

以下示例使用 ExchangeService.FindItems 方法;但是,相同的规则和概念适用于所有方法。 在此示例中,定义了一个名为 SearchWithFilter 的方法 。 它采用 ExchangeService 对象、 WellKnownFolderName 对象和 SearchFilter 对象作为参数。 此示例假定 ExchangeService 对象已使用凭据的有效值和 Url 属性进行了初始化。 SearchFilter 类是所有不同搜索筛选器的基类。

using Microsoft.Exchange.WebServices.Data
private static Guid SearchTestGUID = new Guid("{AA3DF801-4FC7-401F-BBC1-7C93D6498C2E}");
private static ExtendedPropertyDefinition customPropDefinition =
        new ExtendedPropertyDefinition(SearchTestGUID, "ItemIndex", MapiPropertyType.Integer);
static void SearchWithFilter(ExchangeService service, WellKnownFolderName folder, SearchFilter filter)
{
    // Limit the result set to 10 items.
    ItemView view = new ItemView(10);
    view.PropertySet = new PropertySet(ItemSchema.Subject, 
                                       ItemSchema.DateTimeReceived,
                                       EmailMessageSchema.IsRead,
                                       customPropDefinition);
    // Item searches do not support Deep traversal.
    view.Traversal = ItemTraversal.Shallow;
    // Sorting.
    view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Descending);
    try
    {
        FindItemsResults<Item> results = service.FindItems(folder, filter, view);
        foreach (Item item in results.Items)
        {
            Console.WriteLine("Subject: {0}", item.Subject);
            Console.WriteLine("Id: {0}", item.Id.ToString());
            if (item.ExtendedProperties.Count > 0 &&
                 item.ExtendedProperties[0].PropertyDefinition == customPropDefinition)
            {
                Console.WriteLine("Search Index: {0}", item.ExtendedProperties[0].Value);
            }
            if (item is EmailMessage)
            {
                EmailMessage message = item as EmailMessage;
                Console.WriteLine("Read: {0}", message.IsRead.ToString());
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine("Exception while enumerating results: {0}", ex.Message);
    }
}

可以将此函数与本文示例中所示的任何搜索筛选器一起使用。 此示例使用复合筛选器从 Sadie Daniels 返回收件箱中的所有项目,主题中带有“会议笔记”。

SearchFilter.ContainsSubstring subjectFilter = new SearchFilter.ContainsSubstring(ItemSchema.Subject,
    "meeting notes", ContainmentMode.Substring, ComparisonMode.IgnoreCase);
EmailAddress manager = new EmailAddress("sadie@contoso.com");
SearchFilter.IsEqualTo fromManagerFilter =
    new SearchFilter.IsEqualTo(EmailMessageSchema.Sender, manager);
SearchFilter.SearchFilterCollection compoundFilter =
    new SearchFilter.SearchFilterCollection(LogicalOperator.And, subjectFilter, greaterThanFilter);
SearchWithFilter(service, WellKnownFolderName.Inbox, compoundFilter);

示例:使用搜索筛选器和 EWS 查找项

以下 EWS 操作使用搜索筛选器:

以下示例使用 FindItem 操作;但是,相同的规则和概念适用于这两个操作。 搜索筛选器包含在 SOAP 请求中的 Restriction 元素中。 此示例发送一个 SOAP 请求,该请求等效于上述 EWS 托管 API 示例中显示的搜索。

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
    xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types" 
    xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2013" />
  </soap:Header>
  <soap:Body>
    <m:FindItem Traversal="Shallow">
      <m:ItemShape>
        <t:BaseShape>IdOnly</t:BaseShape>
        <t:AdditionalProperties>
          <t:FieldURI FieldURI="item:Subject" />
          <t:FieldURI FieldURI="item:DateTimeReceived" />
          <t:FieldURI FieldURI="message:IsRead" />
          <t:ExtendedFieldURI PropertySetId="aa3df801-4fc7-401f-bbc1-7c93d6498c2e" PropertyName="ItemIndex" PropertyType="Integer" />
        </t:AdditionalProperties>
      </m:ItemShape>
      <m:IndexedPageItemView MaxEntriesReturned="10" Offset="0" BasePoint="Beginning" />
      <m:Restriction>
        <t:And>
          <t:Contains ContainmentMode="Substring" ContainmentComparison="IgnoreCase">
            <t:FieldURI FieldURI="item:Subject" />
            <t:Constant Value="meeting notes" />
          </t:Contains>
          <t:IsEqualTo>
            <t:FieldURI FieldURI="message:Sender" />
            <t:FieldURIOrConstant>
              <t:Constant Value="sadie@contoso.com" />
            </t:FieldURIOrConstant>
          </t:IsEqualTo>
        </t:And>
      </m:Restriction>
      <m:SortOrder>
        <t:FieldOrder Order="Descending">
          <t:FieldURI FieldURI="item:DateTimeReceived" />
        </t:FieldOrder>
      </m:SortOrder>
      <m:ParentFolderIds>
        <t:DistinguishedFolderId Id="inbox" />
      </m:ParentFolderIds>
    </m:FindItem>
  </soap:Body>
</soap:Envelope>

以下示例显示了来自服务器的响应,包括搜索结果。

<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="15" MinorVersion="0" MajorBuildNumber="712" MinorBuildNumber="22" Version="V2_3" 
        xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns="https://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:FindItemResponse xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
        xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:FindItemResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:RootFolder IndexedPagingOffset="3" TotalItemsInView="3" IncludesLastItemInRange="true">
            <t:Items>
              <t:Message>
                <t:ItemId Id="AAMkAGM2..." ChangeKey="CQAAABYA..." />
                <t:Subject>meeting notes</t:Subject>
                <t:DateTimeReceived>2013-11-20T21:18:51Z</t:DateTimeReceived>
                <t:ExtendedProperty>
                  <t:ExtendedFieldURI PropertySetId="aa3df801-4fc7-401f-bbc1-7c93d6498c2e" PropertyName="ItemIndex" PropertyType="Integer" />
                  <t:Value>5</t:Value>
                </t:ExtendedProperty>
                <t:IsRead>true</t:IsRead>
              </t:Message>
              <t:Message>
                <t:ItemId Id="AAMkAGM2..." ChangeKey="CQAAABYA..." />
                <t:Subject>Meeting Notes</t:Subject>
                <t:DateTimeReceived>2013-11-20T21:18:51Z</t:DateTimeReceived>
                <t:ExtendedProperty>
                  <t:ExtendedFieldURI PropertySetId="aa3df801-4fc7-401f-bbc1-7c93d6498c2e" PropertyName="ItemIndex" PropertyType="Integer" />
                  <t:Value>6</t:Value>
                </t:ExtendedProperty>
                <t:IsRead>true</t:IsRead>
              </t:Message>
              <t:Message>
                <t:ItemId Id="AAMkAGM2..." ChangeKey="CQAAABYA..." />
                <t:Subject>Meeting notes</t:Subject>
                <t:DateTimeReceived>2013-11-20T21:18:51Z</t:DateTimeReceived>
                <t:ExtendedProperty>
                  <t:ExtendedFieldURI PropertySetId="aa3df801-4fc7-401f-bbc1-7c93d6498c2e" PropertyName="ItemIndex" PropertyType="Integer" />
                  <t:Value>7</t:Value>
                </t:ExtendedProperty>
                <t:IsRead>true</t:IsRead>
              </t:Message>
            </t:Items>
          </m:RootFolder>
        </m:FindItemResponseMessage>
      </m:ResponseMessages>
    </m:FindItemResponse>
  </s:Body>
</s:Envelope>

后续步骤

熟悉在基本搜索中使用搜索筛选器后,可以继续使用更高级的搜索技术。

另请参阅