Kijkje in de keuken: Alle zoekresultaten snel op je scherm. Dit is hoe ons autocomplete component werkt.

Kijkje in de keuken: Alle zoekresultaten snel op je scherm. Dit is hoe ons autocomplete component werkt.

Eerder lieten we al zien hoe we alle adressen uit de BAG importeren en binnen milliseconden doorzoekbaar maken met Elasticsearch, zodat jij eenvoudig een waarderapport kan maken voor elk adres in Nederland. In dit tweede deel van de serie ‘kijkje in de keuken’ duiken we nog wat dieper onze backend in, om te laten zien hoe we je zoekopdracht naar Elasticsearch sturen en hoe we het resultaat weer op je scherm krijgen.

Dankzij onze infrastructuur kunnen we een autocomplete component neerzetten waarmee je eenvoudig en snel een waarderapport kunt maken voor elk adres in Nederland. Het doorzoeken van de Basisregistratie Adressen en Gebouwen (BAG) is daar een belangrijk onderdeel van. Dit is hoe we ervoor zorgen dat de resultaten weer netjes op je scherm komen.

Grammatica voor onze API met GraphQL

GraphQL is “a query language for your API”. Met GraphQL kan je een externe API beschrijven in de vorm van types, queries en mutations. Bij elkaar levert dat een setje afspraken op over hoe je API werkt, welke data er in en uit mag en aan welke eisen die data moet voldoen. Aangezien de backend code bij Walter Living is opgedeeld in microservices kan GraphQL op een eenvoudige manier in één keer specifieke data uit één of meerdere services opvragen.

Een GraphQL API wordt beschreven in een schema waarin is vastgelegd welke soorten data er in de API worden aangeboden en welke datatypen daarbij horen. Iedere query die naar een GraphQL API wordt gestuurd, moet voldoen aan dit schema. Zo kan je makkelijk vooraf bepalen uit wat voor data de API response bestaat en is het eenvoudig om aan de serverkant validatie te doen op de queries die binnenkomen.

Aan de kant van het frontend is Walter voornamelijk gebouwd in Typescript en Vue. De type checks in Typescript sluiten heel goed aan op hoe typing werkt in GraphQL. Daarover meer in het volgende artikel in deze serie.

Zoekopdrachten van GraphQL naar onze backend

Terug naar het adres autocomplete component op onze website. We maken gebruik van onze GraphQL API om je zoekopdrachten naar Elasticsearch te brengen en op te halen. Dit is ongeveer hoe het werkt:

In het schema van onze GraphQL API is een type gedefinieerd voor deze zoekopdracht:

fuzzyFindAddresses(
  city: String
  query: String!
): FuzzyAddressResult
GraphQL Type

Elke query die binnenkomt om een adres te zoeken, moet dus aan deze specificatie voldoen.

  1. Je tikt een woord in het autocomplete component op onze website, bijvoorbeeld “dorpstraat”.
  2. In de Typescript-code van dit component wordt dit woord in een GraphQL query omgetoverd, en naar onze GraphQL API gestuurd:
fuzzyFindAddresses($query: String!, $city: String) {
  query
  addresses {
    city
    country
    ..
  }
}
GraphQL Query

In de GraphQL API wordt eerst gechecked of je query voldoet aan de specificatie in het schema. Als dat niet zo is, stuurt de API je een foutmelding terug.

Is je query valide, dan wordt deze omgetoverd in een Elasticsearch zoekopdracht en naar ons Elasticsearch cluster gestuurd. Binnen een paar milliseconden stuurt Elasticsearch een lijst met zoekresultaten terug.

Deze zoekresultaten worden door de GraphQL API omgezet in een antwoord dat voldoet aan het API schema en teruggestuurd:

{
  "data": {
    "query": "dorpstraat",
    "addresses": [
      {"city": "Riel", "country": "The Netherlands", ...},
      {"city": "Echt", "country": "The Netherlands", ...},
      ...
    ]
  }
}
GraphQL Response

Tenslotte zie jij in een oogwenk een lijstje met zoekresultaten die voldoen aan je zoekopdracht:

