Extra
Composite Types

Composite Types

Available since v0.6.7

When using MongoDB you will likely need to use embedded documents (opens in a new tab), which Prisma calls 'Composite Types'. Prisma Client Rust will generate field & type modules whenever you use composite types, allowing you to perform CRUD operations on them.

These docs will only focus on Rust-specific details, checkout Prisma's documentation (opens in a new tab) for a comprehensive guide including a list of all available operations, filters, and some caveats to keep in mind.

All examples will use the following schema:

model Product {
  id     String  @id @default(auto()) @map("_id") @db.ObjectId
  name   String  @unique
  price  Float
  colors Color[]
  sizes  Size[]
  photos Photo[]
  orders Order[]
}
 
model Order {
  id              String   @id @default(auto()) @map("_id") @db.ObjectId
  product         Product  @relation(fields: [productId], references: [id])
  color           Color
  size            Size
  shippingAddress Address
  billingAddress  Address?
  productId       String   @db.ObjectId
}
 
enum Color {
  Red
  Green
  Blue
}
 
enum Size {
  Small
  Medium
  Large
  XLarge
}
 
type Photo {
  height Int    @default(200)
  width  Int    @default(100)
  url    String
}
 
type Address {
  street String
  city   String
  zip    String
}

Filtering

To find records with matching composite types, use the field's filter functions in combination with the type's field modules' equals functions.

let orders = client
	.order()
	.find_many(vec![
		order::shipping_adress::is(vec![
			address::street::equals("555 Candy Cane Lane".to_string()),
			address::city::equals("Wonderland".to_string()),
			address::street::equals("52337".to_string()),
		])
	])
	.exec()
	.await?;

Create

To create a new composite type, use its create type module function.

let order = client
	.order()
	.create(
		..,
		vec![
			order::shipping_adress::set(
				address::create(
					"1084 Candycane Lane".to_string(),
					"Silverlake".to_string(),
					"84323".to_string(),
					vec![]
				)
			),
			order::billing_address::set(None),
			order::photos::set(vec![
				photo::create(100, 200, "photo.jpg".to_string());
				3
			])
		]
	)

Update

To update an existing composite type, there are a few type module functions available.

Single Fields

// overwrite entire type
order::shipping_address::set(address::create(
	..
))
 
// update certain fields
order::shipping_address::update(vec![
	address::zip::set("41232".to_string())
])
 
// attempt to update certain fields,
// creating a new type if one doesn't exist
order::billing_address::upsert(
	address::create(..),
	// list of updates to attempt to apply
	vec![address::zip::set("41232".to_string())]
)
 
// removes the field entirely
order::billing_address::unset()

List Fields

// overwrite entire list
product::photos::set(vec![
	photo::create(..),
	photo::create(..),
])
 
// push values to the end of the list
product::photos::push(vec![
	photo::create(..),
	photo::create(..),
])
 
// update multiple values in the list
product::photos::update_many(
	// filter
	vec![photo::url::equals("1.jpg".to_string())],
	// updates
	vec![photo::url::set("2.jpg".to_string())]
)
 
// update multiple values from the list
product::photos::delete_many(
	// filter
	vec![photo::url::equals("1.jpg".to_string())],
)

Ordering

It is possible to sort results based on the order of fields in composite types.

use prisma_client_rust::Direction;
 
let orders = client
	.order()
	.find_many(vec![])
	.order_by(order::shipping_address::order(
		address::city::order(SortOrder::Asc)
	))
	.exec()
	.await?;