Поделиться через


Использование фильтров поиска с EWS в Exchange

Узнайте, как использовать фильтры поиска с управляемым API EWS или EWS в Exchange.

Фильтры поиска — это основное средство для выражения условий поиска в управляемом API EWS или приложении EWS. Мы рекомендуем использовать фильтры поиска, а не строки запроса, чтобы сделать следующее:

  • Поиск по определенному свойству или набору свойств.
  • Поиск с помощью нескольких условий поиска.

Фильтры поиска являются единственным вариантом, если вы выполняете одно из следующих действий:

  • Поиск пользовательских свойств.
  • Выполнение поиска строк с учетом регистра.
  • Выполнение поиска по строкам префикса или точного соответствия.
  • Выполнение поиска по битовой маске.
  • Поиск элементов с определенным набором свойств, независимо от значения.
  • Поиск папок.
  • Создание папок поиска.

Определение нужного типа фильтра поиска

Перед созданием фильтра поиска сначала определите нужный тип фильтра. Типы фильтров реализуются как классы-потомки класса SearchFilter в управляемом API EWS и как дочерние элементы элемента Restriction в EWS.

Таблица 1. Типы фильтров поиска

Тип фильтра Класс Управляемого API EWS Элемент 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
Объединяет несколько фильтров, что позволяет использовать более сложные критерии поиска.

Содержит фильтр

Фильтр contains — лучший вариант для поиска строковых свойств. С помощью фильтра contains можно управлять аспектами сопоставления строк, такими как чувствительность к регистру и способ обработки пробелов, задав режим сдерживания и режим сравнения.

Содержит фильтр в управляемом API EWS.

Если вы используете управляемый API EWS, вы задаете режим хранения с помощью свойства ContainmentMode класса ContainsSubstring , а режим сравнения — с помощью свойства ComparisonMode класса ContainsSubstring . В следующем примере показано, как создать фильтр поиска, который ищет в поле темы элементов подстроку "заметки о собрании". В этом примере игнорируется регистр, но не игнорируется пробел.

// 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 режим хранения задается с помощью атрибута ContainmentMode в элементе Contains , а режим сравнения — с помощью атрибута ContainmentComparison в элементе Contains . В следующем примере показано, как создать фильтр поиска для поиска в поле темы элементов подстроки "заметки о собрании". В этом примере игнорируется регистр, но не игнорируется пробел.

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

Фильтр битовой маски

Фильтр битовой маски позволяет выполнять поиск целочисленных свойств в виде битовых масок и возвращать результаты, если определенные биты не заданы в значении указанного свойства.

Фильтр битовой маски в управляемом API EWS

В следующем примере показано, как использовать Управляемый API EWS для создания фильтра поиска для возврата всех элементов, имеющих значение в настраиваемом свойстве ItemIndex (определенном в разделе Пример: поиск элементов с помощью фильтра поиска и управляемого API EWS этой статьи), для которых не задан второй бит (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 (определенном в разделе Пример. Поиск элементов с помощью фильтра поиска и управляемого API EWS этой статьи), для которых не задан второй бит (10 в двоичном формате).

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

Фильтр существует

Фильтр существует позволяет искать элементы, для которых задано определенное свойство, независимо от значения.

Существует фильтр в управляемом API EWS

В следующем примере показано, как создать фильтр поиска для возврата всех элементов, для которых задано настраиваемое свойство 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>

Фильтр равенства

Фильтры равенства позволяют выполнять поиск всех элементов, имеющих значение для указанного свойства, равное определенному значению или не равно определенному значению. Сравниваемое значение может быть либо константой, либо значением другого свойства для каждого элемента.

Фильтр равенства в управляемом API EWS

В следующем примере показано, как использовать управляемый API EWS для создания фильтра поиска для возврата всех элементов, которые не были прочитаны.

// 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>

Фильтр реляционного тестирования

Фильтры реляционного тестирования позволяют искать все элементы, имеющие значение в указанном свойстве, которое больше (>), больше или равно (>=), меньше (), меньше (<) или меньше или равно (<=) заданному значению. Сравниваемое значение может быть либо константой, либо значением другого свойства для каждого элемента.

Фильтр реляционного тестирования в управляемом API EWS

В следующем примере показано, как использовать управляемый API EWS для создания фильтров поиска для возврата всех элементов со значением в свойстве 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>

Отмена фильтра

Отменяющий фильтр позволяет отменить другой фильтр и получить противоположные результаты поиска. В то время как другие фильтры возвращают результаты, соответствующие определенным условиям, отрицающий фильтр возвращает результаты, которые не соответствуют критериям, заданным фильтром, к которому он применяется.

Отмена фильтра в управляемом API EWS

В следующем примере показано, как использовать управляемый API EWS для создания фильтра поиска для возврата всех элементов, у которых нет подстроки "заметки о собрании" в теме.

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. Таким образом, вы можете выполнять поиск, например "все сообщения от Сэди Дэниэлс, которые содержат "заметки о собрании" в теме".

Составной фильтр в управляемом API EWS

В следующем примере показано, как использовать управляемый API EWS для создания фильтра поиска, который возвращает все элементы, отправляемые от Сэди Дэниэлса и содержащие "заметки о собрании" в теме.

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 для создания фильтра поиска, который возвращает все элементы, отправленные из Сэди Дэниэлса и содержащие "заметки о собрании" в теме.

<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>

Пример. Поиск элементов с помощью фильтра поиска и управляемого API EWS

Следующие методы управляемого API EWS используют фильтры поиска:

В следующем примере используется метод ExchangeService.FindItems . однако одни и те же правила и понятия применяются ко всем методам. В этом примере определяется метод SearchWithFilter . Он принимает объект ExchangeService , объект WellKnownFolderName и объект SearchFilter в качестве параметров. В этом примере предполагается, что для объекта ExchangeService выполнена инициализация с допустимыми значениями в свойствах Credentials и 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);
    }
}

Эту функцию можно использовать с любым из фильтров поиска, показанных в примерах в этой статье. В этом примере используется составной фильтр для возврата всех элементов в папке "Входящие" от Сэди Дэниелс с "заметками о собрании" в теме.

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 . однако одни и те же правила и понятия применяются к обеим операциям. Фильтры поиска содержатся в элементе Restriction в запросах SOAP. В этом примере отправляется запрос SOAP, эквивалентный поиску, который показан в предыдущем примере управляемого API EWS.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" 
    xmlns:t="http://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="http://schemas.microsoft.com/exchange/services/2006/types" 
        xmlns="http://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="http://schemas.microsoft.com/exchange/services/2006/messages" 
        xmlns:t="http://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>

Дальнейшие действия

Теперь, когда вы знакомы с использованием фильтров поиска в простом поиске, вы можете перейти к более сложным методам поиска.

См. также