Op deze manier kunnen we met GraphQL een uniforme API aanbieden aan onze frontend apps, zonder dat alle backend services precies moeten weten hoe die frontend apps werken. GraphQL zorgt ervoor dat zowel de frontend als de backend data ontvangt op de manier waarop ze hun data willen ontvangen.

Backend-implementatie met Elixir en Absinthe

Nee, we hebben het hier niet over de laatste designer-cocktail-hype die uit New York is overgewaaid. Elixir is een functionele programmeertaal gebouwd op de fundamenten van Erlang, het platform waarmee WhatsApp met 50 software-engineers tot 900 miljoen gebruikers is gegroeid. Absinthe is een third-party library die helemaal gericht is op het bouwen van GraphQL API’s in Elixir. Met Elixir en Absinthe hebben we een stukje software gebouwd dat de definities uit onze GraphQL API kan omtoveren in een werkende API.

Bijna alle services bij Walter Living worden gebouwd in Elixir, waarbij we meestal het Phoenix web framework gebruiken. Elixir heeft een paar eigenschappen die het een hele prettige en bruikbare taal maken om webapplicaties en API’s mee te bouwen:

  1. Omdat Elixir een functionele taal is, is er geen globale state en is het makkelijk om pure functies  te schrijven zonder side-effects. Zo kunnen wecode geautomatiseerd testen en refactoren.
  2. Elixir-code wordt gecompileerd naar Erlang byte-code die draait op de BEAM virtual machine. Hierdoor is performance fantastisch en is het makkelijk om met weinig compute power een service te deployen die met lage latency een hoog aantal requests per seconde kan verwerken
  3. De standard library is compleet en er zijn voldoende goed geteste en onderhouden third party libraries beschikbaar voor zaken die niet standaard ondersteund zijn. De kwaliteit van code en documentatie liggen vrij hoog, wat het een heel prettig ecosysteem maakt om in te werken.

Met Absinthe is het kinderlijk eenvoudig om een GraphQL schema te definiëren en daarin je types en queries te beschrijven. Vervolgens wordt er handig gebruik gemaakt van het functionele aspect van Elixir en van pattern matching. Iedere resolver die een GraphQL query uitvoert krijgt een standaard setje data, voorzien van de query input en de sessie-context van de gebruiker.Daarmee kan vervolgens in pure Elixir-code worden verder gewerkt.

Om terug te komen op ons autocomplete component: dit is hoe een GraphQL query met je zoekopdracht “dorpstraat” vanuit het frontend binnenkomt in Absinthe en daar wordt afgehandeld:

Frontend en Backend werken samen dankzij GraphQL

Zo ga je bij Walter dus van een frontend request naar ons backend en weer terug. Dankzij de schema’s van GraphQL kunnen Elasticsearch, Elixer en Absinthe naadloos samenwerken. Dan hoef jij alleen maar het begin van het adres in te typen. De rest doen wij.

In het volgende artikel in deze serie laten we je zien hoe we met Typescript en Vue ons frontend gebouwd hebben, en hoe dat aansluit op onze GraphQL API.

Meer verhalen van Walter Living

#mijnhuis - Thuis bij Johan
Aimée Schuurmans |

#mijnhuis - Thuis bij Johan

Johan woont - zoals een rasondernemer dat betaamt - boven zijn werk aan de Prins Hendrikkade te Amsterdam.

Mensen · 3 minuten leestijd
Bieden op een populair huis? Dit is hoe je kans maakt.
Aimée Schuurmans |

Bieden op een populair huis? Dit is hoe je kans maakt.

Heb jij een populair huis op het oog? Dit is wat je kan verwachten als je gaat bieden op een huis met meerdere geïnteresseerden.

Huizenjacht · 5 minuten leestijd

Klaar om Walter te proberen?

Maak alle juiste huizenjacht keuzes — Geen BS. Beloofd.
Probeer Walter gratis
Alle verhalen
Volgend verhaal
#mijnhuis - Thuis bij Johan