MS Search – Get Query Result

Estimated reading: 9 minutes

MS Search – Get Query Result

Executes one Microsoft Graph search request and returns a structured search response. Choose the entity types and search text, then inspect response containers and hits. The action uses POST /v1.0/search/query; it retrieves discovery metadata rather than full resource content.

Action details

PropertyValue
Action labelMS Search – Get Query Result
CategoryCloudTools
Apex class and methodGetMSSearchQueryResult.getSearchQueryResult
Input typeGetMSSearchQueryResult.GetMSSearchQueryResultInput
Output typeList<MSSearchResult>
Microsoft Graph requestPOST /v1.0/search/query
AuthorizationAuthorization depends on the searched workload. The examples use OAuth Delegated (Authorization Code).

Prerequisites and permissions

Configure a CloudTools Connector with Connector Type set to Microsoft 365. Use OAuth Delegated (Authorization Code) and complete the current user’s Microsoft sign-in for the examples below. The account must be a supported work or school account and have access to the searched content.

The permission provider declares delegated scopes Sites.Read.All, Mail.Read, Chat.Read, Calendars.Read, Files.Read.All, Acronym.Read.All, Bookmark.Read.All, QnA.Read.All, and ExternalItem.Read.All, and application scopes Sites.Read.All and Files.Read.All. These declarations do not mean every scope is required, or that one scope authorizes every entity type. Choose permissions for the workload; do not use Mail.Read to authorize file search. See the Microsoft query and permissions reference.

Inputs

InputApex fieldTypeRequiredDescription
Entity TypesentityTypesList<String>YesOne or more resource type names, for example message, event, driveItem, listItem, list, site, drive, or chatMessage. Blank entries are removed, remaining entries are trimmed, and duplicates are removed case-insensitively. The first spelling is retained; use Microsoft’s canonical casing. Microsoft validates supported types and combinations.
Query StringqueryStringStringYesNonblank search text. The implementation trims leading and trailing whitespace. Supply the query text rather than a JSON request, URL, or OData filter parameter.
SizesizeIntegerNoRequested page size. Positive values are sent to Microsoft; null, zero, and negative values omit size. There is no local maximum check. Microsoft documents a general maximum of 500 and resource-specific constraints can also apply.

Supply a nonempty request list with a non-null first entry. Only the first request is processed. The action creates one requests entry containing entityTypes, query.queryString, and size when positive. It exposes no from, fields, contentSources, sortProperties, aggregations, or custom headers. Entity types that need extra request properties cannot necessarily be used just by adding their name. See the Microsoft request schema.

The global invocable input has no connectorId field; subscriber Apex and Flow use default Microsoft 365 connector selection. The internal public overload accepts a connector ID for the controller but is not the global subscriber API. Resolve dynamic values first; replacement tokens are not resolved by this action.

Outputs

Returns one MSSearchResult inside a list when Microsoft returns an object, or an empty list if the response cannot be mapped as an object. A valid response with no hits is different from an empty outer list. Traverse results[0].value, each entry’s hitsContainers, and then each container’s hits.

Search response — MSSearchResult

OutputApex fieldTypeDescription
OData ContextodataContextStringOData context metadata URL.
ValuevalueList<MSSearchResponseValue>Search response value entries.
Additional PropertiesadditionalPropertiesList<DynamicObject>Additional properties from user-defined query.

Response entries — MSSearchResponseValue

OutputApex fieldTypeDescription
Search TermssearchTermsList<String>Search terms used for this response entry.
Hits ContainershitsContainersList<MSSearchHitsContainer>Containers for search hits.
Additional PropertiesadditionalPropertiesList<DynamicObject>Additional response entry properties.

Hit containers — MSSearchHitsContainer

OutputApex fieldTypeDescription
TotaltotalIntegerTotal hits in the container.
More Results AvailablemoreResultsAvailableBooleanWhether more hits are available.
HitshitsList<MSSearchHit>Search hits in this container.
Additional PropertiesadditionalPropertiesList<DynamicObject>Additional hits container properties.

Individual hits — MSSearchHit

