What =kind= of entity is it?

Given a particular entity-id can I know what type of entity it is?

Hi Blake,

Entities don’t have a type, per se, in Datomic, but what attributes an entity has can be thought of as its type. For example, if there is a:person/id attribute, having that attribute could mean an entity is of type person. If an entity with a :person/id also has the attribute :customer/orders you know it is a person and an active customer.

A query for all persons in the DB might look like:

(d/q [:find ?person 
     :in $ 
     :where [?person :person/id]]
   db)

which returns all entities with the attribute :person/id.

Thank you.

So, if I want to identify a “type”, there has to be something inherent and unique to that type. Which, oh, wow, means that you can assert anything in any schema about any entity.

I can’t decide if that’s incredibly useful or horrifying. :stuck_out_tongue_closed_eyes:

haha, I think “useful”, here’s why:

You can select whatever attributes you want about an entity, asserting attributes that you don’t care about in a given context don’t affect it. It’s set semantics for “type”.

If you want to ensure an entity contains a given set of attributes, you can use a transaction function, e.g., tx-data: [[create-person-entity person-data]], but you shouldn’t go out of your way to enforce that it doesn’t have supplemental attributes.

1 Like

In order to identify entity types in my datomic DB I added an :entity/type attribute that I put on all entities. Excluding the small nuisance of making sure to add this attr in my entities’ constructors, it has served me well.

That’s an interesting idea. This will take some mulling.

I believe this is similar to Datomic’s schema attribute. A schema attribute is itself an entity with :db/ident, :db/cardinality and :db/valueType attributes. Whether an entity is a schema attribute is implicitly determined by whether is has these attributes.

1 Like

I’ve been reading this and re-reading this trying to understand it.

A schema attribute is itself an entity with :db/ident , :db/cardinality and :db/valueType attributes. Whether an entity is a schema attribute is implicitly determined by whether is has these attributes.

This allows you to identify schema attributes, if I understand correctly. That’s interesting but I think irrelevant to my cause?

OK, this is making sense to me now. If I have an entity, I can check to see if it’s part of a particular “schema” by seeing if it has fields that are required by that schema. So I can tell a person from a place or a thing by looking for (e.g.) person/name versus place/name.

And if I have entities that cross schemas, presumably I know what I’m doing. Namespacing really clarifies this one, because I’m not just looking for “name”.

1 Like

I like using :db/unique :db.unique/identity for this purpose. If an entity can be identified by lookup ref like [:account/primary-email "dustin@example.com"] then we know it’s an account record. This is also pretty flexible in that you can have more than one identity

2 Likes

Another approach is to use clojure.spec to define specifications about your business domain “types”. You can use these specs to see if a given entity conforms to a spec (or multiple!).

Since Datomic only records types at the attribute / value level, your entities may satisfy different specs wherever they are used. For example, a given entity may satisfy the “Customer” specification because it has a username, address etc, but it might also satisfy an “Emailable” spec because it has other required attributes.

Something like:

(s/def ::customer (s/keys :req [:user/username :user/password]))
(s/explain ::customer (into {} (d/entity (now) 17592186047087)))

Note at the current time coercing the entity to a map (using into above) is required to interface with spec as it expects maps. Looks like there’s some conversation about this going

1 Like