5

I am trying to set a unique constraint for an edge collection so that only one edge of a certain type can be created between two given nodes. The issue is that it seems I can't use _from and _to attributes as path attributes when creating the index. What I have tried so far:

db._collection('edges').ensureUniqueConstraint('_from', '_to', 'type');

I get the following error:

[ArangoError 10: bad parameter]

I don't want to check whether a certain edge type between two nodes exists before creating it.

Any hints?

jarandaf
  • 4,297
  • 6
  • 38
  • 67

2 Answers2

5

It is currently not possible to create secondary indexes on internal attributes such as _key, _id, _rev, _from, or _to. We want to allow this for a future version of ArangoDB, but it will be a massive code change.

The only way to achieve the desired result is to create an extra attribute in the edge that you save and put the combination of "_from", "_to", and "type" into it. I think these values should be known at edge creation already.

So instead of saving an edge like this

db.edges.save(_from, _to, { type: type, other: ... });

it should be like this:

// create a unique index on attribute "unique"
db._collection("edges").ensureUniqueConstraint("unique");

// create a variable "unique" which contains the values of _from and _to and type
var unique = _from + "-" + _to + "-" + String(type);

// now save the edge, using the "unique" attribute
db.edges.save(_from, _to, { type: type, unique: unique, other: ... });

This is a workaround, but it should solve that particular problem.

stj
  • 9,037
  • 19
  • 33
  • Thanks for pointing this out (wanted to be sure this feature was not available yet). It should do the trick, thanks! – jarandaf Aug 01 '14 at 09:57
5

Since ArangoDB 3.0 you can ensure uniqueness of relations in edge collections with unique hash index on _from and _to fields.

db.edgeCollectionName.ensureIndex({ type: "hash", fields: [ "_from", "_to" ], unique: true });

When a A->B relation exists, another A->B won't be created. B->A can still be created, though.

mrkvon
  • 3,507
  • 2
  • 21
  • 26
  • And you could always sort A and B before creating the hash to make it work for both A->B and B->A. – William Sep 12 '18 at 13:56