OutputApex fieldTypeDescription
OData TypeodataTypeStringOData type for the hit object.
Hit IdhitIdStringIdentifier for the hit.
RankrankDecimalRanking score/order for the hit.
SummarysummaryStringSummary snippet for the hit.
Resource OData TyperesourceOdataTypeStringResource OData type.
Drive ResourcedriveMSGraphDriveTyped drive resource when present.
Drive Item ResourcedriveItemMSGraphDriveItemTyped drive item resource when present.
List Item ResourcelistItemSharePointListItemTyped list item resource when present.
List ResourcelistResourceSharePointListTyped list resource when present.
Site ResourcesiteSharePointSiteTyped site resource when present.
Message ResourcemessageMSOutlookMessageTyped mail message resource when present.
Event ResourceeventMSGraphEventTyped event resource when present.
Teams Message ResourceteamsMessageMSTeamsChatMessageTyped Teams message resource when present.
Resource Raw JSONresourceRawJsonStringRaw resource JSON payload.
Additional PropertiesadditionalPropertiesList<DynamicObject>Additional hit properties.

Typed resource properties are populated according to the resource’s @odata.type: drive, driveItem, listItem, list, site, message, event, and chatMessage map to their corresponding property, with list mapped to listResource and chatMessage to teamsMessage. Other types retain resourceRawJson without a typed property. Treat all resource properties as optional. Resource models expose metadata returned by Search, not a guaranteed full resource.

The parser serializes the resource map into resourceRawJson, preserving its returned properties even when a typed model omits them. It does not preserve the original response bytes. Typed resources are deserialized directly rather than through every connector’s custom property mapper; Graph names that differ from Apex names and dynamic list fields may require reading resourceRawJson. Unknown properties on the response, response entry, container, and hit are retained as DynamicObject name/value entries in additionalProperties.

The action returns only the requested page and does not automatically retrieve additional results. total and moreResultsAvailable describe the containers; the action has no offset input for continuing. A hitId identifies a search hit; use the typed resource id or resourceRawJson and parent identifiers for subsequent connector calls.

Use in Flow

The action appears as MS Search – Get Query Result in Flow Builder. CloudTools Flow automation requires an application connector configured as Set as default for Flow automations. Verify that the selected workload supports application access and that the connector has the required permissions. The action processes only the first request and returns a nested response hierarchy, not a flat collection of records.

Use in custom Apex

This subscriber-org example uses the Apptigent namespace and searches files with an already-authorized delegated connector selected by CloudTools defaults. Replace the query as needed, grant the appropriate delegated file-search permissions, and call in a context that permits callouts. Handle exceptions in the calling application.

Apptigent.GetMSSearchQueryResult.GetMSSearchQueryResultInput request =
    new Apptigent.GetMSSearchQueryResult.GetMSSearchQueryResultInput();
request.entityTypes = new List<String>{ 'driveItem' };
request.queryString = 'project';
request.size = 25;

List<Apptigent.MSSearchResult> results =
    Apptigent.GetMSSearchQueryResult.getSearchQueryResult(
        new List<Apptigent.GetMSSearchQueryResult.GetMSSearchQueryResultInput>{ request }
    );

if (!results.isEmpty() && results[0] != null) {
    for (Apptigent.MSSearchResponseValue entry : results[0].value) {
        for (Apptigent.MSSearchHitsContainer container : entry.hitsContainers) {
            System.debug(container.moreResultsAvailable);
            for (Apptigent.MSSearchHit hit : container.hits) {
                if (hit.driveItem != null) {
                    System.debug(hit.driveItem.id);
                    System.debug(hit.driveItem.name);
                }
            }
        }
    }
}

Use in a Lightning Web Component

Use msSearchConnectorLib, through MSSearchConnectorController. The c/ imports below apply to a component in the same namespace. Supply the selected Connector record ID as the second function argument; the controller forwards it into the action. Although the input factory includes connectorId, the controller uses the separate argument for connector selection.

The example uses getMSSearchQueryResultFromResult, which unwraps the structured Result response and throws a ConnectorOperationError on failure. This preserves requiresInteractiveAuthorization and other error metadata. The plain getMSSearchQueryResult function returns the same mapped payload on success but converts failed operation results to an Aura-handled message through the controller.

searchActionExample.js

import { LightningElement } from 'lwc';
import { getMSSearchQueryResultFromResult, MSSearchObjects } from 'c/msSearchConnectorLib';

