Cerial
Field Types

Number

Number field type in Cerial — auto-detect numeric type that accepts both integers and decimals, with comparison to Int and Float.

The Number field type represents a numeric value that can be either an integer or a decimal. SurrealDB's number type auto-detects the internal representation based on the value provided — 42 stays as an integer, 42.5 becomes a float.

Schema Syntax

model Product {
  id Record @id
  price Number
  rating Number?
  score Number @default(0)
}

Types

DirectionType
Outputnumber
Inputnumber
SurrealDBnumber

All three numeric types — Int, Float, and Number — map to TypeScript number. The difference is at the SurrealDB storage level.

Int vs Float vs Number

TypeSurrealDBDecimalsUse case
IntintNo (truncates)Whole numbers — counts, ages, quantities
FloatfloatYes (always IEEE 754)Explicit decimal precision — measurements, coordinates
NumbernumberYes (auto-detect)Flexible input — accept both integers and decimals

Number is not an alias for Float. They are distinct SurrealDB types:

  • Floatfloat (always IEEE 754 double-precision)
  • Numbernumber (auto-detect — stores 42 as int, 42.5 as float)

Both map to TypeScript number, but SurrealDB treats them differently at the storage and type-checking level.

When to Use Each

  • Number — Flexible input where both 42 and 42.5 should be accepted. Good for user-provided values and fields with mixed numeric data.
  • Int — Whole numbers only. Counts, IDs, quantities. SurrealDB truncates decimal portions.
  • Float — Explicit decimal precision. Scientific data, coordinates, measurements where you want consistent IEEE 754 storage.

For financial calculations, use Decimal instead — it provides arbitrary precision without floating-point rounding errors.

Create & Update

const product = await client.db.Product.create({
  data: {
    name: 'Widget',
    price: 19.99,        // stored as float internally
    rating: 4,           // stored as int internally
  },
});

console.log(product.price);  // 19.99
console.log(product.rating); // 4

// Update
await client.db.Product.updateUnique({
  where: { id: product.id },
  data: { price: 24.99 },
});

Filtering

Number fields support all numeric comparison operators:

// Comparison
const expensive = await client.db.Product.findMany({
  where: { price: { gte: 50 } },
});

// Range
const midRange = await client.db.Product.findMany({
  where: { price: { between: [10, 100] } },
});

// Set
const specific = await client.db.Product.findMany({
  where: { price: { in: [9.99, 19.99, 29.99] } },
});

Available Operators

OperatorDescription
eqEqual to
neqNot equal to
gtGreater than
gteGreater than or equal
ltLess than
lteLess than or equal
betweenWithin a range (inclusive)
inIn a set of values
notInNot in a set of values

Conditional Operators

OperatorAvailable whenDescription
not? or @nullableNegated comparison
isNone? (optional)true = field is absent
isNull@nullabletrue = field is null
isDefinedAlwaystrue = field exists

OrderBy

Number fields support orderBy:

const sorted = await client.db.Product.findMany({
  orderBy: { price: 'desc' },
});

In Objects and Tuples

object Stats {
  min Number
  max Number
  average Number
}

tuple Coordinate {
  x Number,
  y Number,
  z Number?
}

model Measurement {
  id Record @id
  stats Stats
  position Coordinate
}
const m = await client.db.Measurement.create({
  data: {
    stats: { min: 10.5, max: 99.9, average: 55.2 },
    position: [1.5, 2.5, 3.5],
  },
});

m.stats.average;     // 55.2
m.position[0];       // 1.5

Arrays

model Scores {
  id Record @id
  values Number[]
  uniqueValues Number[] @set
}

Number arrays support @set for auto-deduplicated, sorted arrays. They also support @distinct and @sort decorators.

Supported Decorators

DecoratorEffect
@default(value)Default value on create
@defaultAlways(value)Reset to value on every write
@nullableAllow explicit null
@readonlyWrite-once field
@indexDatabase index
@uniqueUnique constraint

On this page