# Performing mutations

> Triggering updates / mutations using TaxiQL

Source: https://orbitalhq.com/docs/querying/mutations

Mutation queries make changes somewhere - ie., perform a task, or update a record.

Mutating operations are defined in Taxi using the `write` modifier:

```taxi
service FlightsService {
  write operation bookFlight(BookingRequest):BookingConfirmation
  write operation sendFlightManifest(Manifest):ManifestConfirmation
}
```

Mutating operations are excluded from being invoked during a query (ie., anything with a `find {}` or `stream {}` directive.)

Instead, they are invoked using a `call` directive.

```taxi
find { Passengers[] }
call FlightsService::sendFlightManifest
```

In this example, a list of `Passengers` is fetched, and converted into a `Manifest` to call the `sendFlightManifest` operation
of the `FlightsService`.

Many different data sources support mutations, such as [databases](/docs/describing-data-sources/databases#writing-data-to-a-database),
[Kafka](/docs/describing-data-sources/kafka#writing-to-a-kafka-topic), [MongoDB](/docs/describing-data-sources/mongodb#writing-data-to-a-collection),
and [Hazelcast](/docs/describing-data-sources/hazelcast#writing-data-to-hazelcast).

Consult the docs for the relevant data source to learn more.

## Projecting and mutating
Orbital will automatically convert from the source type to whatever is required in the input of the mutation operation.

For example:

```taxi

// The data we're writing to our database
@Table(connection = "films-database", schema = "public" , table = "films" )
closed parameter model Film {
  @Id
  filmId : FilmId inherits Int
  title : Title inherits String
  reviewScore : ReviewScore inherits Int
}

@DatabaseService(connection = "films-database")
sevice FilmsDatabase {
  @UpsertOperation
  write operation saveFilm(Film):Film
}

// Our source format
closed model Movie {
   // doesn't have reviews
   title : FilmId
}

// Another source containing reviews
closed model Review {
   id : FilmId
   score : ReviewScore
}
```

Given the above services and models, we can write a mutating query to find films, enrich them, and write to our database:

```taxi
find { Film[] }
call FilmsDatabase::saveFilm
```

In the above example, note that our source format - `Movie` lacks review data, but out target format - `Film` needs it.   

Orbital detects that the source and target formats don't align, and so automatically triggers a projection to enrich the source data
with reviews:

[![](https://mermaid.ink/img/pako:eNptUctOwzAQ_JVoTyCFtonJoz5wAiQOCKm9QThs401ikcTBcQqlyr_jPChUwifvzHhmd32EVAkCDi29d1SndCsx11gltWPPk95Jg6VzdXPj3Muy2pLey5S4k5MZ6kn1hxmV8ys-Ei-vk6hUqnE21BAaEk6mtEOYFk52cjlP29Be0sffvAm5GDwfxOXPmzPdefpE_Wc-eLS3aHCHrTVvcU-_01AtwIWKdIVS2MUcBzgBU1BFCXB7FajfEkjq3uqwM2p7qFPgRnfkQtcIO-C8ROAZlq1FG6yBH-ET-JXH2MKP4zXzmbeOArZiLhyAe56_CFYsjsIgClaeH_QufCllLTwXSEij9OP0UeN__QTdjcwpp1QoSA9R5tAM4ly2xopTVWcyH_BOlxYujGlavlwO9CKXpuh2i1RVy1aKArUp9utwGfphjD6jMGIYMCbSnbeOM__ay0RkG0To-3Gw57HLuQGturyYq_4b2h_Bog?type=png)](https://mermaid.live/edit#pako:eNptUctOwzAQ_JVoTyCFtonJoz5wAiQOCKm9QThs401ikcTBcQqlyr_jPChUwifvzHhmd32EVAkCDi29d1SndCsx11gltWPPk95Jg6VzdXPj3Muy2pLey5S4k5MZ6kn1hxmV8ys-Ei-vk6hUqnE21BAaEk6mtEOYFk52cjlP29Be0sffvAm5GDwfxOXPmzPdefpE_Wc-eLS3aHCHrTVvcU-_01AtwIWKdIVS2MUcBzgBU1BFCXB7FajfEkjq3uqwM2p7qFPgRnfkQtcIO-C8ROAZlq1FG6yBH-ET-JXH2MKP4zXzmbeOArZiLhyAe56_CFYsjsIgClaeH_QufCllLTwXSEij9OP0UeN__QTdjcwpp1QoSA9R5tAM4ly2xopTVWcyH_BOlxYujGlavlwO9CKXpuh2i1RVy1aKArUp9utwGfphjD6jMGIYMCbSnbeOM__ay0RkG0To-3Gw57HLuQGturyYq_4b2h_Bog)

### Manually projecting
If you want more control (eg., for performing calculations or derived fields), you can manually define a projection:

```taxi
find { Film[] } as {
  id : FilmId
  title : Title = upperCase(Title) // make all the titles uppercase in the db
}
call FilmsDatabase::saveFilm
```

Here, Orbital still performs a series of projections:
 - First, projecting from `Film` to the inlined type (defined in the projection)
 - Then from the inlined type to the input type of the mutating operation (`FilmsDatabase::saveFilm`)

[![](https://mermaid.ink/img/pako:eNplULtOxDAQ_JVoK5DyOMfk5YIKOmigQ2kW20nMJXbkOAfHKf-OEwISolvPjHdm5wLcCAkMmt688w6tCx6eah0EQaO0CKLoNhiteZPcbeA-77iMhtmhU0ZHf0X_ie2H0idzlFcc-z4wo7Sb4rrWEMIg7YBK-CCXdUcNrpODrIH5UaA91lDrxetwdub5rDkwZ2cZwjwKdPJOYWtxANZgP3l0RA3sAh_AIkJpnJZlRVNKqiKjBxrCGRghaZwdaFnkWZEdSJotIXwa41eQEKRQztjH72K2fn6M7jfm16c3KKRdrdx5XMWtmpwXc6Mb1a74bHsPd86NE0uSlY5b5br5NeZmSCYl1sq7U5UneZqXmFKZFxQzSgV_JVXZpDekEYUPiLAs22EvW8o9gDVz2-2v5Qsu8pSV?type=png)](https://mermaid.live/edit#pako:eNplULtOxDAQ_JVoK5DyOMfk5YIKOmigQ2kW20nMJXbkOAfHKf-OEwISolvPjHdm5wLcCAkMmt688w6tCx6eah0EQaO0CKLoNhiteZPcbeA-77iMhtmhU0ZHf0X_ie2H0idzlFcc-z4wo7Sb4rrWEMIg7YBK-CCXdUcNrpODrIH5UaA91lDrxetwdub5rDkwZ2cZwjwKdPJOYWtxANZgP3l0RA3sAh_AIkJpnJZlRVNKqiKjBxrCGRghaZwdaFnkWZEdSJotIXwa41eQEKRQztjH72K2fn6M7jfm16c3KKRdrdx5XMWtmpwXc6Mb1a74bHsPd86NE0uSlY5b5br5NeZmSCYl1sq7U5UneZqXmFKZFxQzSgV_JVXZpDekEYUPiLAs22EvW8o9gDVz2-2v5Qsu8pSV)

### Writing single item vs batch
Generally, Orbital tries to run projections and mutations in parallel, and - where possible - using micro-batching to batch writes.

However, sometimes you want everything written in a single write - such as writing a file to S3 (where incremental updates
aren't supported by S3)

To support this, simply declare the input into your mutation as an array.

For example, to update our earlier example to write to S3 instead of a database - let's add the S3 sink:

```taxi
@S3Service(connectionName = "MyAwsConnection")
service AwsBucketService {
    @S3Operation(bucket = "MyBucket")
    write operation writeToS3(@RequestBody films:Film[], filename:FilenamePattern = "films.csv"):Film[]
}
```

By updating our query:

```taxi
find { Film[] }
call AwsBucketService::writeToS3
```

This time, the enrichments happen in parallel, but are held until the all enrichments are finished, then written to S3 in a batch at the end:

[![](https://mermaid.ink/img/pako:eNplUctugzAQ_BVrT41EHuDyiA85tZV6qColPTX04OAFrAKmxiRNI_69BtIoUX3y7szO7OMEiRIIDBr8arFK8EHyTPMyroh9r3onDS_IdLUiT7IoN6j3MkFGMjR9PLKukIF5rmIDsP0YSYVSNVljjdygIKnSBHmSk_Sicuu2xr3Ew7XfmLnrNZ_F5K_mhnfrPkIjESvxf6INZeSgpcE3taFkUG62HxNwoERdcinsWk59WQwmxxJjYPYruP6MIa46y-OtUZtjlQAzukUH2lrY8c4rBJbyorHZmlfATvANbOpSOvOiaEk96i5Dny6oA0dgruvN_AWNwsAP_YXr-Z0DP0pZCdcBFNIo_TKeabjWn9HjgFx8CsUF6t7KHOuenMnGWHKiqlRmfb7VhU3nxtQNm897eJZJk7e7WaLKeSNFzrXJ98tgHnhBxD2KQUi5T6lIdu4ySr17NxWhbZBD1w2DvQ9dnhvQqs3yc9T9AkaNwDk?type=png)](https://mermaid.live/edit#pako:eNplUctugzAQ_BVrT41EHuDyiA85tZV6qColPTX04OAFrAKmxiRNI_69BtIoUX3y7szO7OMEiRIIDBr8arFK8EHyTPMyroh9r3onDS_IdLUiT7IoN6j3MkFGMjR9PLKukIF5rmIDsP0YSYVSNVljjdygIKnSBHmSk_Sicuu2xr3Ew7XfmLnrNZ_F5K_mhnfrPkIjESvxf6INZeSgpcE3taFkUG62HxNwoERdcinsWk59WQwmxxJjYPYruP6MIa46y-OtUZtjlQAzukUH2lrY8c4rBJbyorHZmlfATvANbOpSOvOiaEk96i5Dny6oA0dgruvN_AWNwsAP_YXr-Z0DP0pZCdcBFNIo_TKeabjWn9HjgFx8CsUF6t7KHOuenMnGWHKiqlRmfb7VhU3nxtQNm897eJZJk7e7WaLKeSNFzrXJ98tgHnhBxD2KQUi5T6lIdu4ySr17NxWhbZBD1w2DvQ9dnhvQqs3yc9T9AkaNwDk)
