R/get_by_fids.R

Defines functions get_by_fids

Documented in get_by_fids

#' Get by FIDs
#'
#' Get a layer by querying the FIDs
#'
#' This function works by checking if the requested return count is less tha the max record count.
#' If so, it doesn't bother with getting the FIDs and just requests the data and returns it.
#' Getting FIDs is a big overhea so this should be avoided where possible.
#' @param endpoint a string defining the enpoint url.
#' It can be generated by the \code{feature_server_endpoint} and \code{map_server_endpoint} functons.
#' See https://developers.arcgis.com/rest/services-reference/get-started-with-the-services-directory.htm
#' @param my_token an access token acquired via \code{get_token}
#' @param query the query to POST
#' @param return_geometry should the geometry be returned or just a table?
#' @param return_n how many features (maximum) should be returned by the query?
#' @param layer_details the layer details returned by the get_layer_details function
#' @param out_fields the fields of the layer to return (character vector)
#' @param object_ids a vector of object IDs to return if this argument is NULL the function will get them
#' but passing them in aids performance if they have already been returned
#' @return a tibble or sf object
#' @importFrom progress progress_bar
#' @importFrom purrr map
#' @importFrom dplyr bind_rows
#' @importFrom utils modifyList
get_by_fids <-
  function(endpoint,
           query,
           my_token,
           return_geometry,
           return_n,
           layer_details,
           out_fields,
           object_ids = NULL) {
    # This function works by checking if the requested return count is less tha the max record count.
    # If so, it doesnn't bother with getting the FIDs and just requests the data and returns it.
    # Getting FIDs is a big overhea so this should be avoided where possible.
    query_url <- paste0(endpoint, "/query")

    if(is.null(object_ids)){
    # If Object IDs are null then get them for the query
    # The FIDs are used for two things: first to determine if any results will be returned by a query;
    # second to get the data by FIDs
      object_ids <-
        get_feature_ids(endpoint = endpoint,
                        query = query,
                        my_token = my_token)
    }

    # Check if any FIDs will be returned by the query, if not return an empty tibble avoiding the query
    if (length(object_ids$objectIds) == 0) {
      warning("No data matching query, returning an empty tibble")
      return(
        make_empty_table(
          field_names = field_names(layer_details),
          out_fields = out_fields,
          id_field = object_ids$objectIdFieldName,
          return_geometry = return_geometry
        )
      )
    }

    # Then split the vector so it doesn't exceed the max record count
    object_ids_split <-
      split_vector(x = object_ids$objectIds,
                   max_length = layer_details$maxRecordCount)

    querys <-
      purrr::map(object_ids_split,
                 ~ utils::modifyList(
                   query,
                   id_query(object_id_name = object_ids$objectIdFieldName, object_ids = .x, map_server = map_server(endpoint))
                 ), keep.null = FALSE)

    # Define a progress bar
    pb <- progress::progress_bar$new(
      total = length(querys),
      clear = FALSE,
      width = 60,
      format = "  Downloading data [:bar] :percent in :elapsed eta: :eta"
    )

    # Download the data for each query
    data_list <- purrr::map(
      querys,
      ~ get_data(
        query_url = query_url,
        query = .x,
        my_token = my_token,
        pb = pb
      )
    )

    # Need to add some error checking functionality here
    # any(names(data_list) == "error") stop() message(cat(data_list))

    # Parse the json returned by the api
    parse_esri_data(data_list,
                            geometry = return_geometry & !is_table(layer_details))
  }
MatthewJWhittle/getarc documentation built on April 22, 2023, 12:16 p.m.