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 PortalQueryParameters object and pass the keyword you want to search for into the constructor as the query parameter. Then pass the PortalQueryParameters to the Portal.findItemsAsync method. The resulting PortalQueryResultSet from the future should contain all of the portal items that contain the keyword in any of the searched fields.

final PortalQueryParameters queryParams = new PortalQueryParameters("san francisco");
final ListenableFuture<PortalQueryResultSet<PortalItem>> findItemsFuture = portal.findItemsAsync(queryParams);
findItemsFuture.addDoneListener(new Runnable() {
  @Override
  public void run() {
    try {
      PortalQueryResultSet<PortalItem> queryResultSet = findItemsFuture.get();

      // Process the query results...
      showMessage(String.format("Total results found=%d", queryResultSet.getTotalResults()));

      List<PortalItem> results = queryResultSet.getResults();
      for (PortalItem item : results) {
        // Process the results as required...
        String resultInfo = String.format("Item Name:%s (ID:%s)", item.getTitle(), item.getItemId());
      }

    } catch (InterruptedException | ExecutionException e) {
      dealWithException(e);
    }
  }
});

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.

queryParams.setSortField("modified");
queryParams.setSortOrder(PortalQueryParameters.SortOrder.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.

The setQuery method has a number of overloads—the code below uses the overload allowing you to specify the PortalItem.Type that results must match, along with a group ID (in this case, null indicates you want to search regardless of any groups) and the search query. The PortalItem.Type enum provides a full list of content types that may be stored as items in a portal. Retrieve the results of the query as shown previously for searching by keyword

final PortalQueryParameters queryParams = new PortalQueryParameters();
queryParams.setQuery(PortalItem.Type.WEBMAP, null, "san francisco");
final ListenableFuture<PortalQueryResultSet<PortalItem>> findItemsFuture = portal.findItemsAsync(queryParams);

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

Find items in your organization

By default, a search returns results from within an organization, and also public results from outside the organization. It may be useful to restrict results to only those within the organization of the authenticated user, as shown below.

queryParams.setCanSearchPublic(true);

Portal administrators can turn off the ability for their users to search for items outside the organization when using the website. This setting is independent of the query API, but you can get and use the portal-level setting as shown below to allow the portal administrators setting to determine the search behavior in your app as well as in the website.

PortalInfo info = portal.getPortalInfo();
PortalQueryParameters queryParams = new PortalQueryParameters("san francisco");
queryParams.setCanSearchPublic(info.isCanSearchPublic());
final ListenableFuture<PortalQueryResultSet<PortalItem>> findItemsFuture = portal.findItemsAsync(queryParams);

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 PortalQueryParameters object and pass the keyword you want to search for into the constructor as the query parameter. Then pass the PortalQueryParameters to the Portal.findGroupsAsync method. The resulting PortalQueryResultSet should contain all of the groups that contain the keyword in any of the searched fields. In this case, the query should find all of the groups containing "esri_demographics", including those owned by the user named "esri_demographics".

PortalQueryParameters groupQuery = new PortalQueryParameters("esri_demographics");
final ListenableFuture<PortalQueryResultSet<PortalGroup>> findGroupsFuture = portal.findGroupsAsync(groupQuery);
findGroupsFuture.addDoneListener(new Runnable() {
  @Override
  public void run() {
    try {
      PortalQueryResultSet<PortalGroup> groupResults = findGroupsFuture.get();

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 example shown in find groups by keyword by creating a PortalQueryParameters using the group ID from the PortalGroup from the initial search to set the group ID in the setQueryForItemsInGroup method. The Portal.findItemsAsync method is called to search for the items within that group.

if (groupResults.getResults().size() > 0) {
  for (PortalGroup group : groupResults.getResults()) {
    // Create a PortalQueryParams for each found PortalGroup and search for contents of that group
    PortalQueryParameters groupContentQuery = new PortalQueryParameters();
    groupContentQuery.setQueryForItemsInGroup(group.getGroupId());
    final ListenableFuture<PortalQueryResultSet<PortalItem>> findItemsFuture = portal.findItemsAsync(groupContentQuery);
    findItemsFuture.addDoneListener(new Runnable() {
      @Override
      public void run() {
        try {
          PortalQueryResultSet<PortalItem> groupContentResults = findItemsFuture.get();
          // Display the featured content results...
          processResults(groupContentResults);
        } catch (InterruptedException | ExecutionException e) {
          dealWithException(e);
        }
      }
    });
  }
}

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.

You can perform a search by specifying the ID in the query string.

PortalQueryParameters itemIdQuery = new PortalQueryParameters("");
itemIdQuery.setQueryForItemWithId("1966ef409a344d089b001df85332608f");
final ListenableFuture<PortalQueryResultSet<PortalItem>> findItemsFuture = portal.findItemsAsync(itemIdQuery);
findItemsFuture.addDoneListener(new Runnable() {
  @Override
  public void run() {
    try {
      PortalQueryResultSet<PortalItem> queryResultSet = findItemsFuture.get();
      if (!queryResultSet.getResults().isEmpty()) {
        PortalItem theItem = queryResultSet.getResults().get(0);
        // Only expecting a single result as IDs must be unique
        showMessage(String.format("Found item, title=%s", theItem.getTitle()));
      }
    } catch (InterruptedException | ExecutionException e) {
      dealWithException(e);
    }
  }
});

You can also directly retrieve a PortalItem by ID using the overloaded constructor, passing in a Portal and the ID of the required item.

final PortalItem portalItem = new PortalItem(portal, "1966ef409a344d089b001df85332608f");
portalItem.addDoneLoadingListener(new Runnable() {
  @Override
  public void run() {
    showMessage(String.format("Loaded PortalItem by ID, title=%s", portalItem.getTitle()));
  }
});
portalItem.loadAsync();

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

PortalQueryParameters searchStringParams = new PortalQueryParameters("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.

PortalQueryParameters cultureQueryParams = new PortalQueryParameters("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.

The simplest way to search for the PortalItems featured as homepage content is to use the Portal.fetchHomePageFeaturedContentAsync method. Note this returns all the potential featured items, and is not limited by the number of items the portal administrator may have configured to be shown (which can be found from PortalInfo.getHomePageFeaturedContentCount).

final ListenableFuture<List<PortalItem>> featuredContentFuture = portal.fetchHomePageFeaturedContentAsync();
featuredContentFuture.addDoneListener(new Runnable() {
  @Override
  public void run() {

    try {
      final List<PortalItem> featuredContentItems = featuredContentFuture.get();
      // Display the featured content results - can use PortalInfo.getHomePageFeaturedContentCount to find how many
      // featured items are shown on the home page of the portal
      processResults(featuredContentItems);
    } catch (InterruptedException | ExecutionException e) {
      dealWithException(e);
    }
  }
});

Similarly, the fetchFeaturedItemsAsync method returns the set of featured items shown in the gallery.

final ListenableFuture<List<PortalItem>> featuredItemsFuture = portal.fetchFeaturedItemsAsync();
featuredItemsFuture.addDoneListener(new Runnable() {
  @Override
  public void run() {

    try {
      final List<PortalItem> featuredItems = featuredItemsFuture.get();
      // Display the featured items results...
      processResults(featuredItems);
    } catch (InterruptedException | ExecutionException e) {
      dealWithException(e);
    }
  }
});

Alternatively you can find the group or groups configured to contain featured content or items by using PortalInfo.getHomePageFeaturedContentGroupQuery or PortalInfo.getFeaturedItemsGroupQuery and using this value to set the query string for a PortalQueryParameters. You can then use the query to find the group or groups, and in turn query for the PortalItems contained. One advantage of this approach is that query results are returned in batches, suitable for paging.

PortalInfo info = portal.getPortalInfo();
PortalQueryParameters featuredContentGroupQuery = new PortalQueryParameters(info.getHomePageFeaturedContentGroupQuery());

final ListenableFuture<PortalQueryResultSet<PortalGroup>> findGroupsFuture = portal.findGroupsAsync(featuredContentGroupQuery);
findGroupsFuture.addDoneListener(new Runnable() {
  @Override
  public void run() {

    try {
      PortalQueryResultSet<PortalGroup> featuredContentGroupResults = findGroupsFuture.get();
      if (!featuredContentGroupResults.getResults().isEmpty()) {
        // Get the featured group or groups and use as required, for example issue another query...
        PortalQueryParameters groupContentQuery = new PortalQueryParameters();
        groupContentQuery.setQueryForItemsInGroup(featuredContentGroupResults.getResults().get(0).getGroupId());

        final ListenableFuture<PortalQueryResultSet<PortalItem>> findItemsFuture = portal.findItemsAsync(groupContentQuery);
        findItemsFuture.addDoneListener(new Runnable() {
          @Override
          public void run() {
            try {
              PortalQueryResultSet<PortalItem> groupContentResults = findItemsFuture.get();
              // Display the featured content results...
              processResults(groupContentResults.getResults());
              if (groupContentResults.getTotalResults() > groupContentResults.getResults().size());
                // results are present in more than one batch... deal with paging results
              } catch (InterruptedException | ExecutionException e) {
                dealWithException(e);
              }
            }
          });
      }
    } catch (InterruptedException | ExecutionException e) {
      dealWithException(e);
    }
  }
});

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.

final ListenableFuture<List<Basemap>> basemapsFuture = portal.fetchBasemapsAsync();
basemapsFuture.addDoneListener(new Runnable() {
  @Override
  public void run() {

    try {
      final List<Basemap> basemaps = basemapsFuture.get();

      // Display the available basemaps. If required, access the Basemap.Item to get information about the
      // PortalItem that references each Basemap item.
      processBasemaps(basemaps);

    } catch (InterruptedException | ExecutionException e) {
      dealWithException(e);
    }
  }
});

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.getBasemapGalleryGroupQuery) 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.

final ListenableFuture<List<PortalGroup>> featuredGroupsFuture = portal.fetchFeaturedGroupsAsync();
featuredGroupsFuture.addDoneListener(new Runnable() {
  @Override
  public void run() {

    try {
      final List<PortalGroup> featuredGroups = featuredGroupsFuture.get();
      // Display the available groups...
      processGroups(featuredGroups);
    } catch (InterruptedException | ExecutionException e) {
      dealWithException(e);
    }
  }
});

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 code below creates a PortalQueryParameters, sets the initial query, and calls the Portal.findItemsAsync method. After iterating through the initial results, PortalQueryResultSet.getNextQueryParameters is used to get the correct query to find the next set of results (you can check the getQuery method to find out how this works). If this object is not null, then a second call can be made to retrieve another page of results; this pattern can then be repeated until getNextQueryParameters returns null, indicating there are no more results to fetch.

queryParams = new PortalQueryParameters("global rainfall");
final ListenableFuture<PortalQueryResultSet<PortalItem>> findItemsFuture = portal.findItemsAsync(queryParams);
findItemsFuture.addDoneListener(new Runnable() {
  @Override
  public void run() {
    try {
      // Process the query results...
      resultSet = findItemsFuture.get();
      processResults(resultSet);

      // Check if there are more results beyond this first set.
      PortalQueryParameters nextPageQuery = resultSet.getNextQueryParameters();
      if (nextPageQuery != null) {
        // Present a UI to page through results by using nextPageQuery...
      }
    } catch (InterruptedException | ExecutionException e) {
      dealWithException(e);
    }
  }
});

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