# What =kind= of entity is it?

**URL:** <https://forum.datomic.com/t/what-kind-of-entity-is-it/819>\
**Category:** General\
**Created:** [February 1, 2019, 11:48pm UTC](https://forum.datomic.com/t/what-kind-of-entity-is-it/819 "2019-02-01T23:48:14Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![blake](https://avatars.discourse-cdn.com/v4/letter/b/a9a28c/32.png) [@blake](https://forum.datomic.com/u/blake)\
**Post date:** [February 1, 2019, 11:48pm UTC](https://forum.datomic.com/t/what-kind-of-entity-is-it/819/1 "2019-02-01T23:48:14Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![solussd](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.datomic.com/solussd/32/59_2.png) [@solussd](https://forum.datomic.com/u/solussd)\
**Post date:** [February 3, 2019, 5:20pm UTC](https://forum.datomic.com/t/what-kind-of-entity-is-it/819/2 "2019-02-03T17:20:57Z")

</div>

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:

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

```

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

---

<div class="post-metadata">

**Author:** ![blake](https://avatars.discourse-cdn.com/v4/letter/b/a9a28c/32.png) [@blake](https://forum.datomic.com/u/blake)\
**Post date:** [February 5, 2019, 8:33pm UTC](https://forum.datomic.com/t/what-kind-of-entity-is-it/819/3 "2019-02-05T20:33:25Z")

</div>

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. 😝

---

<div class="post-metadata">

**Author:** ![solussd](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.datomic.com/solussd/32/59_2.png) [@solussd](https://forum.datomic.com/u/solussd)\
**Post date:** [February 5, 2019, 9:10pm UTC](https://forum.datomic.com/t/what-kind-of-entity-is-it/819/4 "2019-02-05T21:10:51Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![tomc](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.datomic.com/tomc/32/221_2.png) [@tomc](https://forum.datomic.com/u/tomc)\
**Post date:** [February 7, 2019, 8:27pm UTC](https://forum.datomic.com/t/what-kind-of-entity-is-it/819/5 "2019-02-07T20:27:25Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![blake](https://avatars.discourse-cdn.com/v4/letter/b/a9a28c/32.png) [@blake](https://forum.datomic.com/u/blake)\
**Post date:** [February 7, 2019, 9:50pm UTC](https://forum.datomic.com/t/what-kind-of-entity-is-it/819/6 "2019-02-07T21:50:41Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![dmarjenburgh](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.datomic.com/dmarjenburgh/32/251_2.png) [@dmarjenburgh](https://forum.datomic.com/u/dmarjenburgh)\
**Post date:** [February 8, 2019, 8:40am UTC](https://forum.datomic.com/t/what-kind-of-entity-is-it/819/7 "2019-02-08T08:40:16Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![blake](https://avatars.discourse-cdn.com/v4/letter/b/a9a28c/32.png) [@blake](https://forum.datomic.com/u/blake)\
**Post date:** [February 12, 2019, 8:10pm UTC](https://forum.datomic.com/t/what-kind-of-entity-is-it/819/8 "2019-02-12T20:10:03Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![blake](https://avatars.discourse-cdn.com/v4/letter/b/a9a28c/32.png) [@blake](https://forum.datomic.com/u/blake)\
**Post date:** [February 12, 2019, 8:31pm UTC](https://forum.datomic.com/t/what-kind-of-entity-is-it/819/9 "2019-02-12T20:31:32Z")

</div>

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”.

---

<div class="post-metadata">

**Author:** ![dustingetz](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.datomic.com/dustingetz/32/56_2.png) [@dustingetz](https://forum.datomic.com/u/dustingetz)\
**Post date:** [February 14, 2019, 1:58am UTC](https://forum.datomic.com/t/what-kind-of-entity-is-it/819/10 "2019-02-14T01:58:00Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![bhurlow](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.datomic.com/bhurlow/32/181_2.png) [@bhurlow](https://forum.datomic.com/u/bhurlow)\
**Post date:** [February 25, 2020, 7:35pm UTC](https://forum.datomic.com/t/what-kind-of-entity-is-it/819/11 "2020-02-25T19:35:46Z")

</div>

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
