Repository navigation
GOQL.nl
🌐 English · Deutsch · Español · Français · 简体中文
Elke lijstweergave in Gramps Connect — Personen, Gezinnen, Gebeurtenissen enzovoort — heeft een zoekvak. Standaard doet typen daarin een snelle overeenkomst op gewone tekst met een handvol veelgebruikte velden van die weergave (voor Personen: Gramps-ID en naam; voor Plaats: ID, titel en plaatsnaam; enzovoort) — genoeg voor de meeste alledaagse zoekopdrachten, en de standaard omdat het eenvoudiger is dan een zoektaal.
Naast het vak staat een vinkje: "Gramps Object Query Language gebruiken." Zet het aan, en hetzelfde vak accepteert in plaats daarvan een volledige GOQL-voorwaarde (gramps-object-query-language) — een kleine taal, speciaal gebouwd om Gramps-records te doorzoeken, die dingen kan waar het zoeken op gewone tekst helemaal niet bij komt: over relaties heen reiken (een join, in databasetermen — "elk gezin waarvan moeder en vader dezelfde achternaam hebben"), en ze zelfs achterwaarts volgen ("elke notitie waar niets meer naar verwijst"). Deze pagina is voor iedereen die zo'n voorwaarde wil schrijven — geen programmeerervaring nodig.
GOQL drijft ook de aanroepen filter()/db.get_number_of() van
Gramplets aan en het argument where= van people()/
families()/enz. — dezelfde syntaxis die u met het vinkje aan in het
zoekvak zou typen, werkt ook vanuit de Python-code van een add-on.
(db.get_number_of()/het oudere kale count() zijn functies van de
Gramplet-API om overeenkomende records te tellen, niet de eigen
any/len van GOQL die hieronder worden behandeld — iets anders,
dezelfde naam.)
Wilt u het helemaal niet met de hand schrijven? De knop "Filters" naast de titel van elke lijst biedt tientallen veelgebruikte regels als gewone vinkjes — combineerbaar met AND/OR, nestbaar en om te keren — en bouwt daaronder precies dezelfde GOQL, alleen-lezen getoond zodat u kunt zien wat er is geschreven. Zie daarvoor de lijst met functies op de pagina Overzicht. "+ Nieuwe aangepaste regel…" is de enige plek in dat dialoogvenster die nog een ruwe GOQL-voorwaarde met de hand accepteert, met dezelfde syntaxis als deze hele pagina — zodra die is opgeslagen en een naam heeft, wordt ze vanaf dat moment als gewoon vinkje hergebruikt, en nooit opnieuw getypt.
Een query wordt altijd geschreven in de context van een weergave — Persoon, Gezin, Gebeurtenis enzovoort — en is slechts één voorwaarde:
surname == 'Smith'Dit leest als: zoek in de weergave Persoon de records waarvan de achternaam gelijk is aan 'Smith'. De weergave waarin u zoekt, bepaalt op welk soort record de voorwaarde van toepassing is.
Een paar symbolen komen steeds terug:
| Symbool | Betekent |
|---|---|
==, !=
|
is gelijk aan / is niet gelijk aan |
<, <=, >, >=
|
is kleiner dan, ten hoogste, groter dan, ten minste (eerder/later, kleiner/groter) |
and, or, not
|
voorwaarden combineren, of er een omkeren |
in [ ... ] |
komt overeen met een van de waarden in een lijst |
'text' in field |
komt overeen als field ergens 'text' bevat |
like(field, 'pattern') |
komt overeen met een tekstpatroon, waarin % staat voor "wat dan ook" |
regex(field, 'pattern') |
komt overeen met een reguliere expressie, voor wie die al kent |
Tekstwaarden staan tussen enkele aanhalingstekens ('Smith'); getallen
niet (1968).
and vereist dat beide kanten waar zijn; or heeft er maar één nodig.
Beide lezen natuurlijk: gender == Person.MALE and surname == 'Smith'
vindt elke man met de naam Smith, terwijl
given_name == 'John' or surname == 'Doyle' iedereen met de voornaam
John vindt of wie dan ook met de achternaam Doyle. De twee mengen
werkt net als gewone rekenkunde, waar vermenigvuldigen vóór optellen
gaat — and wordt vóór or gecontroleerd — maar haakjes maken de
bedoeling hoe dan ook duidelijk:
(gender == Person.MALE and surname == 'Smith') or given_name == 'Mary'
vindt elke mannelijke Smith, plus iedereen die Mary heet, van welk
geslacht dan ook.
not keert een voorwaarde om en komt overeen wanneer wat erin staat
niet waar is: not (surname == 'Smith') is iedereen wiens achternaam
niet Smith is. Vergelijkingen kunnen ook worden geketend, zoals echt
Python toestaat —
Date('Jan 1, 1900') < birth.date.sortval < Date('Jan 1, 1950') vindt
iedereen die strikt tussen die twee datums is geboren, op één regel in
plaats van twee die met and zijn verbonden.
Naast een gewone == dekken een paar lossere manieren om tekst te laten
overeenkomen de meeste alledaagse zoekopdrachten.
given_name in ['John', 'Jane'] komt overeen met elke naam in de lijst
— voeg er zoveel toe als u wilt. 'an' in given_name komt overal in de
naam overeen (Jane, Alexander, Susan, ...) zonder jokertekens.
like(field, 'J%') komt overeen met een patroon waarin % staat voor
"wat dan ook", dus like(given_name, 'J%') komt overeen met John, Jane,
James enzovoort. Voor wie al vertrouwd is met reguliere expressies is
regex(field, 'pattern') nog krachtiger — regex(surname, '^[SD]')
vindt in één keer elke Smith en Doyle, iets wat like(...) niet kan
uitdrukken zonder voor elke beginletter een aparte voorwaarde te
schrijven.
Een veld hoeft niet direct op het record te staan waarin u zoekt.
birth en death reiken van een persoon naar diens geboorte- of
overlijdensgebeurtenis, dus birth.date.sortval is de datum van die
gebeurtenis, en birth.place.title volgt die nog een stap verder, naar
de plaats van die gebeurtenis. Hetzelfde idee werkt bij andere
recordtypen: father en mother reiken van een gezin naar het eigen
Persoon-record van elke ouder (father.surname == 'Smith'), source
reikt van een citaat naar wat het citeert, en enclosed_by reikt van een
plaats naar de plaats die haar omvat (bijvoorbeeld de provincie van een
stad — en het is met zichzelf te ketenen, dus
enclosed_by.enclosed_by.title reikt twee niveaus omhoog).
Beide kanten van een vergelijking kunnen zo'n pad zijn, niet alleen een
vaste waarde, en dat maakt een query als "gezinnen waarin moeder en vader
dezelfde achternaam hebben" mogelijk: father.surname == mother.surname.
Ketenen en vergelijken zijn vrij te combineren —
father.birth.date.sortval < Date('Jan 1, 1850') reikt twee stappen
vanaf een gezin (naar de vader, en dan naar zijn
geboortegebeurtenis) om oudere generaties te vinden zonder van tevoren te
weten wie dat zijn.
Er is geen limiet aan het aantal van zulke sprongen dat één pad kan
maken, en elke sprong kan op een heel ander soort record landen. Vanuit
de weergave Gezin reikt
father.birth.place.title == 'Chicago, Cook, Illinois, USA' van het
gezin naar het eigen Persoon-record van de vader, van daar naar zijn
geboortegebeurtenis, en van daar naar de Plaats van die gebeurtenis —
drie sprongen door drie verschillende soorten records, eindigend bij de
naam van de plaats, allemaal op één regel. Hetzelfde ketenen werkt
vanuit elke weergave, in elke combinatie die de relaties hierboven
toestaan.
Een persoon heeft precies één geboortegebeurtenis, maar een willekeurig
aantal kinderen, notities, citaten of gekoppelde media — die vragen om
een ander soort controle.
any(c.given_name == 'Steve' for c in children) komt overeen met een
gezin als een kind aan de voorwaarde voldoet; de voorwaarde weglaten
(any(n for n in notes)) vraagt alleen of er überhaupt iets is
gekoppeld, en zo vindt not any(n for n in notes) personen zonder
vastgelegde notities. len(...) vraagt "hoeveel" in plaats van "ten
minste één" — len([c for c in children]) > 2 vindt gezinnen met meer
dan twee kinderen, en
len([c for c in children if c.gender == Person.MALE]) > 1 beperkt dat
tot het tellen van alleen de zonen.
Een verzameling is wel zo ver als één query in die richting kan reiken.
Het hierboven beschreven ketenen (father.birth.place.title) werkt
alleen via relaties die met precies één record verbonden zijn —
any/len kunnen u vertellen of iets binnen een verzameling aan een
voorwaarde voldoet, maar de query kan daarna niet verder ketenen voorbij
die overeenkomst om een van diens eigen gerelateerde records te
bereiken. De vader van een gezin heeft bijvoorbeeld zijn eigen
oudergezin — maar omdat een persoon als kind van meer dan één gezin kan
zijn vastgelegd, is die koppeling ook een verzameling, één stap verder
dan een query momenteel kan volgen. Dus "elk gezin waarvan vader en
grootvader in dezelfde provincie zijn geboren" kan GOQL nog niet
uitdrukken.
Elke verzameling hierboven reikt naar buiten — de eigen kinderen van
een gezin, de eigen notities van een persoon. backlinks is de enige
verzameling die de andere kant op reikt: verwijst er iets anders in de
stamboom naar dit record? Die is beschikbaar vanuit elk van de tien
recordtypen, zelfs vanuit typen zonder eigen uitgaande verzamelingen
(een Label heeft geen eigen kinderen of notities, maar veel records
kunnen een label krijgen, dus de eigen backlinks-voorwaarde van Tag
vindt labels die nergens worden gebruikt):
not any(bl for bl in backlinks) # niets verwijst naar dit record
any(bl._class == 'Person' for bl in backlinks) # ten minste één Persoon verwijst ernaar
any(bl for bl in backlinks) and len([bl for bl in backlinks]) > 1 # meer dan één ding verwijst ernaarDat maakt een query als "elke bron die niemand meer citeert" of "elke
plaats zonder vastgelegde gebeurtenissen" mogelijk —
not any(bl for bl in backlinks), uitgevoerd in de weergave Bron of
Plaats.
_class is het enige veld dat een backlinks-voorwaarde kan testen —
het eigen recordtype van de verwijzer ('Person', 'Family', ...).
Omdat de verwijzer van een backlink tegelijk elk van de tien recordtypen
kan zijn, kan _class niet dieper worden gevolgd zoals een normale
relatie — er is geen _class.primary_name — maar het accepteert wel
in/not in met een lijst:
any(bl._class in ['Person', 'Family'] for bl in backlinks)
any(bl._class != 'Media' for bl in backlinks)len([bl for bl in backlinks]) werkt precies zoals len(...) hierboven.
Date('...') begrijpt gewone datumtekst, dus
birth.date.sortval >= Date('Jan 1, 1968') vindt iedereen die op of na
die dag is geboren. Iets om te weten: sortval is altijd één enkel
tijdstip, zonder kwalificatie als "omstreeks", "voor" of "geschat" — een
geboortedatum ingevoerd als "voor 1968" heeft dezelfde sortval als
gewoon "Jan 1, 1968", dus een vergelijking met >= zou die persoon als
op of na de grens geboren tellen, ook al betekent "voor" precies het
tegenovergestelde. Als dat onderscheid ertoe doet, vergelijk dan in
plaats daarvan birth.date.modifier met een benoemde constante, zoals
Date.MOD_ABOUT.
Sommige velden, zoals het geslacht van een persoon of de
betrouwbaarheid van een citaat, worden vergeleken met een benoemde
constante in plaats van een ruw getal — gender == Person.MALE of
confidence >= Citation.CONF_HIGH — rechtstreeks uit Gramps zelf
gehaald, zodat ze nooit uit de pas lopen met wat Gramps werkelijk
opslaat.
GOQL is een kleine, vaste set bouwstenen, geen volledige programmeertaal — alles buiten de patronen hierboven wordt met een foutmelding geweigerd in plaats van geraden.
Deze pagina behandelt de alledaagse patronen; de eigen knop "i" van het
zoekvak, naast het zoekveld van elke weergave, toont de precieze velden
en relaties die voor die weergave beschikbaar zijn. Voor de volledige
syntaxisreferentie — elke operator, relatie, verzameling en elk randgeval,
plus de redenering erachter — zie
where_expr.md
in de repository gramps-object-query-language,
het project waarop GOQL is gebouwd.
Gramps Connect is part of the family of Gramps-based software.
Using the app
- Overview
- Installing
- Deploying
- Messaging
- GOQL (advanced search)
- Gramplets & Add-on Store
- Data Model & Editing
- FAQ
Building & contributing