【问题标题】:Spring-data-aerospike 'findByAttribute' operation working mysteriouslySpring-data-aerospike 'findByAttribute' 操作神秘地工作
【发布时间】:2020-10-24 20:47:14
【问题描述】:

链接如下:- https://www.aerospike.com/blog/spring-data-for-aerospike/

我们有以下示例实体:-

@Document(collection = "cust", expiration = 90, expirationUnit = TimeUnit.DAYS)
public class Customer {

   @Id
   @Field(value = "PK")
   private String custId;

   @Field(value = "mobileNumber")
   private String mobileNumber;

   @Field(value = "creationTime")
   private String creationTime;
 
@Field(value = "custType")
private String custType;
 
}

使用 Spring-repository,我们使用以下方法:-

// 工作 List<Customer> findByMobileNumber (String mobileNumber);

// 失败,201 ERR INNDEX NOT FOUND。 List<Customer> findByMobileNumberAndCustType (String mobileNumber, String customerType);

事实/观察:-

1.) 我们没有在我们的 aerospike-set 上创建任何明确的二级索引。

2.) 当我们使用 AQL 查询(select * from test.cust where mobileNumber = '981XXXXXXX')相同的记录时,它失败给我们一个 Indices not found 的错误。

疑虑/问题:-

a.) 第一种方法是如何工作的?它的内部执行方式是什么?查询完成后,是否有任何即时、二级索引被创建并被冲走?

b.) 为什么第二个失败了?

任何回应都将受到高度赞赏!

【问题讨论】:

    标签: java nosql spring-data aerospike aerospike-ce


    【解决方案1】:

    为了使用 spring-data findBy** 方法,您应该有查询字段的索引(在您的情况下,索引 bin mobileNumber),否则,aerospike 将需要完整扫描您集合中的所有文档(无论是进行或拒绝全面扫描 - 取决于 aerospike 配置)。不会自动创建索引。 所以请创建索引(以编程方式或手动)。如果以编程方式,您可以使用以下方法:

    public void createIndex(AerospikeRepository<?, ?> aerospikeRepository,
                            Class<?> entityClass,
                            String indexName,
                            String fieldName,
                            IndexType indexType) {
        var entityName = entityClass.getSimpleName();
        log.info("Creating Aerospike index [{}] for field [{}] of entity [{}]", indexName, fieldName, entityName);
        try {
            aerospikeRepository.createIndex(entityClass, indexName, fieldName, indexType);
            log.info("Aerospike index [{}] was successfully created for field [{}] of entity [{}]", indexName, fieldName, entityName);
        } catch (IndexAlreadyExistsException ex) {
            log.info("Aerospike index [{}] for field [{}] of entity [{}] already exists", indexName, fieldName, entityName);
        } catch (AerospikeException e) {
            if (e.getResultCode() == ResultCode.INDEX_ALREADY_EXISTS) {
                log.info("Aerospike index [{}] for field [{}] of entity [{}] already exists", indexName, fieldName, entityName);
                return;
            }
            throw e;
        }
    }
    

    您可以在spring-boot 应用程序中的InitializingBean afterPropertiesSet()@PostConstruct 中调用此方法createIndex

    createIndex(customerRepository, Customer.class, "customer_mobileNumber_index", "mobileNumber", IndexType.STRING);
    

    不过,这样的索引只会获取单个字段mobileNumber的记录,你需要在java代码中过滤掉customerType返回的结果

    【讨论】:

    • 感谢您回复本帖。帮我回答这个问题:>>>你应该有查询字段的索引(在你的情况下,bin mobileNumber的索引),否则,aerospike将需要对你的集合中的所有文档进行全面扫描(是否进行全面扫描或拒绝 - 取决于在 aerospike 配置上)>>> 允许或阻止这个的配置是什么?我们还没有做任何具体的配置!