> For the complete documentation index, see [llms.txt](https://sweet-tooth.gitbook.io/specmonstah/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sweet-tooth.gitbook.io/specmonstah/tutorial/10-uniqueness-constraint.md).

# 10: uniqueness constraint

If you're building a forum and want people to be able to like posts, you probably don't want to allow people to like the same post twice. If your schema is something like this:

| **like**  |
| --------- |
| `post-id` |
| `user-id` |

Then you probably have a constraint such that you can't have two records with the same `post-id` and `user-id`. How do you model this in Specmonstah? So far, we've seen schemas like this:

```scheme
(ns reifyhealth.specmonstah-tutorial.10
  (:require [reifyhealth.specmonstah.core :as sm]))
  
(def bad-schema
  {:user {:prefix :u}
   :post {:prefix :p}
   :like {:prefix      :l
          :spec        ::like
          :relations   {:post-id       [:post :id]
                        :created-by-id [:user :id]}}})
```

If you use this to generate ents, you'll end up in a disappointing situation:

```scheme
(defn ex-01
  []
  (sm/view (sm/add-ents {:schema bad-schema} {:like [[3]]})))
(ex-01)
```

![likes all reference the same post and user](/files/-Lp0pHLMpNc1NCFQN_Vu)

All the likes reference the same `:post` (`:p0`) and `:user` (`:u0`). This happens because Specmonstah generates the minimal data needed to satisfy a query.

&#x20;To get Specmonstah to generate data that your database will accept, you introduce a *uniqueness constraint* in the schema:

```scheme
(def good-schema
  {:user {:prefix :u}
   :post {:prefix :p}
   :like {:prefix      :l
          :spec        ::like
          :relations   {:post-id       [:post :id]
                        :created-by-id [:user :id]}
          :constraints {:created-by-id #{:uniq}}}})
```

Notice the `:constraints` key at the bottom of the schema. This tells Specmonstah, "The `:created-by-id` relation of every `:like` should refer to a unique `:user`. If you generate multiple `:like`s, generate new `:user`s too until each like refers to a differ `:user`."

This schema will generate a graph that will satisfy your database's constraints:

```scheme
(defn ex-02
  []
  (sm/view (sm/add-ents {:schema good-schema} {:like [[3]]})))
(ex-02)
```

![a happy graph](/files/-Lp0qJZ4VuPDB5izwoWp)

You could have instead added the `:uniq` constraint to `:post-id`, and it would have generated new `:post`s instead of `:user`s. Give it a try :) Or, try adding the constraint to both `:post-id` and `:created-by-id`.
