---
title: "Indexing"
description: "Create and manage vertex property and label secondary indexes in Aerospike Graph Service to optimize queries."
---

# Indexing

> For the complete documentation index see: [llms.txt](https://aerospike.com/docs/llms.txt)
> 
> All documentation pages available in markdown.

## Overview

This page describes how to create and manage secondary indexes (sindexes). Indexes can make graph database queries faster and more efficient.

There are two ways to create sindexes:

-   [Create an index with the call API](https://aerospike.com/docs/graph/3.1.0/develop/query/indexing/#create-an-index-with-the-call-api)
-   [Create an index with configuration](https://aerospike.com/docs/graph/3.1.0/develop/query/indexing/#create-an-index-with-configuration)

You can then [manage indexes](https://aerospike.com/docs/graph/3.1.0/develop/query/indexing/#manage-indexes) with the call API.

Secondary indexes speed up traversals because they apply only to the first step. When a traversal begins with filters on both an indexed and a non-indexed property, AGS evaluates the indexed filter first. You get the most benefit by indexing high-cardinality properties that sharply reduce the candidate set. Property indexes typically provide more selectivity than label indexes, so starting the traversal at a property index is often the most efficient path.

## Create an index with the call API

AGS supports typed vertex property sindexes. Use `index_type` to create either a `string` or `numeric` index. Typed indexes reduce memory consumption in the Aerospike database.

If you do not specify `index_type`, AGS creates both string and numeric indexes. If only one type exists, AGS creates the missing type.

### Create a typed vertex property sindex

```txt
g.call("aerospike.graph.admin.index.create").

     with("element_type", "vertex").

     with("property_key", "name").

     with("index_type", "string").next()
```

```txt
g.call("aerospike.graph.admin.index.create").

     with("element_type", "vertex").

     with("property_key", "age").

     with("index_type", "numeric").next()
```

Expected output:

```txt
Vertex index creation of property key 'name' in progress.
```

-   `property_key` is the name of the property you want to index.
-   You can index any user-defined property or the `~label` field. The `~id` field is indexed automatically.

### Create a vertex label index

```txt
g.call("aerospike.graph.admin.index.create").

     with("element_type", "vertex").

     with("property_key", "~label").next()
```

### Creation without index\_type for both types

The following example creates both string and numeric indexes because `index_type` is not set.

```txt
g.call("aerospike.graph.admin.index.create").

     with("element_type", "vertex").

     with("property_key", "name").next()
```

## Create an index with configuration

You can create indexes by configuration when starting AGS in Docker.

-   Use a [properties file](https://aerospike.com/docs/graph/3.1.0/install/docker#use-a-properties-file).
-   Or set options with the `-e` flag in the Docker command. See [configuration options](https://aerospike.com/docs/graph/reference/config).

### Typed vertex property index creation

AGS supports typed configuration keys. Provide property keys as a comma-separated list.

Terminal window

```bash
aerospike.graph.index.vertex.properties.string=name,city

aerospike.graph.index.vertex.properties.numeric=age,salary
```

### Vertex label index creation

Enable a label index for all vertex labels:

Terminal window

```bash
aerospike.graph.index.vertex.label.enabled=true
```

If you create a label index on one AGS instance, other instances in the cluster detect and use it.

### Configuration without index\_type for both types

The legacy key creates both numeric and string indexes for the listed properties.

Terminal window

```bash
aerospike.graph.index.vertex.properties=property_key1,property_key2
```

Vertex property indexes are taken as a union from all AGS instances. If one instance has an index on `property_key1` and another has an index on `property_key2`, AGS creates and uses both.

When a vertex property index is first created on a dataset, creation time is proportional to the amount of data in the Aerospike database. Larger datasets take longer. Creating indexes before loading data is faster, but you can create them afterward as well.

::: note
Vertex property indexes have a value limit of 2k bytes. Property values greater than 2k bytes cannot be indexed.
:::

## Manage indexes

Use the call API to drop indexes and to view index status, existing keys, and cardinality.

::: note
Aerospike Graph does not support edge secondary indexes. Avoid traversals that start from edges unless you already have the edge ID. Starting from vertices using property or label indexes is preferable.
:::

### Drop a secondary index

Specify `index_type` to drop a specific typed index, or omit it to drop both.

```txt
g.call("aerospike.graph.admin.index.drop").

     with("element_type", "vertex").

     with("property_key", "name").

     with("index_type", "string").next()
```

```txt
g.call("aerospike.graph.admin.index.drop").

     with("element_type", "vertex").

     with("property_key", "age").

     with("index_type", "numeric").next()
```

Omitting index\_type drops both types

```txt
g.call("aerospike.graph.admin.index.drop").

     with("element_type", "vertex").

     with("property_key", "name").next()
```

::: note
When you drop an index, any query that would have used that index is briefly unavailable while AGS rebuilds its index list.
:::

Expected output:

```txt
Vertex index of property key 'name' dropped.
```

### Index status

Get the status of a vertex property index:

```txt
g.call("aerospike.graph.admin.index.status").

     with("element_type", "vertex").

     with("property_key", "<key>").next()
```

-   `percent_complete`: Percentage from 0 to 100. Returns 100 when the index is ready to use.
-   `total_entries`: Total number of entries in the index across all Aerospike nodes.
-   `total_used_bytes`: Total RAM usage in bytes of the index across all Aerospike nodes.
-   `load_time`: Time in milliseconds to create the index.

### List indexed property keys

List all property keys with existing secondary indexes:

```txt
g.call("aerospike.graph.admin.index.list").next()
```

If successful, AGS returns a list of indexed property keys.

### Cardinality

In general, indexes with higher cardinality are more effective. To see examples of how indexes affect graph queries, see [Traversals](#traversals).

Get the cardinality of existing secondary indexes:

```txt
g.call("aerospike.graph.admin.index.cardinality").next()
```

If successful, AGS returns a list of indexed property keys and the cardinality of each one. The cardinality of an index is the number of unique entries in that index.

## Traversals

Indexes apply to the first step only. When the initial steps include both indexed and non-indexed properties, AGS runs the indexed filter first. Property indexes typically have higher cardinality than label indexes.

### Single indexed vertex property

This traversal uses the index on the `name` field:

```txt
______ The first step uses the index, so it is fast and efficient.

       |

       |                      _______________ Subsequent steps do not use

       |                      |    |     |    the index because they are not at the

       |                      |    |     |    start of the traversal.

       v                      V    v     v

 g.V().has("name", "Lyndon").out().in().has("name", "Simon").toList()
```

### Single non-indexed vertex property

This traversal does not use an index and may perform poorly.

```txt
______ This step does not use an index and must scan the entire database

       |       for the `country` property.

       |

       |                      __________ These steps do not use the index because they

       |                     |     |     are not at the start of the traversal.

       v                     V     v

 g.V().has("country", "USA").out().has("name", "Lyndon").toList()
```

### One indexed and one non-indexed vertex property

This traversal performs two `has` steps, one on the non-indexed `country` field and one on the indexed `name` field. AGS compounds the two `has` steps together and runs the indexed one first, improving performance.

```txt
g.V().has("country", "USA").has("name", "Lyndon").out().has("name", "Simon").toList()
```

### Two indexed vertex properties

This traversal performs two initial `has` steps, both on indexed properties. AGS uses cardinality metadata from the Aerospike database to determine which step to run first for maximum efficiency.

::: note
Cardinality metadata in Aerospike is updated once per hour, so index efficiency information may not always be current.
:::

```txt
g.V().has("age", 29).has("name", "Lyndon").out().has("name", "Simon").toList()
```

### Label index and indexed vertex property

This traversal’s first two steps are a `hasLabel` step which uses the instance’s label index, and a `has` step which uses the `name` property index. AGS performs the `has` step first because property indexes usually have higher cardinality than label indexes.

```txt
g.V().hasLabel("Person").has("name", "Lyndon").out().has("name", "Simon").toList()
```

### Label index and non-indexed vertex property

This traversal begins with a `hasLabel` step which uses the instance’s label index, and a `has` step which involves the non-indexed `country` property. AGS performs the `hasLabel` step first and uses the index, but the `country` step may be slow and inefficient.

```txt
g.V().hasLabel("Person").has("country", "USA").out().has("name", "Simon").toList()
```