Search for content

Portals can contain a huge amount of information. To help your users find the information they want to work with, you can add searching to your app. Searching can allow users to find information in different ways, for example, by searching for the groups that include a keyword, or finding all portal items that are web maps having specific tags.

Portal administrators can configure a number of settings to highlight specific content to users, such as the set of available basemaps,the content featured in the portal homepage and gallery, and the featured groups for the organization. Learn how to easily find featured basemaps, content, and groups.

Searching is done from the Portal class. Publicly accessible items and groups can be accessed without any authentication, but to find items that are secured, a user with access to the item must be authenticated with the portal. See Access the ArcGIS Platform for more information about authenticating with a portal.

Search by defining query parameters

The API provides a flexible, generic search, along with some convenience methods to help you perform common portal searches.

Find portal items by keyword

To search for portal items using a keyword, construct a query that includes the keyword you want to search for. By default, the query will return portal items that include the keyword in any of the common fields of a portal item, including the title, tags, description, and type. The results of the query can be iterated.

Create a PortalQueryParametersForItems object and pass the search term (QString) into the constructor. Then use the PortalQueryParametersForItems in a call to the findItems method. The resulting PortalQueryResultSetForItems contains portal items that use the search term in any of the searched fields.

Tip:

Use PortalQueryParametersForItems with an Envelope to find portal items that intersect a specified extent. You can optionally provide a query string to define search parameters that include both spatial and attribute criteria.

connect(portal, &Portal::findItemsCompleted, this, [](PortalQueryResultSetForItems* result)
{
  // process the result
  if (result)
    qDebug() << result->totalResults();
});


PortalQueryParametersForItems findItemsQueryParameters("san francisco");
portal->findItems(findItemsQueryParameters);

Note:

Remember, only the items that are accessible to the authenticated user of the portal will be included in the search results. When a user is not authenticated, only publicly shared items are found.

By default, the result set contains only the first 10 results but provides a convenient way to fetch subsequent sets of results if required. To learn more about working with large result sets, see Display many search results.

For a full list of the default fields used for searching, and complete information on constructing portal query strings, see the ArcGIS Online Search reference.

Order the search results

If there are more than a few results, you may want to help your user narrow down the results to find items of most interest. Your app can show the most recently updated results to the user first, sorting search results by the date they were last modified, in descending order.

findItemsQueryParameters.setSortField("modified");
findItemsQueryParameters.setSortOrder(PortalQuerySortOrder::Descending);

Results can be sorted in either ascending or descending order, by portal item fields such as the title, date of creation or date last modified, type, and owner. For a full list of sort fields, see ArcGIS Online Search.

Find items by type

You can restrict the results of a search to be a specific type or types of content; for example, you can search to find only web maps.

Create a PortalQueryParametersForItems object and pass the text you want to search for into the constructor. Then pass the PortalQueryParametersForItems to the Portal::findItems method. The resulting PortalQueryResultSetForItems should contain all of the portal items that contain the keyword in any of the searched fields.

connect(portal, &Portal::findItemsCompleted, this, [](PortalQueryResultSetForItems* result)
{
  // process the result
  if (result)
    qDebug() << result->totalResults();
});


PortalQueryParametersForItems findItemsQueryParameters =
    PortalQueryParametersForItems::forItemType(PortalItemType::WebMap, "san francisco");
portal->findItems(findItemsQueryParameters);

If you want to find results of more than one type of portal item, you can do this by defining your query string.

Find groups by keyword

You can find groups by using a keyword in a similar way as it is used when finding portal items. For groups, the default fields searched include title, description, and tags (as for portal items), but also include owner.

Create a PortalQueryParametersForGroups object using your desired search terms and pass it to the Portal::findGroups method. The resulting PortalQueryResultSetForGroups should contain all of the groups that match the criteria.

QString owner = "esri_atlas";
QString title = "Living Atlas";
PortalQueryParametersForGroups queryParams(owner, title);
portal->findGroups(queryParams);


QStringList titles;
connect(portal, &Portal::findGroupsCompleted, this, [&titles](PortalQueryResultSetForGroups* results)
{
  if (!results)
    return;


  QAbstractListModel* model = results->groupResults();
  if (!model)
    return;


  for (int i = 0; i < model->rowCount(); i++)
    titles.append(model->data(model->index(i,0), PortalGroupListModel::PortalGroupTitleRole).toString());
});

Find items in a known group

