Fork me on GitHub
#datomic
<
2020-10-18
>
zhuxun205:10:57

In datomic, is there a way to enforce that a relation be one-to-many as opposed to many-to-many? For example, setting :folder/files to have :db.cardinality/many does not prohibit the co-existence of [x :folder/file k] and [y :folder/file k].

joshkh09:10:15

if i'm reading that correctly, then file k can only exist in one :folder/files relationship, correct? you could put a :db.unique/value constraints on :folder/files

(d/transact (client/get-conn)
            {:tx-data [#:db{:ident       :some/id
                            :valueType   :db.type/string
                            :cardinality :db.cardinality/one
                            :unique      :db.unique/identity}

                       #:db{:ident       :folder/files
                            :valueType   :db.type/ref
                            :cardinality :db.cardinality/many
                            :unique      :db.unique/value}]})
here is a folder with two files:
(d/transact (client/get-conn)
            {:tx-data [{:db/id "file1"
                        :some/id "file1"}

                       {:db/id "file2"
                        :some/id "file2"}
                       
                       ; file1 and file2 are part of folder1
                       {:db/id "folder1"
                        :some/id "folder1"
                        :folder/files ["file1" "file2"]}]})
=> Success
then adding file1, which is already claimed by folder1, throws an exception when adding it to a new folder2:
(d/transact (client/get-conn)
            {:tx-data [{:db/id        "folder2"
                        :some/id      "folder2"
                        :folder/files [{:some/id "file1"}]}]})
Execution error (ExceptionInfo) at datomic.client.api.async/ares (async.clj:58).
Unique conflict: :folder/files, value: 30570821298684032 already held by: 44692948645838978 asserted for: 69889357107953795

👍 1