Hash Indexes

Introduction to Hash Indexes

It is possible to define a hash index on one or more attributes (or paths) of adocument. This hash index is then used in queries to locate documents in O(1)operations. If the hash index is unique, then no two documents are allowed to have thesame set of attribute values.

Creating a new document or updating a document will fail if the uniqueness is violated. If the index is declared sparse, a document will be excluded from the index and no uniqueness checks will be performed if any index attribute value is not set or has a value of null.

Accessing Hash Indexes from the Shell

Unique Hash Indexes

Ensures that a unique constraint exists:collection.ensureIndex({ type: "hash", fields: [ "field1", …, "fieldn" ], unique: true })

Creates a unique hash index on all documents using field1, … _fieldn_as attribute paths. At least one attribute path has to be given.The index will be non-sparse by default.

All documents in the collection must differ in terms of the indexed attributes. Creating a new document or updating an existing document willwill fail if the attribute uniqueness is violated.

To create a sparse unique index, set the sparse attribute to true:

collection.ensureIndex({ type: "hash", fields: [ "field1", …, "fieldn" ], unique: true, sparse: true })

In case that the index was successfully created, the index identifier is returned.

Non-existing attributes will default to null.In a sparse index all documents will be excluded from the index for which allspecified index attributes are null. Such documents will not be taken into accountfor uniqueness checks.

In a non-sparse index, all documents regardless of null - attributes will beindexed and will be taken into account for uniqueness checks.

In case that the index was successfully created, an object with the indexdetails, including the index-identifier, is returned.

  1. arangosh> db.test.ensureIndex({ type: "hash", fields: [ "a", "b.c" ], unique: true });
  2. arangosh> db.test.save({ a : 1, b : { c : 1 } });
  3. arangosh> db.test.save({ a : 1, b : { c : 1 } });
  4. arangosh> db.test.save({ a : 1, b : { c : null } });
  5. arangosh> db.test.save({ a : 1 });

Show execution results

  1. {
  2. "deduplicate" : true,
  3. "fields" : [
  4. "a",
  5. "b.c"
  6. ],
  7. "id" : "test/74693",
  8. "isNewlyCreated" : true,
  9. "name" : "idx_1642473900986073090",
  10. "selectivityEstimate" : 1,
  11. "sparse" : false,
  12. "type" : "hash",
  13. "unique" : true,
  14. "code" : 201
  15. }
  16. {
  17. "_id" : "test/74697",
  18. "_key" : "74697",
  19. "_rev" : "_ZJNS8LK---"
  20. }
  21. [ArangoError 1210: unique constraint violated - in index idx_1642473900986073090 of type hash over 'a, b.c'; conflicting key: 74697]
  22. {
  23. "_id" : "test/74701",
  24. "_key" : "74701",
  25. "_rev" : "_ZJNS8LO---"
  26. }
  27. [ArangoError 1210: unique constraint violated - in index idx_1642473900986073090 of type hash over 'a, b.c'; conflicting key: 74701]

Hide execution results

Non-unique Hash Indexes

Ensures that a non-unique hash index exists:collection.ensureIndex({ type: "hash", fields: [ "field1", …, "fieldn" ] })

Creates a non-unique hash index on all documents using field1, … _fieldn_as attribute paths. At least one attribute path has to be given.The index will be non-sparse by default.

To create a sparse unique index, set the sparse attribute to true:

collection.ensureIndex({ type: "hash", fields: [ "field1", …, "fieldn" ], sparse: true })

In case that the index was successfully created, an object with the indexdetails, including the index-identifier, is returned.

  1. arangosh> db.test.ensureIndex({ type: "hash", fields: [ "a" ] });
  2. arangosh> db.test.save({ a : 1 });
  3. arangosh> db.test.save({ a : 1 });
  4. arangosh> db.test.save({ a : null });

