Data Expressions

Data Expressions

Data expressions are dot-notation paths for reading and writing genealogy data in Pedigree Forge. They provide a uniform way to navigate the record structure — the same path syntax works everywhere:

Basics

A data expression starts with a root type, followed by one or more field segments separated by dots:

person.birth.date

This reads as: starting from a person record, navigate to their birth fact, then return its date.

Fields come in three kinds:

KindWhat it doesExample
TerminalReturns a string valuesurname, date, name
NavigationLinks to another record typefather (person), place (place)
CollectionAn indexed list of recordschildren, facts

Terminal fields are the leaves — they produce a value you can display or compare. Navigation fields move you to a different record, where you can continue with that record’s fields. Collection fields give you access to a list of records, which you can index, filter, or count.

Using in scripts

Read a value with pf.get:

pf.get("I1", "person.birth.date")          – "1 Jan 1900"
pf.get("I1", "person.surname") – "Darwin"

Write a value with pf.set:

pf.set("I1", "person.birth.date", "1 Jan 1900")
pf.set("I1", "person.surname", "Darwin")

Run a query with pf.query:

pf.query("SELECT name FROM persons WHERE surname = ’Darwin’")

This returns a table of rows matching the query.

Person fields
Terminal fields
FieldWritableDescription
idNoRecord ID
nameNoFull formatted name
surnameYesSurname
given_namesYesGiven names
sexYesSex (M/F/U)
tradeYesOccupation
life_datesNoFormatted life dates
nicknameYesNickname
name_prefixYesName prefix
name_suffixYesName suffix
titleYesFormal title
first_given_nameNoFirst given name only
genderNoGender description
pronounNoPronoun (he/she/they)
possessive_pronounNoPossessive pronoun (his/her/their)
religionYesReligion
nationalityYesNationality
son_or_daughterNo"son" or "daughter"
boy_or_girlNo"boy" or "girl"
brother_or_sisterNo"brother" or "sister"
husband_or_wifeNo"husband" or "wife"
father_or_motherNo"father" or "mother"
bachelor_or_spinsterNo"bachelor" or "spinster"
livingYesWhether flagged as living
user_referenceYesUser reference number
fullnameNoFull name with dates
Navigation fields
FieldTarget type
fatherperson
motherperson
spouseperson
birthfact
deathfact
baptismfact
burialfact
cremationfact
family_as_childfamily
Collection fields
FieldElement type
childrenperson
families_as_spousefamily
factsfact
Fact fields
Terminal fields
FieldWritableSorts asDescription
dateYesChronologicalDate of the event. Sorts by internal serial number; non-Gregorian calendars are normalised to Gregorian.
kindNoTextFact type code (e.g. "BIRT", "CENS") — use in WHERE filters and bracket expressions
labelNoTextHuman-readable event name (e.g. "Birth", "Census") — use in SELECT for display
addressYesTextAddress
noteYesTextNote text
causeYesTextCause (e.g. cause of death)
ageYesDurationAge at time of event. Sorts by total duration; vague ages are assigned approximate values for sorting (stillborn = 0, infant ~ 1 year, child ~ 8 years, minor ~ 16 years, full age ~ 21 years) and sort before numeric ages.
timeYesTextTime of event
typeYesTextSubtype
agencyYesTextAgency
fact_tradeYesTextOccupation at time of event
statusYesTextStatus
roleYesTextRole
default_valueYesTextDefault value
withYesTextWith whom
whomYesTextWhom
likelihoodYesTextLikelihood
uncertainYesTextUncertainty flag
other_addressYesTextOther address
Marriage couple fields

These fields are available on marriage facts, providing details about each partner:

