Cerial
Filtering

Null & None

Filter by null values, absent fields, and defined status

isNull

Checks whether a @nullable field has a null value. Only available on fields decorated with @nullable.

// Schema: deletedAt Date @nullable

// Find records where deletedAt is null
const softDeleted = await client.db.User.findMany({
  where: { deletedAt: { isNull: true } },
});

// Find records where deletedAt is NOT null
const deleted = await client.db.User.findMany({
  where: { deletedAt: { isNull: false } },
});

eq: null and neq: null

You can also use eq and neq with null directly on @nullable fields:

// Equivalent to isNull: true
await client.db.User.findMany({
  where: { deletedAt: { eq: null } },
});

// Equivalent to isNull: false
await client.db.User.findMany({
  where: { deletedAt: { neq: null } },
});

isNone

Checks whether an optional (?) field is absent (NONE) on the record. Only available on fields marked with ?.

// Schema: bio String?

// Find records where bio is absent
const noBio = await client.db.User.findMany({
  where: { bio: { isNone: true } },
});

// Find records where bio exists (has any value, including null if @nullable)
const hasBio = await client.db.User.findMany({
  where: { bio: { isNone: false } },
});

isDefined

A semantic alias for isNone with inverted logic. Only available on optional (?) fields.

// Equivalent to isNone: false — field is present
await client.db.User.findMany({
  where: { bio: { isDefined: true } },
});

// Equivalent to isNone: true — field is absent
await client.db.User.findMany({
  where: { bio: { isDefined: false } },
});

Use whichever reads more naturally for your intent — isDefined: true is often clearer than isNone: false.

NONE vs null vs Value

SurrealDB distinguishes between three field states: absent (NONE), null, and having a value. This is different from most databases where absent and null are the same thing.

For fields with both ? and @nullable (e.g., bio String? @nullable), there are three distinct states:

StateField exists?Has value?isNone: trueisNull: trueisDefined: true
NONENoNo
nullYesNo (null)
'hello'YesYes

Fields with only ? have two states (value or NONE). Fields with only @nullable have two states (value or null).

// Schema: bio String? @nullable

// Create records in each state
await client.db.User.create({ data: { name: 'Alice' } });
// Stored: { name: 'Alice' } — bio is NONE (absent)

await client.db.User.create({ data: { name: 'Bob', bio: null } });
// Stored: { name: 'Bob', bio: null }

await client.db.User.create({ data: { name: 'Carol', bio: 'Hello!' } });
// Stored: { name: 'Carol', bio: 'Hello!' }

Querying the differences:

// Only Alice — bio field is absent
await client.db.User.findMany({ where: { bio: { isNone: true } } });

// Only Bob — bio is null
await client.db.User.findMany({ where: { bio: { isNull: true } } });

// Bob and Carol — bio field exists (regardless of value)
await client.db.User.findMany({ where: { bio: { isNone: false } } });

// Alice and Carol — bio is not null (NONE is also not null)
await client.db.User.findMany({ where: { bio: { isNull: false } } });
  • NONE vs null — Understanding the difference between absent fields and null values
  • Special Operators — Range queries with between and combining filters

On this page