Show execution results

  1. {
  2. "deduplicate" : true,
  3. "fields" : [
  4. "a"
  5. ],
  6. "id" : "test/74389",
  7. "isNewlyCreated" : true,
  8. "name" : "idx_1642473900930498562",
  9. "selectivityEstimate" : 1,
  10. "sparse" : false,
  11. "type" : "hash",
  12. "unique" : false,
  13. "code" : 201
  14. }
  15. {
  16. "_id" : "test/74393",
  17. "_key" : "74393",
  18. "_rev" : "_ZJNS8Hy--B"
  19. }
  20. {
  21. "_id" : "test/74395",
  22. "_key" : "74395",
  23. "_rev" : "_ZJNS8H2---"
  24. }
  25. {
  26. "_id" : "test/74397",
  27. "_key" : "74397",
  28. "_rev" : "_ZJNS8H2--A"
  29. }

Hide execution results

Hash Array Indexes

Ensures that a hash array index exists (non-unique):collection.ensureIndex({ type: "hash", fields: [ "field1[]", …, "fieldn[]" ] })

Creates a non-unique hash array index for the individual elements of the arrayattributes field1[], … fieldn[] found in the documents. At leastone attribute path has to be given. The index always treats the indexed arrays assparse.

It is possible to combine array indexing with standard indexing:collection.ensureIndex({ type: "hash", fields: [ "field1[*]", "field2" ] })

In case that the index was successfully created, an object with the indexdetails, including the index-identifier, is returned.

  1. arangosh> db.test.ensureIndex({ type: "hash", fields: [ "a[*]" ] });
  2. arangosh> db.test.save({ a : [ 1, 2 ] });
  3. arangosh> db.test.save({ a : [ 1, 3 ] });
  4. arangosh> db.test.save({ a : null });

Show execution results

  1. {
  2. "deduplicate" : true,
  3. "fields" : [
  4. "a[*]"
  5. ],
  6. "id" : "test/74406",
  7. "isNewlyCreated" : true,
  8. "name" : "idx_1642473900935741440",
  9. "selectivityEstimate" : 1,
  10. "sparse" : false,
  11. "type" : "hash",
  12. "unique" : false,
  13. "code" : 201
  14. }
  15. {
  16. "_id" : "test/74410",
  17. "_key" : "74410",
  18. "_rev" : "_ZJNS8IG--_"
  19. }
  20. {
  21. "_id" : "test/74412",
  22. "_key" : "74412",
  23. "_rev" : "_ZJNS8IG--B"
  24. }
  25. {
  26. "_id" : "test/74414",
  27. "_key" : "74414",
  28. "_rev" : "_ZJNS8IK---"
  29. }

Hide execution results

Creating Hash Index in Background

This section only applies to the rocksdb storage engine

Creating new indexes is by default done under an exclusive collection lock. This meansthat the collection (or the respective shards) are not available as long as the indexis created. This “foreground” index creation can be undesirable, if you have to perform iton a live system without a dedicated maintenance window.

Indexes can also be created in “background”, not using an exclusive lock during the creation. The collection remains available, other CRUD operations can run on the collection while the index is created.This can be achieved by using the inBackground option.

To create an hash index in the background in arangosh just specify inBackground: true:

  1. db.collection.ensureIndex({ type: "hash", fields: [ "value" ], inBackground: true });

For more information see “Creating Indexes in Background” in the Index basics page.

Ensure uniqueness of relations in edge collections

It is possible to create secondary indexes using the edge attributes _fromand _to, starting with ArangoDB 3.0. A combined index over both fields togetherwith the unique option enabled can be used to prevent duplicate relations frombeing created.

For example, a document collection verts might contain vertices with the documenthandles verts/A, verts/B and verts/C. Relations between these documents canbe stored in an edge collection edges for instance. Now, you may want to make surethat the vertex verts/A is never linked to verts/B by an edge more than once.This can be achieved by adding a unique, non-sparse hash index for the fields _fromand _to:

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

Creating an edge { from: "verts/A", _to: "verts/B" } in _edges will be accepted,but only once. Another attempt to store an edge with the relation AB willbe rejected by the server with a unique constraint violated error. This includesupdates to the _from and _to fields.

Note that adding a relation BA is still possible, so is AAand BB, because they are all different relations in a directed graph.Each one can only occur once however.