# Choose or write config modifier selectors

In a config modifier, a <u>**selector**</u> serves two purposes: 

- Sets the scope of the input for the config modifier schema.
- Defines the JSON path where the modifier acts and changes the output. In other words, the selector determines where a config modifier's defined processing should happen within a payload. 

By designating the path and using config modifier keywords, you can choose which action should happen on the specified selector. There's intentionally a lot of flexibility. You can overwrite existing values and arrays, add to existing arrays, or build new arrays altogether. 

This article contains guidelines for writing your selectors and config modifiers based on what action you want to occur on the payload. 

> **Other docs about config modifiers**
>
> - [Change data with config modifiers](/how-to-use-redox/change-data-with-config-modifiers)
> - [Create and link a config modifier](/how-to-use-redox/change-data-with-config-modifiers/set-up-config-modifiers)
> - [Build a config modifier](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema) (includes common use cases)

## Different formats

There are different ways to choose or write a selector for a config modifier. It largely depends on which format the data is in. 

For Redox data models or FHIR resources, [follow the guidelines for choosing a selector from a drop-down list](https://docs.redoxengine.com/permalink/1EFEDDZG8zyMgYVFlG3eoj/#choose-a-selector-from-the-drop-down).

For all other formats, [follow the guidelines for writing a selector](https://docs.redoxengine.com/permalink/1EFEDDZG8zyMgYVFlG3eoj/#write-a-selector). 

Because of format differences, you might use paths like any of these for different formats: 

| **Format** | **Selector example** |
| --- | --- |
| Redox data model | `$.Visit.Insurances[*].Plan.ID` |
| Redox FHIR | `$.entry[?(@.resource.resourceType=="Patient")].resource.address[*].state` |
| HL7v2 | `$.INSURANCE[*].IN1.2.1` |

## Choose a selector from the drop-down

If you're targeting a field path from a Redox data model or FHIR resource, select the field path from a drop-down list. The drop-down list is comprehensive for data models but not for FHIR paths (there are too many possibilities with FHIR to show all the options). 

You can manually edit the field path after you've chosen it from the drop-down.

## Write a selector

If you're targeting a field path for any other format (i.e., not a Redox data model or FHIR resource), you must write the JSON path from scratch. If needed, find the field path in the input payload snapshot for reference. 

Then, [review a help article](https://goessner.net/articles/JsonPath/) and refer to these JSONPath expressions to help write your JSON path correctly:

| **Expression** | **Notes** |
| --- | --- |
| `$` | The root object or element. The start of your path must contain `$`. |
| `@` | The current object or element. |
| `@root` | The root node. |
| `@parent` | The parent node. |
| `.` or `[]` | The child operator. |
| `..` | Recursive descent. JSONPath borrows this syntax from E4X. |
| `*` | Wildcard. Includes all objects or elements, regardless of their names. |
| `[?(...)]` | Applies a filter expression (for arrays). |
| `==` or `&&` or `\|\|` | Direct equality and boolean comparison operators (`<` and `>` aren't allowed). |

## Copy path options

Instead of writing a path, you can also copy a selector path from a JSON payload within log inspector. All you have to do is find an operation with the JSON payload snapshot you want to act on. 

> **Some notes**
>
> You should keep in mind these things if you're copying a selector path: 
>
> - You don't have to have any config modifiers set up to copy from a JSON payload.   
> - If there's a diff view with two JSON payloads in an operation, the copy options are only available on the output payload. A diff view highlights the differences between the input and output payload snapshots and appears when:
>   - The operation has both an input and output. 
>   - The input and output are both JSON. 
>   - The operation type isn't `deliveries` or `Redox base configs`. 

1. Within log inspector, find an operation with one or more JSON payload snapshots. 
2. Find the array or field you want to target with the config modifier. 
3. Right-click on the array or field. Three copy options display in the menu: 
   - **Copy selector - wildcard**
     - This option copies the path with an \* to match on ALL items within the selected array (i.e., $`my.array[*].field`). If there isn't an array, this copies the same path as <u>Copy selector - exact</u>.
   - **Copy selector - exact**
     - This option copies the path to match on ONLY the selected item in the array (i.e., $`my.array[1].field`). 
   - **Copy get path**
     - This option copies the path used for the `get` operation within a config modifier schema (i.e., `my.array[1].field`).

![Copy options](https://images.ctfassets.net/cl3wt5ehhnlv/2XtFsxzWOwEdkNLLpfbrCB/853b4d4069f2aeddf7966933ef79b893/Config_modifiers_copy-from-selector.png)

*Copy options*

## No search indexing

The selector defines what to operate on in a payload. However, the output of a config modifier isn't indexed for Redox log searches. 

Redox indexes payloads for search _before_ a config modifier runs. This means if you choose a selector path that you later want to search for in the log, you won't be able to find it with our log search in the Redox processing stage. For example, if your selector path is `AttendingProvider`, it will appear correctly in the destination's payload, but it won't be searchable in the Redox dashboard and it won't be under the Redox processing log stages. 

If you want to modify and search for a particular indexed field, it must be modified in a <u>**Redox base config**</u> instead. Talk to your Technical Account Manager with your use case.

## Asterisks and arrays for selectors

An asterisk (`*`) indicates that all objects or elements should be included, regardless of their name. You can use asterisks in selectors to indicate that all items within an array should be acted upon. 

### Operate on all elements

Use an asterisk (`*`) at the end of an array path name to operate on all elements within an array.  

Let's say you have this initial payload: 

**Example: Initial payload with an array**

```json
{
  "My": {
    "ArrayPath": [{
      "PropertyName": "value-1"
    }, {
      "PropertyName": "value-2"
    }]
  }
}
```

You want to replace everything inside `ArrayPath`. So you would write this selector:

**Example: Selector with asterisk**

```json
$.My.ArrayPath[*] 
```

And build a config modifier schema with a keyword like this: 

**Example: Config modifier for selector**

```yaml
constant: 'new-value'
```

These would produce this output payload: 

**Example: Output payload with an array**

```json
{
  "My": {
    "ArrayPath": [
      "new-value",
      "new-value"
    ]
  }
}
```

Since the original values in the array are replaced, you'd end up with the same number of values that existed in the input. However, they'd be replaced with the new values indicated in the config modifier schema. 

### Operate on specific elements

Use an asterisk (`*`) at the end of the array path name to operate on all elements within an array. However, if you only want to operate on specific elements within the array, add the element name without an asterisk. 

Let's say you have this initial payload: 

**Example: Initial payload with an array and different values**

```json
{
  "My": {
    "ArrayPath": [{
      "PropertyA": "old-value-1",
      "PropertyB": "value-will-not-change"
    }, {
      "PropertyA": "original-value-2",
      "PropertyB": "value-will-not-change"
    }]
  }
}
```

You want to modify a specific element within `ArrayPath`. So you would write this selector:

**Example: Selector for specific properties in an array **

```json
$.My.ArrayPath[*].PropertyA
```

And build a config modifier schema with a keyword like this: 

**Example: Config modifier for selector**

```yaml
constant: 'new-value'
```

These would produce this output payload: 

**Example: Output payload with an array and different values**

```json
{
  "My": {
    "ArrayPath": [{
      "PropertyA": "new-value",
      "PropertyB": "value-will-not-change"
    }, {
      "PropertyA": "new-value",
      "PropertyB": "value-will-not-change"
    }]
  }
}
```

So all items with the same property name would change. 

### Replace an existing value

To overwrite an existing value, enter the specific element name without an asterisk (`*`). If you enter a specific array name, this means that the new value will overwrite the entire array. 

For example, let's say you have this initial payload: 

**Example: Initial payload with an array**

```json
{
  "My": {
    "ArrayPath": [{
      "PropertyName": "value-1"
    }, {
      "PropertyName": "value-2"
    }]
  }
}
```

You want to overwrite all the values within `ArrayPath`. So you would write this selector:

**Example: Selector without an asterisk**

```json
$.My.ArrayPath
```

And build a config modifier schema with a keyword like this: 

**Example: Config modifier for selector**

```yaml
constant: 'new-value'
```

These would produce this output payload: 

**Example: Output payload with an overwritten array**

```json
{
  "My": {
    "ArrayPath": "new-value"
  }
}
```

### Create a new array

Use the `concat` keyword to build elements into a new array within a payload.  

> **Useful expressions for concat**
>
> There are a couple of expressions that you should know about when using `concat`.
>
> - `-` : Indicates an array or list item in standard YAML and can still be used that way generally with config modifiers. However, in the context of `concat`, a hyphen (`-`) can also indicate one independent value that should be present in an array. Each element in the array should be designated with a `-` before the key-value pair.
> - `{}`: Refers to a current value in an array within the initial payload. Use this to retain an original value rather than deleting or overwriting it. To make sure the value appears in a processed payload as-is, add this expression on its own line in the `concat` object as `- {}`. 

Let's say you have this initial payload: 

**Example: Initial payload without an array**

```json
{
  "My": {
    "Property": "value-1"
  }
}
```

You want to build an entirely new array. So you would write this selector:

**Example: Selector for creating an array**

```json
$.My.NewArray
```

And build a config modifier schema with a keyword like this: 

**Example: Config modifier for creating an array**

```yaml
concat:
  - constant: new-value
```

These would produce this output payload: 

**Example: Output payload with new array**

```json
{
  "My": {
    "Property": "value-1",
    "NewArray": [
      "new-value"
    ]
  }
}
```

### Add new values

Use the `concat` keyword to add values to an existing array within a payload, while retaining any initial values.  

> **Useful expressions for concat**
>
> There are a couple of expressions that you should know about when using `concat`.
>
> - `-` : Indicates an array or list item in standard YAML and can still be used that way generally with config modifiers. However, in the context of `concat`, a hyphen (`-`) can also indicate one independent value that should be present in an array. Each element in the array should be designated with a `-` before the key-value pair.
> - `{}`: Refers to a current value in an array within the initial payload. Use this to retain an original value rather than deleting or overwriting it. To make sure the value appears in a processed payload as-is, add this expression on its own line in the `concat` object as `- {}`. 

Let's say you have this initial payload: 

**Example: Initial payload to add new values**

```json
{
  "My": {
    "ArrayPath": [{
      "PropertyName": "value-1"
    }, {
      "PropertyName": "value-2"
    }],
    "Property": "value-3"
  }
}
```

You want to add new values along with existing values at `My.Property`. So you would write this selector:

**Example: Selector for adding to an existing array**

```json
$.My.Property
```

And build a config modifier schema with a keyword like this: 

**Example: Config modifier for adding to an array**

```yaml
concat:
  - {}
  - constant: new-value
```

These would produce this output payload: 

**Example: Output payload with new values**

```json
{
  "My": {
    "ArrayPath": [{
      "PropertyName": "value-1"
    }, {
      "PropertyName": "value-2"
    }],
    "Property": [
      "value-3",
      "new-value"
    ]
  }
}
```

So you would retain original values while adding new values to the array. 

### Modify specific values

Specify a particular value in an array that should change based on your selector.  

Let's say you have this initial payload: 

**Example: Initial payload to change an array**

```json
{
  "MyProperty": [{
    "id": "some-id",
    "value": "some-value"
  }, {
    "id": "specific-id",
    "value": "specific-value"
  }]
}
```

You want to change the `id` value within the array at `My.Property`, but you only want to change the value where `id` is currently equal to `specific-id`:

**Example: Selector for changing values in an existing array**

```json
$.MyProperty[?(@.id=="specific-id")].id
```

And build a config modifier schema with a keyword like this: 

**Example: Config modifier for changing a value within an array**

```yaml
constant: new-id
```

These would produce this output payload: 

**Example: Output payload to change an array**

```json
{
  "MyProperty": [{
    "id": "some-id",
    "value": "some-value"
  }, {
    "id": "new-id",
    "value": "specific-value"
  }]
}
```

So only one value in an array would change based on the conditions you defined. 

### Refer to a defined selector

In your config modifier schema, you can sometimes refer to the defined selector with `{}` instead of repeating the path. This is possible when you're referring to the selector within most keyword statements. More specifically, if you need to access the input payload provided by the selector as an argument to your keyword, use `{}`. However, you can't refer to the selector in a `get` statement or outside the context of an accepted keyword.

**Example: Use {} in a keyword statement**

```yaml
if:
  operator: all
  terms:
    - {}
  then:
    constant: true
  else:
    constant: false
```

> **Config modifier vs. translation set**
>
> Both config modifiers and translation sets can alter specific values in a payload.
>
> When should you use a config modifier versus a translation set?
>
> - A <u>translation set</u> maps a list of values from one code set to another. It’s useful if you have lots of values you want to change based on different code sets used by different systems. This is a static mapping that looks for a particular value and translates it to a corresponding value. [Learn about translation sets](/how-to-use-redox/create-translation-sets-and-links).
> - A <u>config modifier</u> contains flexible instructions based on conditions. For example, you could map a specific value to another _only if_ another specified field is present. Essentially, a config modifier allows you to define conditional or fallback behavior. Also, you can only define instructions for values at one field path at a time. If you wanted to change lots of values in different locations, you’d have to create a config modifier for each one.
