datascript

Jonas Rodrigues 2025-02-13T13:10:47.578259Z

Hi everyone! 👋 I have a simple Datascript schema:

{:page/name {:db/unique :db.unique/identity}}
Now, I’d like to extend this schema to include a :ui/label attribute, but with support for multiple labels based on language (e.g., English, Spanish, etc.). My main goal is to store something like:
{:page/name "home"
 :ui/label [{:lang "en" :value "Home"}
            {:lang "es" :value "Inicio"}]}
How would you model this in a Datascript schema? I’d appreciate any best practices or examples. Thanks in advance! 😊

magra 2025-03-12T15:46:57.154269Z

Maybe:

(let [schema {:page/name  {:db/unique :db.unique/identity}
                :label/page {:db/valueType :db.type/ref}}
        conn   (ds/create-conn schema)]
    (ds/transact! conn [{:db/id 1
                         :page/name "home"}
                        {:label/page  1
                         :label/value "Home"
                         :label/lang  "en"}
                        {:label/page  1
                         :label/value "Inicio"
                         :label/lang  "en"}])
    (ds/pull @conn
             [:page/name
              {:label/_page [:label/lang :label/value]}]
             1))
  =>
  {:page/name "home",
   :label/_page
   [#:label{:lang "en", :value "Home"}
    #:label{:lang "en", :value "Inicio"}]}

Jonas Rodrigues 2025-02-13T13:20:54.797499Z

My first attempt:

(def schema
  {:page/name {:db/unique :db.unique/identity}
   :ui/label {:db/valueType :db.type/ref
              :db/cardinality :db.cardinality/many}})

(def conn (d/create-conn schema))

(d/transact! conn
    [{:page/name "home"
      :ui/label [{:lang :en :value "Home"}
                 {:lang :pt :value "Início"}]}])
Would you suggest a different modeling approach or improvements to the schema?

seepel 2025-02-13T18:44:00.814009Z

I don’t know how you expect this to interact with the rest of your data, but if you intend these labels to be children and they won’t be referenced from elsewhere, you might want to add the :db/isComponent to your :ui/label attribute. This makes it so that if you retract the parent entity the referenced entities are also retracted.

:ui/label {:db/valueType :db.type/ref
           :db/cardinality :db.cardinality/many
           :db/isComponent true}
I find that things go smoother when an entity is either a component of another entity, or has an identity attribute to identify it.