mrn
Morn!
Morn!
Hvilken mentale modell og verktøy bruker dere for å designe/visualisere datamodeller og relasjoner mellom entiteter for Datomic? Vet dere om noen eksempler?
Aha! 💡 Så der er «tidsrom» et navnerom som har to datoer og to tider, kanskje?
;; Tidsrom (datoer inklusive til/fra, tider inklusiv fra, eksklusiv til)
{:db/ident :tidsrom/fra-ld
:dte/valueType :java.time/local-date
:db/cardinality :db.cardinality/one}
{:db/ident :tidsrom/til-ld
:dte/valueType :java.time/local-date
:db/cardinality :db.cardinality/one}
{:db/ident :tidsrom/fra-lt
:dte/valueType :java.time/local-time
:db/cardinality :db.cardinality/one}
{:db/ident :tidsrom/til-lt
:dte/valueType :java.time/local-time
:db/cardinality :db.cardinality/one}
{:db/ident :tidsrom/uke ;; {:år 2025 :ukenummer 9}
:dte/valueType :edn/data
:db/cardinality :db.cardinality/one}
Når det gjelder betraktningen om besøksadresse og postadresse: Det er ikke sikkert den distinksjonen er viktig for deg! Men den er viktig for oss 🙂 Dårlig eksempel, jeg ville allikevel skilt på :bedrift/adresse og :person/adresse uten at jeg helt klarer å føre et flammende argument for hvorfor 😅
De eneste forskjellene mellom en fakturaadresse og leveringsadresse, som jeg kan komme på her og nå, er at en leverings adresse for B2B ofte har ytterligere tre verdier: firmanavn, c/o navn (personen som kan ta imot pakken på vegne av bedriften), og kanskje en leveringsinstruks, typ «ta heisen til resepsjonen i 6.etasje og bruk dørkoden 1234.» B2C kunder har sjeldent mer enn én adresse bortsett fra hvis de skal få noe levert til hytta eller til en venn (for eksempel en gave). For B2C kaffeabonnement (som sendes hver måned) kan andressen endres per leveranse, så leveringsadressen til kunden blir «printet» på selve ordren når den blir skapt. B2C kunder kan også gi kaffeabonnement som gave og da er også fakturaadressen og leveringsadressen forskjellige (én privatperson betaler og en annen mottar leveransen).
Fakturaadresse og leveringsadresse kan gjerne peke på samme type entitet. Jeg mener ikke at du trenger :fakturaadresse/linje1 - det er ikke en egen type. Men attributtet som peker på den gir deg noe informasjon om hva slags adresse det er: :kunde/fakturaadresse vs :kunde/leveringsadresse
Men her er det noen interessante nyanser. Det kan jo være at en kunde bare har en liste med adresser, og at det er ordre som har leveringsadresse og fakturaadresse.
Eller kanskje det holder å modellere adresser på ordre. Når en kunde kommer med en ny bestilling kan du se på tidligere ordre for å foreslå adresser.
😅
Jepp! Og jeg vil måtte lage en funksjon for å generere en CSV-fil med alle leveringsadresser som Aya kan bruke for å bestille alle fraktetikettene i batch via Bring og/eller PostNord, typ 50~100 om gangen. Evt. bruke API-ene deres. Og printe etikettene. Da tenker jeg det er mest naturlig og hente ut leveringsadressene fra ordrene og ikke fra kunden. Men forstår jeg rett kan man bruke _ i Datomic for å gå «baklengs» i datahierarkiet og på den måten finne alle de relevante adressene på kundene fra ordrene, så det har kanskje liten praktisk betydning hvor i treet adressene ligger.
Yes!
Pass på å modellere ting der de naturlig hører hjemme. Så lenge det er referanser mellom alle viktige punkter så kan du navigere frem og tilbake til hjertets lyst.
Det er faktisk helt rått.
Indeed 😄
Jeg merker det er nokså rotete i hodet mitt hvordan jeg skal strukturere abonnement (som egentlig bare er «ordrefabrikker»), ordre, ordrelinjer, produkter, og B2B-prisavtaler på produkter. Alle de tingene henger på en måte sammen. Vurderer å ha en «tilbud»-entitet for B2B som «blir til» en ordre når kunden bekrefter i check-out. Og knytte en slags «prisavtale» til produkter og tilbud i forkant, kun for B2B-kunder. Det er også noe utfordrende å modeller lagerlokasjoner og produktbeholdning. Jeg har egentlig veldig god domenekunnskap til slike retail-ting etter nesten 10 år i Elkjøp Nordic + egne bedrifter, men nå ser jeg hvor mye dumt vi gjorde der. Utfordringen jeg har er å ikke havne i samme spor med gamle vaner, og samtidig ta med kunnskapen som faktisk har nytteverdi.
Finnes det ikke ganske mye prior art på produktkatalog, ordre og rabatter osv? SKU-greier?
Dette kan nok du mer om enn meg 😊
Evt. lager jeg en «handlepose» som kan fungere både som B2B-«tilbud» og «ikke-bekreftet ordre» for B2C-kunder.
Jo, det finnes mye eksisterende materiale å hente inspirasjon fra. Utfordringen er at nesten alle bruker ERP systemer som f.eks. SAP hvor disse tingene er komplisert til ville høyder, eller SQL databaser som ikke «mapper» fra til Datomic. Jeg er derfor litt redd for å lene meg for mye på kunnskap rundt eksisteredene implementasjoner.
Skjønner
Jeg ville helt klart laget noen eksempler på alle casene du trenger. Bare maps og vektorer
Fordelen jeg har er at jeg har sett alle tingene som suger i den verdenen der 😂
😂
En av de mest kjente utfordringene er at produktdata ofte finnes i PIM, som er koblet på nettbutikkene og kassasystemer i butikk. Men alt som har med lager og beholdning å gjøre ligger begravet dypt nedi den sorte ERP-boksen. Det leder ofte til misinformasjon og overslag fordi eCom-plattformen forsøker å konsumere data fra et dusin andre systemer, som vedlikeholdes av forskjellige avdelinger i selskapet. Det er et lappeteppe uten sidestykke.
Men nå har jeg ikke tenkt å lage en fullverdig enterprice ERP løsning eller SAP-killer 😂
Hehe, nei, det gjelder å begrense seg til akkurat hva man trenger, uten å male seg inn i et hjørne
Jepp! Nettopp.
For en stund siden lagde jeg https://github.com/2food/datomic-graph-viz. Datomic har skjema på attributt-nivå, som er veldig bra, men kan gjøre det vanskelig å "se" strukturen og relasjonene mellom entiteter bare fra skjema. Men når du har en database med data så har de en struktur, som man kan vise som en graf. Kanskje ikke så nyttig som designverktøy, for du må ha en database med data i først. Men en artig måte å utforske en datomic database du kanskje ikke kjenner så godt 😊
Wow! Kult! > Structure is intentionally not constrained in Datomic, which gives it great structural flexibility. This is one of its really strong features in my opinion. But, the lack of a structural schema can make it difficult to understand and build a mental model of the data, especially if you're new to the db or to Datomic in general. Det er nøyaktig hva jeg sliter med nå 😅
Haha, ja nettopp 😄
Til design-arbeid for datomic-data vil jeg egentlig anbefale å bare tegne sirkler og streker på et whiteboard (eller lignende). Det er en fleksibel graf-database, så alt du kan tegne som en graf kan du veldig lett skrive datomic schema for etterpå.
Mener du en sirkel per "entitet/navnerom" med en strek mellom hver sirkel hvor et navnerom refererer til en verdi i et annet?
En sirkel for hver entitet, en strek/pil for hver referanse til andre entiteter. 👍
Skjønner!
Også typ en liste med verdier under hver sirkel på en måte?
Det blir nesten en flat tabell med verdier som har et navn.
Ja, typ noe sånn. En entitet er en "sekk" med attributt/verdi-par
Og piler fra enkelte verdier i én liste til andre lister.
Så modellerer man bare relasjoner i én retning, sant? Fordi man kan gå baklengs og sidelengs via Datomic uansett.
Så det er mer "streker" enn "piler."
Slik som den éne brukeren viser på Stack Overflow.
Nettopp 👍 Når man spør på dataene etterpå er det egentlig likegyldig hvilken retning pilen er. Så man kan bare peke i den retningen man selv syns "gir mest mening". Jeg tror eneste tilfellet det betyr noe er hvis du skal bruke :db/isComponent (som gjør at "component" entiteter retractes hvis "parent"-en retractes, litt som "on delete cascade" fra SQL).
Så i eksempelbildet der kunne kanskje :article/comment ref-en hatt :db/isComponent true , hvis du vil at en retraction av en artikkel skal retracte kommentarene også.
Er ikke dette ganske akkurat hva man ville gjort med en vanlig relasjonsdatabase?
Jo, i utgangspunktet helt likt 😄 I hvert fall ville jeg gjort det
Men det noen ting som gjør at datomic sin datamodell er litt nærmere en "ren" graf-modell, i hvert fall i mitt hode. F.eks. at alt med primær/fremmed-nøkler er håndtert med konseptet om en "ref", og man trenger ikke lage join-tabeller for du kan bare si at en "ref" er :db.cardinality/many. I relasjonsdatabaser vil man også gjerne tenke litt mer igjennom hvilke kolonner man vil ha i hvilke tabeller osv, siden det er litt "stress" å utvide en eksisterende tabell senere. Det kan man utsette mer med datomic siden det er så lett å "gro" med å legge til attributter senere. Så man kan fokusere mest på bare entiteter og relasjoner i begynnelsen.
Er ikke dette ganske akkurat hva man ville gjort med en vanlig relasjonsdatabase?Med en relasjonsdatabase har jeg pleid å bruke "streker med føtter og dører" for å visualisere én-til-én relasjoner, én-til-mange relasjoner, hvilke retninger en kan gå, etc. Det blir fort mer komplisert. Med Datomic trenger man heller ikke info om primary keys og foreign keys.
Med Datomic trenger man bare enkle piler som peker én vei (eller bare rette linjer), hvis jeg forstår rett.
https://youtu.be/H854fF6K2_o @ 44:39: > “Other things besides stories can have comments, so I’m going to put that in a different namespace.” Ref. dialogen om adresser tidligere i tråden. Stu prater spesifikt om samme problemstilling der. Veldig nyttig!
https://clojurians.slack.com/archives/C03RZMDSH/p1766438407612629?thread_ts=1606928463.043600&cid=C03RZMDSH av modellen til https://github.com/Datomic/codeq er ganske fin! Jeg legger den inn i tråden her til fremtidige Slack-arkeologer.
Ah! Det er tydeligvis andre som har lignende spørsmål. Fant en del god info https://stackoverflow.com/questions/10357778/data-modeling-in-datomic.
Tror jeg må starte med å beskrive entiteter med vanlig prosa uten å tenke på noe teknisk og implementasjonsdetaljer. Hjernen min dro umiddelbart i retningen denormalisert og relasjonell modellering á la SQL, men så oppdaget fort ut at det ikke funker i Datomic på en grunnleggende konseptuelt nivå. Dagens påminnelse: Det er vanskelig å «glemme» det en har lært tidligere og tenke på en annerledes måte.
Jeg pleier å bruke hodet. Og whiteboard noen ganger. Jeg tror det jeg prøver å si er at enten så forstår jeg datamodellen, og da får den greit plass i hodet, eller så gjør jeg ikke det, og da hjelper ingen diagrammer/verktøy.
Jeg føler at jeg har relativt grei kontroll på hvilke «ting» appen består av i hodet mitt. Men jeg er ikke sikker på om modellen er «korrekt» og tror kanskje det hadde blitt enklere for meg å tenke på ting hvis jeg ser det med øynene samtidig. Skal prøve å få det ut av hodet og ut i verdenen.
Jeg er ikke like god på å gjøre ting i hodet og ser ofte ikke feilene mine før jeg får med meg hendene og øynene.
Det er derfor jeg gjerne liker å leke med det i kode også. Det er først da jeg klarer å finne ut av ting. Men da er det gunstig at det går superfort å test/endre og at man ikke må gjøre tusen ting (endre tabeller, typer, interfaces, whatnot) for hver endring du gjør.
Jeg utformer datamodeller ved å tenke på hvilke attributter jeg trenger, gjerne eksemplifisert med noen maps. Jeg bruker gjerne litt tid på å finne gode navn. Ofte løsner det når du finner de rette navnene.
Alt som trenger å adresseres på utsiden av systemet (URL-er osv) får en syntetisk id, typisk :roast/id denne kan være en uuid som er lett å lage, men aller helst noe kortere og mer menneskevennlig/lesbart
Ah! Så det er mer en «bottom-up» tilnærming hvor du finner ut av alle verdiene som trengs først? Når du har funnet de fleste verdiene og gitt dem gode navn så grupperer du dem inn i logiske «domener/entiteter» ved hjelp av navnerom? Det var et enkelt og nyttig tips, @christian767.
Attributtene kommer gjerne med navnerom, så strukturen kommer på plass as you go
Fint å ha noen konkrete eksempler å jobbe med også
En ting jeg lurer på da er hvis flere entiteter trenger samme verdier. For eksempel trenger både bedrifter og personer én eller flere adresser, f.eks. en fakturaadresse og en leveringsadresse. Kanskje flere. Gir det da mening og ha et eget/separat «domene/navnerom» for adresser, som både bedrifter og personer kan «bruke?» Hvor én adresse består av flere verdier som f.eks. linje 1, linje 2, postnummer, poststed, land, og kanskje en merkelapp som «Hjem» eller «Jobb». Eller ville du «duplisert» de verdiene direkte i bedrift og person navnerommene?
Godt spørsmål! Om attributtet kun indikerer eierskap, altså det er en referanse til en entitet, så gir jeg dem unike navn. Det er nok beskrivende for adresse-eksempelet: :bedrift/postadresse
Hvis du skal gjenbruke samme attributt er det nyttig å stille spørsmålet "er dette samme ting?". En besøksadresse er ikke det samme som en postadresse.
(Selv om de kan være like)
Vi har en del ting i vår modell som representerer et tidsrom. De tingene deler attributter:
{:avtale/id "..."
:tidsrom/fra-lt "12:00"
...}