Add Fields
Add computed fields to documents using $addFields stage.
Basic Usage
Add new fields to documents:
konduct.collection<Product>()
.addFields {
"totalValue" from (Product::stock * Product::price)
"inStock" from (Product::quantity gt 0)
}
.toList()
Field Sources
From Property References
From String Fields
From Literal Values
From Expressions
.addFields {
"total" from (Order::quantity * Order::price)
"profit" from ((Product::sellingPrice - Product::costPrice) * Product::stock)
"discountedPrice" from (Product::price * (1 - (Product::discount / 100)))
}
Array Operations
Sum Array Elements
Average Array
Min/Max Array
Array Size
String Concatenation
Combine strings:
.addFields {
"fullName" concat listOf(User::firstName, " ", User::lastName)
"displayName" concat listOf(User::title, ". ", User::name)
}
Conditional Fields
Add fields based on conditions:
.addFields {
"stockStatus" from when {
Product::stock eq 0 -> "out_of_stock"
Product::stock lt Product::reorderPoint -> "low_stock"
otherwise -> "in_stock"
}
}
Real-World Examples
E-Commerce: Calculate Order Total
data class OrderWithTotal(
val id: String,
val items: List<OrderItem>,
val subtotal: Double,
val tax: Double,
val total: Double
)
konduct.collection<Order>()
.addFields {
"subtotal" sumOf "items.price"
"tax" from ("\$subtotal" * 0.1)
"total" from ("\$subtotal" + "\$tax")
}
.into<OrderWithTotal>()
.toList()
Inventory: Stock Value
konduct.collection<Product>()
.addFields {
"stockValue" from (Product::quantity * Product::costPrice)
"potentialRevenue" from (Product::quantity * Product::sellingPrice)
"potentialProfit" from (
(Product::quantity * Product::sellingPrice) -
(Product::quantity * Product::costPrice)
)
"marginPercentage" from (
((Product::sellingPrice - Product::costPrice) / Product::sellingPrice) * 100
)
}
.match { "stockValue" gte 10000 }
.sort { "potentialProfit".desc() }
.toList()
User Profile: Full Name and Age
konduct.collection<User>()
.addFields {
"fullName" concat listOf(User::firstName, " ", User::lastName)
"age" from yearsDiff(User::birthDate, Date())
"isAdult" from (yearsDiff(User::birthDate, Date()) gte 18)
}
.toList()
Sales: Commission Calculation
konduct.collection<Sale>()
.addFields {
"revenue" from (Sale::quantity * Sale::price)
"commission" from (
(Sale::quantity * Sale::price) * (Sale::commissionRate / 100)
)
"netRevenue" from (
(Sale::quantity * Sale::price) -
((Sale::quantity * Sale::price) * (Sale::commissionRate / 100))
)
}
.toList()
Computed Flags
Add boolean flags:
konduct.collection<Product>()
.addFields {
"isFeatured" from (Product::rating gte 4.5)
"needsRestock" from (Product::stock lte Product::reorderPoint)
"onSale" from (Product::discount gt 0)
"isPremium" from (Product::price gte 1000)
}
.toList()
Replacing Fields
Override existing fields:
konduct.collection<Product>()
.addFields {
// Update price with discount applied
"price" from (Product::price * (1 - (Product::discount / 100)))
// Normalize status
"status" from when {
Product::stock eq 0 -> "unavailable"
Product::active eq false -> "inactive"
otherwise -> "active"
}
}
.toList()
Nested Field Creation
Create nested objects:
.addFields {
"address" from doc {
"street" from User::street
"city" from User::city
"country" from User::country
}
"metadata" from doc {
"createdAt" from Date()
"version" from 1
}
}
Combining with Other Stages
Match → AddFields → Sort
konduct.collection<Product>()
.match { Product::status eq "active" }
.addFields {
"profitMargin" from (
((Product::sellingPrice - Product::costPrice) / Product::sellingPrice) * 100
)
}
.sort { "profitMargin".desc() }
.limit(10)
.toList()
Group → AddFields
konduct.collection<Sale>()
.group {
by(Sale::productId)
accumulate {
"revenue" sum (Sale::quantity * Sale::price)
"unitsSold" sum Sale::quantity
}
}
.addFields {
"avgPricePerUnit" from ("\$revenue" / "\$unitsSold")
}
.toList()
Using Expressions
Leverage the expression system:
import io.github.denofbits.konduct.expressions.*
konduct.collection<Order>()
.addFields {
"total" from (
(OrderItem::quantity * OrderItem::price) +
(OrderItem::quantity * OrderItem::price * (OrderItem::taxRate / 100)) -
(OrderItem::quantity * OrderItem::price * (OrderItem::discountRate / 100))
)
}
.toList()
Performance Tips
-
Add fields after filtering:
-
Avoid expensive computations:
-
Reuse computed fields:
See Also
- Expressions - Arithmetic operations
- Grouping - Aggregate data
- Match & Filter - Filter results