Index unique on Array in MongoDB

advertisements

Say we have a collection of documents similar to this:

{
  foo: "Bar",
  foos: [1, 2, 3]
}

I would like to define a unique index such that no document identical to this one can be inserted into the database.

db.stuffs.ensureIndex({ foos: 1 }, { unique: true })

Seems to block any document containing a foos array with any intersection, eg. if the document above was already in the database, then

{
    foo: "Bar",
    foos: [ 1 ]
}

Would also be blocked.

> db.stuffs.ensureIndex({ foos: 1 }, { unique: true })
> db.stuffs.insert({ foo: "Bar", foos: [ 1, 2, 3 ]})
> db.stuffs.insert({ foo: "Bar", foos: [ 1 ]})
E11000 duplicate key error index: test.stuffs.$foos_1  dup key: { : 1.0 }

I would like to be able to make insertions of [ 1, 2 ], [ 2, 1 ], [ 1, 3 ], etc. but not two [ 1, 2 ]


The array index will not meet your requirement. But I think you can switch to the other format to store your data.

If there is no need to use the feature of array (such as $addToSet, $push op), you can simply hash/map your data to another format. e.g.: [1,2,3] to the string "1,2,3".

While I assume that you want to remain the array operations in order to make some updates. Then you can try the subdocument below:

db.stuffs.ensureIndex({ foos: 1 }, { unique: true })  // build the index for the sub doc
db.stuffs.insert({ foo: "Bar", foos: {k:[ 1, 2, 3 ]}})
db.stuffs.insert({ foo: "Bar", foos: {k:[ 1 ]}})
db.stuffs.update({ "_id" : ObjectId("54081f544ea4d4e96bffd9ad")}, {$push:{"foos.k": 2}})
db.stuffs.insert({ foo: "Bar", foos: {k:[1, 2]}})
E11000 duplicate key error index: test.stuffs.$foos_1  dup key: { : { k: [ 1.0, 2.0 ] } }