DEV Community

loading...

Yelp GraphQL Demo

Related Code
Mobile Application Development. Scalable Architecture Design. Custom Backend Development. Application Security. Performance Engineering. Analytics. Maintenance.
・3 min read

Moving away from the demonstration API examples towards real life, the Yelp GraphQL API could be a good exercise to start with.

Since the Yelp GraphQL API is part of their Developer Beta program, you will need to make few extra steps before using the endpoint. You definitely will need an API Key here, other than just the base url.

Screenshot

In our demo app, we will fetch restaurants using the following query.

query SearchRestaurants($term: String!, $location: String!, $limit: Int!, $offset: Int) {
  search(term: $term, location: $location, limit: $limit, offset: $offset) {
    total
    business {
      id
      name
      alias
      rating
      url
      is_claimed
      is_closed
      phone
      display_phone
      review_count
      price
      location {
        address1
        address2
        address3
        city
        state
        postal_code
        country
        formatted_address
      }
      coordinates {
        latitude
        longitude
      }
      reviews {
        id
        rating
        user {
          id
          name
          profile_url
          image_url
        }
        text
        time_created
        url
      }
      photos
      distance
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Since the query structure is pretty complex, we need to split the received data into the following tables.

class Restaurant: NSObject, GQLObject {

  @objc var id = ""
  @objc var name = ""
  @objc var alias = ""
  @objc var rating = 0.0
  @objc var url = ""
  @objc var is_claimed = false
  @objc var is_closed = false
  @objc var phone = ""
  @objc var display_phone = ""
  @objc var review_count = 0
  @objc var price = ""
  @objc var distance = 0.0
  @objc var photo = ""

  class func primaryKey() -> String {
    return "id"
  }
}
Enter fullscreen mode Exit fullscreen mode
class Locations: NSObject, GQLObject {

  @objc var id = ""
  @objc var address1 = ""
  @objc var address2 = ""
  @objc var address3 = ""
  @objc var city = ""
  @objc var state = ""
  @objc var postal_code = ""
  @objc var country = ""
  @objc var formatted_address = ""

  static func primaryKey() -> String {
    return "id"
  }
}
Enter fullscreen mode Exit fullscreen mode
class Coordinates: NSObject, GQLObject {

  @objc var id = ""
  @objc var latitude = 0.0
  @objc var longitude = 0.0

  static func primaryKey() -> String {
    return "id"
  }
}
Enter fullscreen mode Exit fullscreen mode
class Review: NSObject, GQLObject {

  @objc var id = ""
  @objc var rating = 0.0
  @objc var text = ""
  @objc var time_created = ""
  @objc var url = ""

  @objc var restaurant_id = ""

  @objc var user_id = ""
  @objc var user_name = ""
  @objc var user_profile_url = ""
  @objc var user_image_url = ""

  class func primaryKey() -> String {
    return "id"
  }
}
Enter fullscreen mode Exit fullscreen mode

Screenshot

The fetching methods are more or less the same as what we had in the previous demos.

func fetch(_ query: String, _ variables: [String: Any]) {

  server.query(query, variables) { result, error in
    if let error = error {
      print(error.localizedDescription)
    } else {
      if let dictionary = result.values.first as? [String: Any] {
        if let array = dictionary["business"] as? [[String: Any]] {
          for values in array {
            self.updateDatabase(values)
          }
        }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
func updateDatabase(_ values: [String: Any]) {

  guard let restaurantId = values["id"] as? String else { return }

  if var coordinates = values["coordinates"] as? [String: Any] {
    coordinates["id"] = restaurantId
    gqldb.updateInsert(Coordinates.table(), coordinates)
  }

  if var location = values["location"] as? [String: Any] {
    location["id"] = restaurantId
    gqldb.updateInsert(Locations.table(), location)
  }

  if let reviews = values["reviews"] as? [[String: Any]] {
    for review in reviews {
      updateReview(review, restaurantId)
    }
  }

  var restaurant = values
  if let photos = values["photos"] as? [String] {
    if let photo = photos.first {
      restaurant["photo"] = photo
    }
  }
  gqldb.updateInsert("Restaurant", restaurant)
}
Enter fullscreen mode Exit fullscreen mode

The responses are paginated by the API, so we need to fetch the data accordingly.

func fetchObjects() {

  let query = GQLQuery["SearchRestaurants"]

  let offset = Restaurant.count(gqldb)
  let variables: [String: Any] = ["term": "Restaurants", "location": "San Francisco", "limit": 10, "offset": offset + 1]

  fetch(query, variables)
}
Enter fullscreen mode Exit fullscreen mode

Once we have the fetched data in the local database, we only need to display them in some TableViews.

Screenshot

And pretty much that's all we need for a basic Yelp demo app. You can check the full source code here.

Discussion (0)