Skip to main content

How to create secondary index in Spring Data Aerospike

· 3 min read

Secondary indexes are on a non-primary key, which allows you to model one-to-many relationships. []( Secondary indexes are on a non-primary key, which allows you to model one-to-many relationships.

spring-data-aerospike supports creating secondary indexes in Aerospike out of the box.

There are two ways to accomplish this task:

  1. Using AerospikeTemplate createIndex method; or

  2. Using @Indexed annotation placed over the field in your entity.

    Let’s dive into more details.

Note: Before continuing it is expected that your project has spring-data-aerospike already setup. Please check this guide to find out how to do it.

First approach — creating index via AerospikeTemplate

In this example we will create an index at startup of the application manually.

package com.example.demo.persistence.index;

import com.aerospike.client.query.IndexType;
import com.example.demo.persistence.simplecrud.MovieDocument;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

public class AerospikeIndexConfiguration {

private static final String INDEX_NAME = "movie-rating-index";

value = "aerospike." + INDEX_NAME + ".create-on-startup",
havingValue = "true",
matchIfMissing = true)
public boolean createAerospikeIndex(AerospikeTemplate aerospikeTemplate) {
try {
aerospikeTemplate.createIndex(MovieDocument.class, INDEX_NAME, "rating", IndexType.NUMERIC);"Index {} was successfully created", INDEX_NAME);
} catch (IndexAlreadyExistsException e) {"Index {} already exists, skipped creating", INDEX_NAME);
return true;

Second approach — creating index via @Indexed annotation

Place @Indexed annotation over the field that you want to index in your entity and specify required types of the index. This will make spring-data-aerospike to auto-create specified secondary index in Aerospike on startup of your application.

Note:@Indexed annotation is not supported for the fields annotated with @Id, @Expiration or @Version annotations.

package com.example.demo.persistence.index;

import lombok.Value;

import java.util.List;

import static com.aerospike.client.query.IndexCollectionType.DEFAULT;
import static com.aerospike.client.query.IndexCollectionType.LIST;
import static com.aerospike.client.query.IndexType.NUMERIC;
import static com.aerospike.client.query.IndexType.STRING;

public class IndexedDocument {

String key;

@Indexed(type = STRING, collectionType = DEFAULT)
String author;

@Indexed(type = NUMERIC, collectionType = DEFAULT)
int likes;

@Indexed(type = NUMERIC, collectionType = LIST)
List<Integer> options;


Verify indexes were created using the following tests:

package com.example.demo;

import com.aerospike.client.AerospikeClient;
import com.aerospike.client.Info;
import com.aerospike.client.cluster.Node;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

public class IndexTests extends DemoApplicationTests {

String namespace;

AerospikeClient client;

void verifyCustomIndexCreated() {
List<String> existingIndexes = getIndexes(client, namespace);


void verifyAnnotationBasedIndexesCreated() {
List<String> existingIndexes = getIndexes(client, namespace);


private static List<String> getIndexes(AerospikeClient client, String namespace) {
Node node = client.getNodes()[0];
String response = Info.request(node, "sindex/" + namespace);
.map(info -> {
Map<String, String> keyValue =":"))
.map(part -> {
String[] kvParts = part.split("=");
return Map.entry(kvParts[0], kvParts[1]);
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
return keyValue.get("indexname");


Demo project is located on GitHub —