# 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](https://4068685904-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LoN3fu4ydp8osDZFQch%2F-Lp0manTT3RYiCSFHC32%2F-Lp0pHLMpNc1NCFQN_Vu%2Fbad-schema.png?alt=media\&token=d167d809-24cd-429d-8112-38c4f34c909c)

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](https://4068685904-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LoN3fu4ydp8osDZFQch%2F-Lp0manTT3RYiCSFHC32%2F-Lp0qJZ4VuPDB5izwoWp%2Fgood-schema.png?alt=media\&token=d8d20222-f3bb-469b-a895-ed0fdbf20aa9)

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