Fork me on GitHub
#datomic
<
2020-11-08
>
ivangalbans01:11:41

Hi everyone, I’m trying to use attribute predicates in a project and i’m following https://docs.datomic.com/on-prem/schema.html#attribute-predicates I have a running transactor with datomic-pro-0.9.6045 :

bin/transactor config/samples/dev-transactor-template.properties
and I have a simple file as in the doc:
(ns datomic.samples.attrpreds
 (:require [datomic.api :as d]))

(defn user-name?
 [s]
 (<= 3 (count s) 15))

(def user-schema
 [{:db/ident :user/name,
  :db/valueType :db.type/string,
  :db/cardinality :db.cardinality/one,
  :db.attr/preds 'datomic.samples.attrpreds/user-name?}])

(def uri "datomic:")

(d/create-database uri)

(defonce conn (d/connect uri))

@(d/transact conn user-schema)
This file is outside the Datomic directory. I have a running repl via cider-jack-in-clj. I have evaluated the buffer and the schema is installed as expected, but when I run
@(d/transact conn [{:user/name "X"}])
I get the following error: > Could not locate datomic/samples/attrpreds__init.class, datomic/samples/attrpreds.clj or datomic/samples/attrpreds.cljc on classpath. I have read this in the doc: > Attribute predicates must be on the classpath of a process that is performing a transaction. But I don’t know how to do it. I have a proof of concept project with datomic-pro-0.9.6045 (dev), cider, deps.edn… Should I set the DATOMIC_EXT_CLASSPATH variable to datomic/samples/attrpreds.jar (or .clj if possible) before run the transactor ? How do you configure your projects in this case ? Thanks in advance

souenzzo11:11:55

@ivangalbans for learning, use datomic: For "production", you will generate an artifact or something like and do that classpath thing

ivangalbans17:11:02

is there a workaround ? I avoid using mem because I don’t wanna lose the datomic console. Persistent data is not important to me at this moment, although I would like to have it too

ivangalbans17:11:29

i understand what you say and generate an artifact is overkill for my purpose.

joshkh16:11:13

this one is driving me a little crazy. given the following tree: a -> b -> c -> d -> e how might i write a rule to find the most ancestral entity of e that has :item/active? true? in this example, the result would be b

[; schema

 {:db/ident       :item/id
  :db/valueType   :db.type/long
  :db/cardinality :db.cardinality/one
  :db/unique      :db.unique/identity}

 {:db/ident       :item/children
  :db/valueType   :db.type/ref
  :db/cardinality :db.cardinality/many}

 {:db/ident       :item/active?
  :db/valueType   :db.type/boolean
  :db/cardinality :db.cardinality/one}

 ; entities

 {:item/id       "a"
  :item/children ["b"]}

 {:db/id         "b"
  :item/id       "b"
  :item/children ["c"]
  :item/active?  true}

 {:db/id         "c"
  :item/id       "c"
  :item/children ["d"]}

 {:db/id         "d"
  :item/id       "d"
  :item/children ["e"]
  :item/active?  true}

 {:db/id   "e"
  :item/id "e"}] 
here is my starting point, which at least finds all ancestors of e (where as i want the just farthest ancestor from e that is active, which is b)
(let [rules '[[(anc ?par ?child)
               [?par :item/children ?child]]
              [(anc ?anc ?child)
               [?par :item/children ?child]
               (anc ?anc ?par)]]]
  
  (d/q '{:find  [(pull ?anc [*])]
         :in    [$ % ?item-id]
         :where [[?n :item/id ?item-id]
                 (anc ?anc ?n)]}
       (db) rules "e"))

benoit23:11:27

From a logical point of view, you're looking for an ancestor that is active and that itself doesn't have an active ancestor. So I would write a rule to check if an entity has an active ancestor and negate it.

joshkh15:11:42

that sounds like a good way to approach it. thanks.