After a search for groups, you might want to list all of the items shared with those groups. Alternatively, you might want to list the items in a group returned from the authenticated users list of groups. If a search result set contains at least one group, to find all the items in that group, issue a second search using the group ID as part of the second query.

The code below continues from the previous example, by passing the group Id of the PortalGroup objects from the initial search to the static PortalQueryParametersForItems::inGroup factory method, and then calling the Portal::findItems method to perform the second search.

connect(portal, &Portal::findGroupsCompleted, this, [portal](PortalQueryResultSetForGroups* results)
{
  // handle the results of the group query
  if (!results)
    return;


  QAbstractItemModel* groups = results->groupResults();
  if (!groups)
    return;


  for (int i = 0; i < groups->rowCount(); ++i)
  {
    QString groupId = groups->data(groups->index(i,0), PortalGroupListModel::PortalGroupGroupIdRole).toString();
    if (groupId.isEmpty())
      continue;


    PortalQueryParametersForItems itemParams = PortalQueryParametersForItems::inGroup(groupId);
    itemParams.setGroupId(groupId);


    // start a new query to look for items shared with this group
    portal->findItems(itemParams);
    return;
  }
});


connect(portal, &Portal::findItemsCompleted, this, [portal](PortalQueryResultSetForItems* results)
{
  // handle the results of the items query
  if (!results)
    return;


  QAbstractItemModel* items = results->itemResults();
  if (!items)
    return;


  for (int i = 0; i < items->rowCount(); ++i)
    qDebug() << items->data(items->index(i, 0), PortalItemListModel::PortalItemTitleRole);
});


// start the initial query to find groups
portal->findGroups(groupParams);

Find items by ID

If you already know the ID of a portal item, you can search for it by using that ID. You might find this technique useful if your app is closed while displaying a specific item—you can save the ID and fetch the item again to ensure the item is still accessible and all the properties are up-to-date, and use this information to restore the state of the app. If the search returns no results, then the item may no longer be available; for example, the owner may have changed the access permissions, and your app can react accordingly.

connect(portal, &Portal::findItemsCompleted, this, [](PortalQueryResultSetForItems* result)
{
  if (!result)
    return;


  // process the result
});


PortalQueryParametersForItems queryParams = PortalQueryParametersForItems::withId(savedItemId);
portal->findItems(queryParams);

You can also directly retrieve a PortalItem by ID by passing a loaded Portal and the ID to the PortalItem constructor. Upon loading the PortalItem it's properties can be accessed.

PortalItem* item = new PortalItem(portal, savedItemId, parent);


connect(item, &PortalItem::loadStatusChanged, this, [item](LoadStatus status)
{
  if (status != LoadStatus::Loaded)
    return;


  qDebug() << item->title();
});


item->load();

Define a query

If you need to search for items using more complex criteria, you can build a query to satisfy that criteria making use of multiple predicates, Boolean operators, ranges, and wildcards. You could, for example, build a query that finds items that are web maps, owned by the user "esri", with either of the tags "atlantic" or "pacific".

PortalQueryParametersForItems queryParamsWithTags("type:\"web map\" AND owner:esri AND tags:(pacific OR atlantic)");

Adding specific criteria can be especially useful when you are localizing your app, as you can limit results to a specific culture.

PortalQueryParametersForItems queryParamsWithCulture("culture:fr-FR AND type:\"map service\"");

Tip:

You can also search using ranges of dates that items were created and last modified, using the created and modified fields of a portal item. However, be aware that portal searches use UNIX epoch dates (defined as the number of seconds that have elapsed since midnight January 1, 1970), as noted in the ArcGIS Online Search reference.

Search for featured basemaps, content, and groups

Portal administrators can configure a number of settings to highlight specific content to users. Configurable settings include the set of available basemaps, content featured in the portal homepage and gallery, and featured groups for the organization.

Get Home page and Gallery featured content

Administrators can configure two groups that contain featured content to show in different situations. The portal gallery can be populated either with the contents of a group, or with the top 100 most-viewed items. The homepage of the organization can also display featured content from a chosen group, and the maximum number of items displayed can be separately configured. Depending on the type of content that is featured, you may want your app to display the same featured items as shown in the website. For example, if the featured items are web maps, app users may want to browse a list of these maps, and then open them.

To search for the items displayed as homepage featured content, first create a query using the PortalInfo::homepageFeaturedContentGroupQuery method to set the query string. Use the query to find the group containing the featured content, and then perform a second search to find the items shared with that group.

PortalInfo* portalInfo = portal->portalInfo();
PortalQueryParametersForGroups groupParams(portalInfo->homePageFeaturedContentGroupQuery());


connect(portal, &Portal::findGroupsCompleted, this, [portal](PortalQueryResultSetForGroups* results)
{
  // handle the results of the group query
  if (!results)
    return;


  QAbstractItemModel* groups = results->groupResults();
  if (!groups)
    return;


  for (int i = 0; i < groups->rowCount(); ++i)
  {
    QString groupId = groups->data(groups->index(i,0), PortalGroupListModel::PortalGroupGroupIdRole).toString();
    if (groupId.isEmpty())
      continue;


    PortalQueryParametersForItems itemParams = PortalQueryParametersForItems::inGroup(groupId);
    itemParams.setGroupId(groupId);


    // start a new query to look for items shared with this group
    portal->findItems(itemParams);
    return;
  }
});


connect(portal, &Portal::findItemsCompleted, this, [](PortalQueryResultSetForItems* results)
{
  // handle the results of the items query
  if (!results)
    return;


  QAbstractItemModel* items = results->itemResults();
  if (!items)
    return;


  for (int i = 0; i < items->rowCount(); ++i)
    qDebug() << items->data(items->index(i, 0), PortalItemListModel::PortalItemTitleRole);
});


// start the initial query to find homepage featured group
portal->findGroups(groupParams);

Get a list of configured basemaps

Many apps allow a user to change the basemap used to provide context for other data shown in a map. Portal administrators can configure the list of basemaps they want to be available to a user of a portal by sharing web maps into a specific group.

PortalInfo* portalInfo = portal->portalInfo();
PortalQueryParametersGroups queryParams(portalInfo->basemapGalleryGroupQuery());
portal->findGroups(queryParams);

For each web map in the result set, you can show the thumbnail and title of the item in a gallery or list. You can easily display a web map from the selected item by using its ID.

Additionally, you can use another predefined query (PortalInfo.basemapGalleryGroupQuery) to find out the basemaps group for a portal if required, and from there you can list the items in that group.

Get featured groups

A list of featured groups can be configured to appear on the Groups and My Organization pages of the website. You can find out these groups, and in turn can get the contents as you would for any other group.

PortalInfo* portalInfo = portal->portalInfo();
QStringList groupQueries = portalInfo->featuredGroupsQueries();
for (const QString& query : groupQueries)
{
  PortalQueryParametersForGroups groupParams(query);
  // perform a query to retrieve the featured group
}

Again, predefined query strings are available for the set of groups. Unlike the other predefined queries mentioned above, there are multiple queries used to find all of the groups. You can get a list of queries from the portal, each of which should return a single featured group.

Display many search results

Searches may return just a few results, or many thousands of results. To reduce network traffic and memory , search results are returned in batches (by default, only the first 10 are returned), along with a count of the total results found on the portal.

Often, the required item is in the first set of results, but your app can let the user decide if they need to see more items, for example, by scrolling past the end of a list, switching to the next page of results, or by tapping a button. You can easily issue another query to find the next set of results, as the result set from your first query constructs the correct subsequent query for you.

The following code creates a PortalQueryParametersForItems, sets the initial query, and calls the Portal::findItems method. After iterating through the initial results, the PortalQueryResultSetForItems::nextQueryParameters method is used to get the correct query to find the next set of results. If there are more results to retrieve, then a second call to findItems is made. This pattern can be repeated until PortalQueryResultSetForItems::nextQueryParameters method returns a PortalQueryParametersForItems with a startIndex of -1, indicating there are no more results to get.

bool complete = false;
QStringList allTitles;
int count = 0;
connect(portal, &Portal::findItemsCompleted, this, [portal, &allTitles, &complete, &count](PortalQueryResultSetForItems* result)
{
  ++count;


  if (!result)
    return;


  PortalItemListModel* model = result->itemResults();
  if (!model)
    return;


  for (int i = 0; i < model->rowCount(); ++i)
  {
    allTitles.append(model->data(model->index(i,0), PortalItemListModel::PortalItemTitleRole).toString());
  }


  // a startIndex of -1 indicates there are no more results
  PortalQueryParametersForItems nextParams = result->nextQueryParameters();
  if (nextParams.startIndex() > 0)
    portal->findItems(nextParams); // start a query to retrieve the next batch of results
  else
    complete = true;
});


// perform the initial query
PortalQueryParametersForItems queryParams("global rainfall");
portal->findItems(queryParams);

If you want to retrieve results in larger batches, use PortalSearchParameters.setLimit to change the batch size.