Roam EDN Structure

Written
  • The structure is a datascript database in Clojure's native EDN format.
  • The initial object in the database defines the schema, and this is not particular interesting for most uses.
  • After that comes the :datoms, which contain all the graph data.
    • Each datom is an entry in entity-attribute-value (EAV) format.
    • That is, each is a list of the format: [entity-id "attribute-name" value tx-id], where tx-id is the ID of the database transaction in which the item was most recently modified.
  • Attributes
    • Each page and block is a single entity, and each has multiple attributes. An entity can also have multiple values for a particular attribute. Generally simply mean that the attribute appears multiple times on the entity, with a different value each time.
    • Attributes on Pages and Blocks
      • :block/uid - A unique ID for the block, different from the datascript entity id. This is the same id that you see in block references.
      • :block/children - The IDs of the direct children of this block or page.
      • :block/refs - A list of UIDs referenced by a block, by links, hashtags, attributes, etc. Here we see the block reference in string format, as well as a "refs" value that indicates the actual block id.
        •  [82509 :block/children 82528 536905570]
           [82509 :block/open true 536905536]
           [82509 :block/order 0 536905536]
           [82509 :block/page 82508 536905537]
           [82509 :block/parents 82508 536905537]
           [82509 :block/refs 80137 536905571] ;; The page with UID mniPrpzKa
           [82509 :block/string "((mniPrpzKa))" 536905570]
           [82509 :block/uid "u_EGyfOOI" 536905536]
           [82509 :create/email "daniel@danielmfeld.com" 536905536]
           [82509 :create/time 1610571818743 536905536]
           [82509 :edit/email "daniel@danielmfeld.com" 536905536]
           [82509 :edit/time 1610571818743 536905536]
          
      • :create/email - The email of the user that created this block
      • :create/time - A timestamp of when this block was created. Sometimes this is absent.
      • :edit/email - The email of the last user to edit this block
      • :edit/time - A timestamp of when this block was last edited
    • Block-only Attributes
      • :block/heading - The heading level of the block.
      • :block/parents - All the ancestor blocks of this one, up to the page it's in.
      • :block/page - The entity ID of the page that this block is in.
      • :block/open - If this block is expanded or collapsed
      • :block/order - The order that this block appears relative to its sibling blocks.
    • Page-only Attributes
      • :node/title - The title of the page
      • :log/id - This appears on daily notes, and you can use the timestamp to determine which day the note is for.
        • [82511 :block/uid "01-14-2021" 536905548]
          [82511 :create/email "daniel@danielmfeld.com" 536905548]
          [82511 :create/time 1610620052622 536905548]
          [82511 :edit/email "daniel@danielmfeld.com" 536905548]
          [82511 :edit/time 1610620066797 536905565]
          [82511 :log/id 1610620052621 536905548] ;; The timestamp
          [82511 :node/title "January 14th, 2021" 536905548]
      • :entity/attrs - A set of all attributes and values referenced in a page.
        • Each item in the set is a list of three maps.
        • The :value of the second item is the attribute's UID.
        • The :value of the third is the attribute's value, either a string or a UID. The rest all seem to be the page's UID.
        • If an attribute has multiple values (i.e. multiple hashtags) there will be one entry for each value of the attribute.
        • [6367 :entity/attrs
           @
              ;; The current page
             [{:source [:block/uid "BwqNL2PQq"], :value [:block/uid "BwqNL2PQq"]}
              ;; The UID of the attribute
             {:source [:block/uid "4NH7hu_Ow"], :value [:block/uid "hcB3qiqqa"]}
              ;; The UID of the attribute's value (when it's a link/hashtag)
             {:source [:block/uid "4NH7hu_Ow"], :value [:block/uid "x_lDM2Klh"]}]
           
             ;; The current page
            [{:source [:block/uid "BwqNL2PQq"], :value [:block/uid "BwqNL2PQq"]}
             ;; The UID of the attribute
             {:source [:block/uid "Hg3Z0L4ap"], :value [:block/uid "gNlp2UsOV"]}
             ;; The string value of the attribute
             {:source [:block/uid "Hg3Z0L4ap"], :value " The Problems With Deliberate Practice"]}}
          
          
      • :attrs/lookup - I haven't looked into this much yet, but it appears to link to blocks in the page that reference attributes, and also to the attributes themselves.
        • ;; The current page
          [8718 :attrs/lookup 8718 536880551]
          ;; A block in this page that references an attribute
          [8718 :attrs/lookup 8766 536880551]
          ;; The id of an attribute referenced inside this page
          [8718 :attrs/lookup 8946 536880551]
          [8718 :entity/attrs 
           @
             [{:source [:block/uid "wWln_ysjZ"], :value [:block/uid "wWln_ysjZ"]}
              {:source [:block/uid "RBlQZRu5V"], :value [:block/uid "uZNZalyHW"]}
              {:source [:block/uid "RBlQZRu5V"], :value " https://scch.io/tutorials/deep-dive-into-css-grid-2"}]
            } 536880551]
          

Thanks for reading! If you have any questions or comments, please send me a note on Twitter. And if you enjoyed this, I also have a newsletter where I write about tech thoughts, interesting things I've read, and project updates each Thursday.

You can check out a recent issue, or enter your email below to subscribe.