Skip to content

Instantly share code, notes, and snippets.

@tiensonqin
Created April 10, 2024 13:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tiensonqin/929b6affb8fd6a07723c53a8d0c9678f to your computer and use it in GitHub Desktop.
Save tiensonqin/929b6affb8fd6a07723c53a8d0c9678f to your computer and use it in GitHub Desktop.
Property key-value pairs as entities
(def conn (d/create-conn {:db/ident {:db/unique :db.unique/identity}
:block/uuid {:db/unique :db.unique/identity}
:block/content {}
:block/properties {:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many
:db/isComponent true}
:property-value/property {:db/valueType :db.type/ref}}))
;; Add internal properties
(d/transact! conn [{:db/ident :logseq.property/created-by
:db/cardinality :db.cardinality/one
:db/index true}])
(d/transact! conn [{:db/ident :logseq.property/order
:db/cardinality :db.cardinality/one
:db/index true}])
;; Add user properties
(d/transact! conn [{:db/ident :user.property/foo
:db/cardinality :db.cardinality/one
:db/index true}])
(d/transact! conn [{:db/ident :user.property/bar
:db/cardinality :db.cardinality/one
:db/index true}])
;; set :user.property/foo for a block
(d/transact! conn [{:db/id 10
:block/uuid (random-uuid)
:block/content "block 1"
:block/properties {:property-value/property :user.property/foo
:user.property/foo "block-1-foo-value"
:logseq.property/created-by "user-1-ref"
:logseq.property/order 1}}])
(d/transact! conn [{:db/id 10
:block/properties {:property-value/property :user.property/bar
:user.property/bar "block-1-bar-value"
:logseq.property/created-by "user-1-ref"
:logseq.property/order 2}}])
;; add another block
(d/transact! conn [{:db/id 100
:block/uuid (random-uuid)
:block/content "block 2"
:block/properties {:property-value/property :user.property/foo
:user.property/foo "block-2-foo-value"
:logseq.property/created-by "user-1-ref"
:logseq.property/order 1}}])
(d/transact! conn [{:db/id 100
:block/properties {:property-value/property :user.property/bar
:user.property/bar "block-2-bar-value"
:logseq.property/created-by "user-1-ref"
:logseq.property/order 2}}])
(def block-1 (d/entity @conn 10))
(def block-2 (d/entity @conn 100))
;; get property keys from block 1
(map (comp :db/ident :property-value/property) (:block/properties block-1))
;; => (:user.property/foo :user.property/bar)
;; query block-1's value for :user.property/foo
(->> (:block/properties block-1)
(filter #(some? (:user.property/foo %)))
(map :user.property/foo))
;; => ("block-1-foo-value")
;; Get all the blocks' values for :user.property/foo
(map :v (d/datoms @conn :avet :user.property/foo))
;; ("block-1-foo-value" "block-2-foo-value")
;; Delete :user.property/foo from block-1
(let [values (->> (:block/properties block-1)
(keep (fn [e] (when (some? (:user.property/foo e)) (:db/id e)))))]
(d/transact! conn (map (fn [id] [:db/retractEntity id]) values)))
(assert (= 1 (count (:block/properties (d/entity @conn 10)))))
;; Delete :user.property/bar globally
(let [property-value-entities (map :e (d/datoms @conn :avet :user.property/bar))]
;; Delete property value entities first
(d/transact! conn (map (fn [id] [:db/retractEntity id]) property-value-entities))
;; Delete property itself
(d/transact! conn [[:db/retractEntity :user.property/bar]])
;; TODO: also need to handle [:block/schema :properties] for classes
)
(assert (= 0 (count (:block/properties (d/entity @conn 10)))))
;; Delete a block should remove all of its :block/properties entities because of defined `:db/isComponent`
(:tx-data (d/transact! conn [[:db/retractEntity 100]]))
(assert (empty? (d/datoms @conn :avet :user.property/foo)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment