Выполнение сгруппированного поиска с помощью EWS в Exchange
Узнайте, как выполнять сгруппированные поиски в управляемом API EWS или приложении EWS, предназначенном для Exchange.
Сгруппированные поисковые запросы полезны тем, что они позволяют управлять организацией результатов поиска. Организованные результаты поиска упрощают обработку результатов в приложении или их отображение для конечного пользователя управляемым способом.
Группирование выполняется путем помещения в группу всех элементов в результирующем наборе, имеющих одинаковое значение определенного поля. Например, можно сгруппировать результаты по отправителю, и все элементы одного и того же человека будут находиться в отдельной группе, а элементы в каждой группе будут отсортированы в соответствии с порядком, указанным в представлении. Сами группы сортируются по статистическому значению на основе выбранного поля.
Таблица 1. Методы управляемого API EWS и операции EWS для упорядочения результатов поиска
Задача | В управляемом API EWS, используйте... | В EWS используйте... |
---|---|---|
Упорядочивание элементов с одинаковым значением в определенном свойстве в результатах по группам |
Grouping.GroupOn |
Элемент FieldURI в качестве дочернего элемента элемента GroupBy |
Сортировка элементов в каждой группе по значению в определенном свойстве |
ItemView.OrderBy |
Элемент SortOrder |
Сортировка групп |
Grouping.AggregateOn Grouping.AggregateType Grouping.SortDirection |
Элемент FieldURI как дочерний элемент элемента AggregateOn Атрибут Aggregate в элементе AggregateOn Атрибут Order в элементе GroupBy |
Давайте сделаем это шаг за шагом.
Группирование результатов по определенному свойству
Первым шагом к использованию группирования является выбор свойства или атрибута элементов в хранилище Exchange для группировки. Управляемый API EWS предоставляет их как свойства класса для соответствующих классов, а EWS предоставляет их в виде XML-элементов. Вы можете выбрать любое свойство, включая пользовательские или расширенные свойства, но полезно понять, как элементы группируются на основе значения выбранного свойства.
Все элементы с одинаковым значением в свойстве, по которому вы выбираете группирование, будут сгруппированы. Это может показаться очевидным, но это важная деталь. Рассмотрим, что происходит при группировке по свойству даты и времени, например Item.DateTimeReceived в управляемом API EWS или элементу DateTimeReceived в EWS. Целью может быть организация результатов по группам, каждая из которых содержит элементы за один день. Однако при группировке выполняется просмотр всего значения, включая время.
Конечный результат заключается в том, что элементы будут сгруппированы таким образом, что элементы, полученные одновременно, вплоть до второго, находятся в своих собственных группах. Результаты, скорее всего, будут отсортированы по большому количеству групп с небольшим количеством элементов в каждой группе.
Чтобы получить набор результатов с меньшим количеством групп и большим количеством элементов в каждой группе, выберите свойство, которое, скорее всего, будет иметь меньшее количество значений, например EmailMessage.From или Item.Categories в управляемом API EWS или From или Categories в EWS. На следующем рисунке показан список сообщений электронной почты, которые отображаются в папке "Входящие".
Рис. 1. Сообщения в папке "Входящие"
Если сгруппировать элементы на рисунке 1 по свойству EmailMessage.From , результатом будет две группы: одна для сообщений, отправленных Надеждой Гросс, а другая — для сообщений, отправленных Сэди Дэниелс.
Рис. 2. Сообщения, разделенные на группы на основе свойства From
Сортировка элементов в группах
Вы можете управлять сортировкой элементов в каждой группе с помощью свойства ItemView.OrderBy в управляемом API EWS или элемента SortOrder в EWS. Один и тот же порядок применяется к каждой группе. Например, если отсортировать элементы с рисунка 1 по свойству Item.DateTimeReceived в порядке убывания, элемент, недавно полученный от Hope Gross, будет первым в группе Надежда Гросс, а элемент, недавно полученный от Сэди Дэниэлс, будет первым в группе Сэди Дэниелс. Удобно, что группы на рис. 2 уже отсортированы таким образом.
Сортировка групп
Теперь, когда группы упорядочены, последним шагом является сортировка самих групп. Поскольку сами группы не имеют конкретных значений, процесс группирования должен присваивать каждой группе значение сортировки. Это делается путем агрегирования значений определенного свойства в каждой группе, заданного свойством Grouping.AggregateOn в управляемом API EWS или элементом FieldURI в качестве дочернего элемента AggregateOn в EWS. Свойство Grouping.AggregateType в управляемом API EWS (или атрибут Aggregate в элементе AggregateOn в EWS) указывает, какое значение из элементов в каждой группе присваивается значению сортировки для группы — наибольшему или наименьшему значению. Наконец, порядок сортировки (по убыванию или возрастанию) задается свойством Grouping.SortDirection в управляемом API EWS или атрибутом Order элемента GroupBy в EWS.
Например, если группы на рисунке 2 сортируются путем агрегирования в свойстве Item.DateTimeReceived , использования наименьшего значения и сортировки в порядке убывания, элементы возвращаются в порядке, указанном на рисунке 3.
Рис. 3. Сгруппированные результаты поиска с группами, отсортированные по свойству DateTimeReceived
В следующих разделах показано, как можно выполнить группирование и сортировку в коде.
Пример. Выполнение сгруппированного поиска с помощью управляемого API EWS
Следующие методы управляемого API EWS могут использовать группирование:
В следующем примере используется метод ExchangeService.FindItems . однако те же правила и понятия применяются к методу Folder.FindItems . В этом примере определен метод с именем GroupItemsByFrom . Он принимает объект ExchangeService и объект WellKnownFolderName в качестве параметров. Он запрашивает первые 50 элементов в папке, сгруппированных по свойству EmailMessage.From , отсортированному по свойству Item.DateTimeReceived в порядке убывания. Сами группы сортируются по наименьшему значению свойства Item.DateTimeReceived в их элементах в порядке убывания.
В этом примере предполагается, что для объекта ExchangeService выполнена инициализация с допустимыми значениями в свойствах Credentials и Url.
static void GroupItemsByFrom(ExchangeService service, WellKnownFolderName folder)
{
// Limit the result set to 50 items.
ItemView view = new ItemView(50);
view.PropertySet = new PropertySet(ItemSchema.Subject,
ItemSchema.DateTimeReceived,
EmailMessageSchema.From,
ItemSchema.Categories);
// Item searches do not support Deep traversal.
view.Traversal = ItemTraversal.Shallow;
// Specify the sorting done within the groups.
view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Descending);
// Configure grouping.
Grouping groupByFrom = new Grouping();
groupByFrom.GroupOn = EmailMessageSchema.From;
groupByFrom.AggregateOn = ItemSchema.DateTimeReceived;
groupByFrom.AggregateType = AggregateType.Minimum;
groupByFrom.SortDirection = SortDirection.Descending;
try
{
GroupedFindItemsResults<Item> results = service.FindItems(folder,
view, groupByFrom);
foreach (ItemGroup<Item> group in results.ItemGroups)
{
Console.WriteLine("Group: {0}", group.GroupIndex);
foreach (Item item in group.Items)
{
if (item is EmailMessage)
{
EmailMessage message = item as EmailMessage;
Console.WriteLine("From: {0}", message.From);
Console.WriteLine("Subject: {0}", message.Subject);
Console.WriteLine("Id: {0}\n", message.Id.ToString());
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Exception while enumerating results: {0}", ex.Message);
}
}
Пример. Выполнение сгруппированного поиска с помощью EWS
В следующем примере запроса показан запрос операции FindItem для первых 50 элементов в папке, сгруппированных по элементу From и отсортированных по элементу DateTimeReceived в порядке убывания. Сами группы сортируются по наименьшему значению элемента DateTimeReceived в их элементах в порядке убывания.
<?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="Exchange2007_SP1" />
<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Eastern Standard Time" />
</t:TimeZoneContext>
</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:From" />
<t:FieldURI FieldURI="item:Categories" />
</t:AdditionalProperties>
</m:ItemShape>
<m:IndexedPageItemView MaxEntriesReturned="50" Offset="0" BasePoint="Beginning" />
<m:GroupBy Order="Descending">
<t:FieldURI FieldURI="message:From" />
<t:AggregateOn Aggregate="Minimum">
<t:FieldURI FieldURI="item:DateTimeReceived" />
</t:AggregateOn>
</m:GroupBy>
<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>
Сервер возвращает следующий ответ.
<?xml version="1.0" encoding="utf-8"?>
<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="10" TotalItemsInView="8" IncludesLastItemInRange="true">
<t:Groups>
<t:GroupedItems>
<t:GroupIndex>0</t:GroupIndex>
<t:Items>
<t:Message>
<t:ItemId Id="AAMkAGM2..." ChangeKey="CQAAABYA..." />
<t:Subject>Planning resources</t:Subject>
<t:DateTimeReceived>2013-12-10T17:41:05Z</t:DateTimeReceived>
<t:From>
<t:Mailbox>
<t:Name>Sadie Daniels</t:Name>
<t:EmailAddress>/O=FIRST ORGANIZATION/OU=EXCHANGE ADMINISTRATIVE GROUP (FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN=8D84A3F4CBB34D48838A3AECF99795C0-SADIE</t:EmailAddress>
<t:RoutingType>EX</t:RoutingType>
</t:Mailbox>
</t:From>
</t:Message>
<t:Message>
<t:ItemId Id="AAMkAGM2..." ChangeKey="CQAAABYA..." />
<t:Subject>Timeline</t:Subject>
<t:DateTimeReceived>2013-12-10T17:40:37Z</t:DateTimeReceived>
<t:Categories>
<t:String>Project</t:String>
</t:Categories>
<t:From>
<t:Mailbox>
<t:Name>Sadie Daniels</t:Name>
<t:EmailAddress>/O=FIRST ORGANIZATION/OU=EXCHANGE ADMINISTRATIVE GROUP (FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN=8D84A3F4CBB34D48838A3AECF99795C0-SADIE</t:EmailAddress>
<t:RoutingType>EX</t:RoutingType>
</t:Mailbox>
</t:From>
</t:Message>
<t:Message>
<t:ItemId Id="AAMkAGM2..." ChangeKey="CQAAABYA..." />
<t:Subject>For your perusal</t:Subject>
<t:DateTimeReceived>2013-11-20T21:51:16Z</t:DateTimeReceived>
<t:From>
<t:Mailbox>
<t:Name>Sadie Daniels</t:Name>
<t:EmailAddress>/O=FIRST ORGANIZATION/OU=EXCHANGE ADMINISTRATIVE GROUP (FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN=8D84A3F4CBB34D48838A3AECF99795C0-SADIE</t:EmailAddress>
<t:RoutingType>EX</t:RoutingType>
</t:Mailbox>
</t:From>
</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:Categories>
<t:String>Blue category</t:String>
</t:Categories>
<t:From>
<t:Mailbox>
<t:Name>Sadie Daniels</t:Name>
<t:EmailAddress>/O=FIRST ORGANIZATION/OU=EXCHANGE ADMINISTRATIVE GROUP (FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN=8D84A3F4CBB34D48838A3AECF99795C0-SADIE</t:EmailAddress>
<t:RoutingType>EX</t:RoutingType>
</t:Mailbox>
</t:From>
</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:From>
<t:Mailbox>
<t:Name>Sadie Daniels</t:Name>
<t:EmailAddress>/O=FIRST ORGANIZATION/OU=EXCHANGE ADMINISTRATIVE GROUP (FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN=8D84A3F4CBB34D48838A3AECF99795C0-SADIE</t:EmailAddress>
<t:RoutingType>EX</t:RoutingType>
</t:Mailbox>
</t:From>
</t:Message>
</t:Items>
</t:GroupedItems>
<t:GroupedItems>
<t:GroupIndex>1</t:GroupIndex>
<t:Items>
<t:Message>
<t:ItemId Id="AAMkAGM2..." ChangeKey="CQAAABYA..." />
<t:Subject>Query</t:Subject>
<t:DateTimeReceived>2013-12-10T17:43:15Z</t:DateTimeReceived>
<t:From>
<t:Mailbox>
<t:Name>Hope Gross</t:Name>
<t:EmailAddress>/O=FIRST ORGANIZATION/OU=EXCHANGE ADMINISTRATIVE GROUP (FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN=9B55E4100C064D9D8C5F72FF36802ED3-HOPE</t:EmailAddress>
<t:RoutingType>EX</t:RoutingType>
</t:Mailbox>
</t:From>
</t:Message>
<t:Message>
<t:ItemId Id="AAMkAGM2..." ChangeKey="CQAAABYA..." />
<t:Subject>Update</t:Subject>
<t:DateTimeReceived>2013-12-10T17:42:33Z</t:DateTimeReceived>
<t:Categories>
<t:String>Project</t:String>
<t:String>Blue category</t:String>
</t:Categories>
<t:From>
<t:Mailbox>
<t:Name>Hope Gross</t:Name>
<t:EmailAddress>/O=FIRST ORGANIZATION/OU=EXCHANGE ADMINISTRATIVE GROUP (FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN=9B55E4100C064D9D8C5F72FF36802ED3-HOPE</t:EmailAddress>
<t:RoutingType>EX</t:RoutingType>
</t:Mailbox>
</t:From>
</t:Message>
<t:Message>
<t:ItemId Id="AAMkAGM2..." ChangeKey="CQAAABYA..." />
<t:Subject>This cat is hilarious!</t:Subject>
<t:DateTimeReceived>2013-10-15T20:22:12Z</t:DateTimeReceived>
<t:From>
<t:Mailbox>
<t:Name>Hope Gross</t:Name>
<t:EmailAddress>/O=FIRST ORGANIZATION/OU=EXCHANGE ADMINISTRATIVE GROUP (FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN=9B55E4100C064D9D8C5F72FF36802ED3-HOPE</t:EmailAddress>
<t:RoutingType>EX</t:RoutingType>
</t:Mailbox>
</t:From>
</t:Message>
</t:Items>
</t:GroupedItems>
</t:Groups>
</m:RootFolder>
</m:FindItemResponseMessage>
</m:ResponseMessages>
</m:FindItemResponse>
</s:Body>
</s:Envelope>
Различия версий
Версии Exchange, начиная с основной версии 15 и заканчивая сборкой 15.0.775.38, возвращают элементы Group (типа GroupedItemsType) вместо элементов GroupedItems в ответе SOAP. Если вы используете управляемый API EWS, это приведет к тому, что коллекция GroupedFindItemsResults.ItemGroups будет содержать 0 объектов. Если вы используете EWS, элементы Group должны обрабатываться как элементы GroupedItems .
Версии Exchange, начиная с основной версии 15, возвращают дополнительные элементы Group или GroupedItems с атрибутом xsi:nilв ответе SOAP. Если вы используете управляемый API EWS, эти дополнительные элементы вызовет исключение ServiceXmlDeserializationException . Если вы используете EWS, эти дополнительные элементы следует игнорировать.