mattyw

talkative, friendly, programmer

Unique Contraint in Mongo

| Comments

My first post on my new blog, so let’s keep it simple.

In sql databases you can specify unique constrains on certain columns, like this example from postgres:

1
2
create unique index idx_UniqRef on FooBar (
       UniqRef ASC);

The question is: Is it possible to do this in a schema-less database like mongo? Lets’ start writing some code that we want to fail. For this I’m going to use go and Gustavo’s mgo library

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
+package main
+
+import (
+  "labix.org/v2/mgo"
+  "log"
+)
+
+type FooBar struct {
+  Name   string
+  Age    int
+  UniqId int
+}
+
+func main() {
+  session, err := mgo.Dial("127.0.0.1")
+  if err != nil {
+    log.Fatal(err)
+  }
+
+  coll := session.DB("test").C("uniq_test")
+  coll.DropCollection()
+
+  a := FooBar{"Foo", 1, 1}
+  b := FooBar{"Bar", 2, 1}
+
+  err = coll.Insert(a)
+  if err != nil {
+    log.Fatal(err)
+  }
+  err = coll.Insert(b)
+  if err == nil {
+    log.Fatal("We wrote something but wanted to fail!")
+  }
+
+}

Nothing too fancy here:

  • Create a connection to our collection
    • If the collection exists drop it (useful for iterating quickly on this test)
  • Create two structures with a UniqId field duplicated
  • Insert both, if the second insert doesn’t fail log an error

If we run it as is, we see our failure

1
2
2013/06/12 13:14:51 We wrote something but wanted to fail!
exit status 1

Now we’re in a position to start looking into a solution, and it turns out we don’t have to look far. Just like postgres mongo has indexes, we can create one using ensureIndex. Here’s how it looks in the mgo library:

1
2
3
4
5
6
7
8
9
    //Let's try an index
    index := mgo.Index{
        Key: []string{"uniqid"},
        Unique: true,
    }
    err = coll.EnsureIndex(index)
    if err != nil {
        log.Fatal(err)
    }

This creates an index on our uniqid field and forces it to be unique. If we call this code before we try inserting here’s what we get

1
Failed to write! E11000 duplicate key error index: test.uniq_test.$uniqid_1  dup key: { : 1 }

There we go, it also supports compound indexes which lets you specify multiple fields which must be unique, but I’m not going to cover that here. The mongo documention is a great source for more information

Comments