export default class SearchActionExample extends LightningElement {
    connectorId = 'REPLACE_WITH_CONNECTOR_RECORD_ID';
    hits = [];
    total = 0;
    moreResultsAvailable = false;
    errorMessage = '';
    isRunning = false;

    async handleSearch() {
        if (this.isRunning) {
            return;
        }
        this.isRunning = true;
        this.errorMessage = '';
        this.hits = [];
        this.total = 0;
        this.moreResultsAvailable = false;
        try {
            const request = MSSearchObjects.inputs.searchQuery();
            request.entityTypes = ['driveItem'];
            request.queryString = 'project';
            request.size = 25;
            const result = await getMSSearchQueryResultFromResult(request, this.connectorId);
            if (!result || !Array.isArray(result.hits)) {
                throw new Error('The search did not return a usable response.');
            }
            this.hits = result.hits.map((hit, index) => ({
                ...hit,
                rowKey: String(index),
                displayName: hit.resourceDisplayName || hit.resourceId || 'Search result'
            }));
            this.total = result.total;
            this.moreResultsAvailable = result.moreResultsAvailable === true;
        } catch (error) {
            this.errorMessage = error.requiresInteractiveAuthorization
                ? 'Sign in to Microsoft for this connector, then search again.'
                : error.message || 'The Microsoft search failed.';
        } finally {
            this.isRunning = false;
        }
    }
}

searchActionExample.html

<template>
    <lightning-button label="Search Microsoft 365" onclick={handleSearch}
        disabled={isRunning}></lightning-button>
    <p role="alert">{errorMessage}</p>
    <p>Total reported hits: {total}</p>
    <template for:each={hits} for:item="hit">
        <div key={hit.rowKey}>
            <p>{hit.displayName}</p>
            <p>{hit.summary}</p>
        </div>
    </template>
    <template lwc:if={moreResultsAvailable}>
        <p>More results are available. Refine the query to narrow the results.</p>
    </template>
</template>

The LWC response is one object with odataContext, total, moreResultsAvailable, hits, and rawJson. The controller concatenates container hits, sums container totals, and sets moreResultsAvailable when any container reports it. These totals are not a deduplicated count across resource types. Each hit includes hitId, integer rank, summary, resourceOdataType, resourceId, resourceDisplayName, resourceWebUrl, resourceJson, and optional typed resource properties.

LWC resourceJson comes from the hit’s resourceRawJson; response rawJson serializes the mapped Apex search result. The controller also hydrates event and Teams message properties from raw resource metadata when available. The example renders summaries as text because Microsoft snippets can contain highlight markers such as <c0> and <ddd/>; it does not inject them as HTML.

For explicit operation status, getMSSearchQueryResultResult returns success, code, message, requiresInteractiveAuthorization, connector and authorization metadata, resultJson, and a parsed payload. Success can contain a null payload if the action mapped no response. Use getMSSearchAuthorizationState, beginMSSearchAuthorization, and createMSSearchOAuthMessageHandler to arrange delegated sign-in. getMSSearchConnectorOptions supplies connector choices. These helpers do not automatically authorize or retry a failed search.

Error handling and troubleshooting

SymptomWhat to check
Request validation failureProvide a non-null first request, at least one nonblank entity type, and nonblank query text.
Authorization requiredComplete delegated sign-in for the selected connector. Use the structured Result wrapper when the UI needs authorization metadata.
Forbidden or unsupported resource typeCheck workload permissions, user access, canonical type names, and supported entity-type combinations.
Invalid page sizeSupply a positive size within Microsoft’s limits for the selected resource type. The action does not clamp it.
Empty or incomplete resultsCheck indexed content, query text, identity access, and page-size limits. Search is not exhaustive resource enumeration.
More results availableNarrow the query. The action cannot advance to another page because it has no from input.
Missing typed propertiesInspect resourceOdataType and resourceRawJson or LWC resourceJson. Search may omit metadata and direct typed deserialization may not apply custom property mappings.
Wrong connectorPass the selected ID as the second LWC argument. Global Apex and Flow inputs use default connector selection.
Share this Doc

MS Search – Get Query Result

Or copy link

CONTENTS

Free eBook: The Ultimate Guide to Power Platform Custom Connectors

Antimanual

Ask our AI support assistant your questions about our platform, features, and services.

You are offline
Chatbot avatar
What can I help you with?

Subscribe

×
Cancel