FieldWritableSorts as
husband_ageYesDuration
wife_ageYesDuration
husband_addressYesText
wife_addressYesText
husband_statusYesText
wife_statusYesText
husband_tradeYesText
wife_tradeYesText
Navigation fields
FieldTarget type
placeplace
other_placeplace
husband_placeplace
wife_placeplace
Collection fields
FieldElement type
citationscitation
Family fields
Terminal fields
FieldWritableDescription
idNoFamily ID
namesNoCombined couple names
statusYesCouple status
never_marriedYesNever married flag
divorcedYesDivorced flag
separatedYesSeparated flag
stated_child_countYesStated number of children
user_referenceYesUser reference
main_notesYesMain notes
Navigation fields
FieldTarget type
husbandperson
wifeperson
marriagefact
divorcefact
Collection fields
FieldElement type
childrenperson
factsfact
Source fields
Terminal fields
FieldWritableDescription
idNoSource ID
titleYesTitle
short_titleYesShort title
authorYesAuthor
publisherYesPublisher
call_numberYesCall number
call_number_noteYesCall number note
source_typeYesSource type
groupYesGroup
fact_typeYesAssociated fact type
urlYesURL
Navigation fields
FieldTarget type
archivearchive
Archive fields
Terminal fields
FieldWritableDescription
idNoArchive ID
nameYesName
phoneYesPhone
emailYesEmail
wwwYesWebsite
faxYesFax
address_0YesAddress line 1
address_1YesAddress line 2
address_2YesAddress line 3
address_3YesAddress line 4
townYesTown
countyYesCounty
postcodeYesPostcode
countryYesCountry
noteYesNotes
Place fields

All place fields are read-only.

FieldDescription
namePlace name
townTown
countyCounty
countryCountry
prepositionPreposition (in, at, etc.)
Citation fields

All citation terminal fields are read-only.

FieldDescription
descriptionCitation description
pagePage reference
noteNote
is_localWhether citation is local
Navigation fields
FieldTarget type
sourcesource
Date sub-fields

Date fields support sub-fields for accessing individual components. Append them after any date field:

Sub-fieldSorts asReturns
.yearIntegerYear number (normalised to Gregorian for non-Gregorian calendars)
.monthIntegerMonth number (1-12)
.dayIntegerDay number (1-31)
.weekdayTextDay of week name
.fullTextFull format (e.g. "1 January 1900")
.compactTextCompact format (e.g. "1 Jan 1900")
.minimalTextMinimal format (e.g. "1900")
.decoratedTextDecorated format with qualifiers

For example, person.birth.date.year returns "1809" for Charles Darwin.

Chaining

Navigation fields link to another record type, so you can keep adding fields to drill deeper:

person.father.birth.date          – father’s birth date
person.mother.surname – mother’s maiden name
person.spouse.death.place.name – spouse’s death place

Each navigation step changes the current record type. After person.father you are on a person record, so all person fields are available again. After .birth you are on a fact, so fact fields (like date and place) apply.

Collections

Collection fields return a list of records. Access individual elements with square brackets:

person.children[0]                – first child
person.children[-1] – last child
person.families_as_spouse[0].marriage.date – first marriage date

Use .count to get the number of elements:

person.children.count             – number of children

Note — Children are aggregated across all marriages.

Filters

Narrow a collection to matching elements using [property=value] syntax:

person.facts[kind=census]                     – all census facts
person.facts[kind=census & year=1881] – 1881 census specifically
person.children[sex=M] – male children
person.children[sex=M].count – count of male children
Comparison operators
OperatorMeaning
=Equals
!=Not equals
<Less than
>Greater than
<=Less than or equal
>=Greater than or equal
*=Contains
~=Not equals (alternative)
^=Starts with
$=Ends with
\=Sounds like
Compound filters

Combine conditions within a filter using logical operators:

OperatorMeaning
&AND
\OR
!NOT

Use parentheses for grouping:

person.facts[kind=census & (year=1881 | year=1891)]
Filter fields

The properties available inside filters depend on the collection’s element type:

Fact filters: kind, year, place, date, note

Person filters: sex, year, name, surname

Family filters: year

Parameters

Expressions can include $parameter placeholders that are replaced at runtime:

These are used in gizmo bound widgets (where parameter values come from the binding context) and in parameterised queries (where the user is prompted for values).

Examples
Display a person’s parents and birth
pf.get("I1", "person.father.name")         – "Robert Darwin"
pf.get("I1", "person.mother.name") – "Susannah Wedgwood"
pf.get("I1", "person.birth.date") – "12 Feb 1809"
pf.get("I1", "person.birth.place.name") – "The Mount, Shrewsbury"
Walk a family structure
pf.get("I1", "person.families_as_spouse[0].children.count")  – "10"
pf.get("I1", "person.families_as_spouse[0].children[0].name")
Filter census facts
pf.get("I1", "person.facts[kind=census & year=1881].date")
pf.get("I1", "person.facts[kind=census].count") – "5"
Source and archive lookup
pf.get("S1", "source.title")
pf.get("S1", "source.archive.name")