5. Matching and replacing values
4m

Overview

Let's explore how to work with enum types in our mapping.

In this lesson, we will:

  • Learn how to match and replace values
  • Learn about the @ symbol

Matching values

Let's return to our schema. We've given our Product type a new : category, which returns an enum of type Category.

schema.graphql
type Product {
# ... other product fields
"The category this product belongs to"
category: Category!
}

We're using an enum type for the category so that we can group our products into a set of standard, predefined categories. This lets us limit categories to just the options that we specify: ACCESSORIES, APPAREL, and MISC, among others.

schema.graphql
enum Category {
ACCESSORIES
APPAREL
DECOR
ELECTRONICS
GAMES
MISC
}

Back in our JSON, we'll see our products include their own "category" ; its value can range from "toys", to "home decor", to many more. Adding more diverse products to our inventory will presumably result in lots more categories we can't begin to predict.

Already we can see that the values in our data don't exactly align with the options in our Category enum. So in order to sync our JSON response with our schema definition, we can put the match method to work.

With match, we define what some resulting value should be based on its original value. In practice, this means defining various cases that our mapping will attempt to "match" each value against; if the value matches, the method swaps in the value that we specify instead.

A diagram showing how with match we can determine a resulting value based on an original value

This means we can transform what we return for a product's category ("gear") into the corresponding value we want (ACCESSORIES). We can also define a catch-all case, in the event that none of our options are matched (such as MISC for "Miscellaneous" in our enum type).

Let's return to the mapping playground. A product's category appears outside of its variants array, so let's add our new property at the same level of indentation as our id, name, tagline, and tags .

$.products {
id
name
tagline: description
tags {
id: tagId
name
}
category
variants->first {
price: price.original
quantity: inventory.quantity
specifications: specifications->entries {
name: key
value
}
}
}

The category property is what we're going to apply our match transform to, but it's also the name we want to use as our output key. So right away let's add a colon (:) followed by category again.

category: category

Nothing's changed—yet. Now let's apply the match method. Add the arrow (->) followed by match and a set of parentheses (()).

category: category->match()

A red squiggly will alert us to what's missing from match:

The error message
Method ->match did not match any [candidate, value] pair.

Let's see how this works by specifying what we want the category from our first product, "gear", to be converted to. In this case, let's choose the ACCESSORIES option from our Category enum.

We'll pass a set of square brackets ([]) into match(). Here we need to provide a pair of values: first, the value that should be matched, then what the matching value should be converted to.

category: category->match(
["gear", "ACCESSORIES"]
)

Right now, our mapping syntax will still show an error: this is because some categories in our data were not "matched" and replaced with a different value. To fix this, let's keep going.

An error indicating that some categories were not matched to a replacement value

Further down in our products data, we'll find a category of "clothing". Let's add another condition to our match method to return "clothing" as APPAREL. Each new "candidate/value" pair should be contained within its own set of square brackets, with each pair separated by a comma.

category: category->match(
["gear", "ACCESSORIES"],
["clothing", "APPAREL"]
)

We could keep going this way—but as our list of products grows, we might encounter more and more new categories we'd then have to account for in the match method.

Ideally, we'd bucket any new categories we haven't already accounted for into the MISC option in our enum, for "Miscellaneous". So how do we pass a catch-all value in case there aren't any other matches for a particular category? Introducing: the @ symbol!

The @ symbol

Whenever we apply a transform method to a value, we can refer to the value being transformed using the @ symbol. In many methods, this symbol lets us refer to the value that we're transforming and define what should be done with it: we can select and return specific properties, change them, or wrap them up in a new enclosing object.

In our case, we'll use @ to provide a catch-all value for a product's category when it isn't matched against any of our other options. And because the @ symbol represents the current value being matched, that value will always match against itself!

If we encounter a category we haven't already matched against a different option, we'll stick it in the MISC category.

A diagram showing how all other candidates will be matched to the @ symbol if they haven't yet found a match before

Let's add that catch-all condition to our match.

category: category->match(
["gear", "ACCESSORIES"],
["clothing", "APPAREL"],
[@, "MISC"]
)

Note: If we made [@, "MISC"] the first option in the match method, every category would match against itself (@) and get converted to "MISC". Let's keep it at the end so it catches only those values that haven't already been matched!

With our match method in place, we should see that we've successfully updated each product's "category" to match one of the values in our enum.

The match method updated so that unmatched categories become MISC

Practice

Use the mapping below to answer the next question.

category: category->match(
["switch", "ELECTRONICS"],
[@, "MISC"]
["vase", "DECOR"],
)
Given the mapping above, what will be the output if category is "vase"?
Given the mapping above, what will be the output if category is "switch"?

Key takeaways

  • The match method allows us to locate instances of some value in our data, and replace them with a value that we define.
  • The @ symbol is used to refer to the value we are applying a transform method to. With match, we can use @ to specify our catch-all match, and replace any values that are not matched by our other options.

Journey's end

We've covered a lot of ground! With some new methods in our back pocket, we can traverse and transform our JSON responses confidently. We hope you'll continue to share your connectors journey with us—and we'll see you next time on !

Previous

Share your questions and comments about this lesson

This course is currently in

beta
. Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.