Skip to content

Instantly share code, notes, and snippets.

@nwjsmith
Last active December 20, 2015 20:33
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 nwjsmith/3247c96fcc157bb0606b to your computer and use it in GitHub Desktop.
Save nwjsmith/3247c96fcc157bb0606b to your computer and use it in GitHub Desktop.
(ns categories.core
(:require [datomic.api :as d]))
(let [uri (str "datomic:mem://" (gensym))
conn (and (d/create-database uri) (d/connect uri))]
@(d/transact conn [{:db/id #db/id[:db.part/db]
:db/ident :category/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "A category's name"
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :categorization/category
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "The parent category"
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :categorization/subcategory
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "The child category"
:db.install/_attribute :db.part/db}])
@(d/transact conn [{:db/id #db/id[:db.part/user -1]
:category/name "Books"}
{:db/id #db/id[:db.part/user -2]
:category/name "Fiction"}
{:db/id #db/id[:db.part/user -3]
:category/name "Children's"}
{:db/id #db/id[:db.part/user -4]
:category/name "Fantasy"}
{:db/id #db/id[:db.part/user]
:categorization/category #db/id[:db.part/user -1]
:categorization/subcategory #db/id[:db.part/user -2]}
{:db/id #db/id[:db.part/user]
:categorization/category #db/id[:db.part/user -2]
:categorization/subcategory #db/id[:db.part/user -3]}
{:db/id #db/id[:db.part/user]
:categorization/category #db/id[:db.part/user -3]
:categorization/subcategory #db/id[:db.part/user -4]}])
(d/q '[:find ?great-grandparent ?grandparent ?parent
:in $ ?child-name
:where [?child :category/name ?child-name]
[?parenting :categorization/subcategory ?child]
[?parenting :categorization/category ?parent]
[?grandparenting :categorization/subcategory ?parent]
[?grandparenting :categorization/category ?grandparent]
[?great-grandparenting :categorization/subcategory ?grandparent]
[?great-grandparenting :categorization/category ?great-grandparent]]
(d/db conn)
"Fantasy"))
@mgaare
Copy link

mgaare commented Dec 20, 2015

Something like this might do what you're looking for:

(def child-category-rule
  '[
    [(child-category ?parent ?child)
     [?parent :categoration/subcategory ?child]]
    [(child-category ?parent ?child)
     [?parent :categoration/subcategory ?direct-child]
     (child-category ?direct-child ?child)]
    ])

;; example usage

(d/q '[:find ?ancestor
       :in $ % ?child-name
       :where
       [?child :category/name ?child-name]
       (child-category ?ancestor ?child)]
     (d/db conn)
     child-category-rule
     "Fantasy")

@nwjsmith
Copy link
Author

@mgaare Thanks! That was really helpful, I ended up with this:

(def ancestor-rules
    '[[(parent ?parent ?child) [?czn :categorization/category ?parent]
                               [?czn :categorization/subcategory ?child]]
      [(ancestor ?parent ?child) (parent ?parent ?child)]
      [(ancestor ?grandparent ?child) (ancestor ?grandparent ?parent)
                                      (ancestor ?parent ?child)]])

  (d/q '[:find ?ancestor-name
         :in $ % ?child-name
         :where [?child :category/name ?child-name]
                (ancestor ?ancestor ?child)
                [?ancestor :category/name ?ancestor-name]]
       (d/db conn)
       ancestor-rules
       "Fantasy")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment