You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Aerospike Expressions实现列表项的正则前缀搜索

迁移Aerospike后实现列表Bin的前缀匹配搜索

背景

我们正在从Aerospike 3.15.1.4迁移至6.2.0.7版本,同时将Go客户端从aerospike-client-go v4.5.2+incompatible升级到aerospike-client-go/v6 v6.6.0。由于Predicate Expressions(PredExp)在Aerospike 5.2起被弃用,6.0版本已完全移除,因此必须切换到Aerospike Expressions。

我们有一个存储字符串列表的Bin,需要实现前缀匹配搜索。旧版本中用PredExp实现的代码如下:

as.NewPredExpStringVar("v"),
as.NewPredExpStringValue("^"+regexp.QuoteMeta("search_term")),
as.NewPredExpStringRegex(QueryRegexOptionExtended|QueryRegexOptionIgnoreCase),
as.NewPredExpListBin("ListField"),
as.NewPredExpListIterateOr("v"),

新版本中,实现精确值搜索可使用以下两种方式:

// 作为Statement内的Filter
as.NewContainsFilter("ListField", as.ICT_LIST, "search_term")

// 作为QueryPolicy的FilterExpression
*as.ExpGreater(
    as.ExpListGetByValue(
        as.ListReturnTypeCount,
        as.ExpStringVal("search_term"),
        as.ExpListBin("ListField")),
    as.ExpIntVal(0),
)

问题

如何通过新的Aerospike Expressions实现前缀匹配搜索?

我们尝试了以下代码但未成功:

*as.ExpRegexCompare(
    "^"+regexp.QuoteMeta("search_term"),
    as.ExpRegexFlagICASE,
    as.ExpListBin("ListField"),
)

Aerospike日志中出现警告:

WARNING (exp): (exp.c:1469) build_cmp_regex - error 4 invalid arg type 4 (list) != 3 (str)
WARNING (query): (query.c:1485) basic query job failed msg field processing

补充信息

  • 存储的模型结构:
type MyModel struct {
    ListField []string
    // 其他字段
}
  • 对应的二级索引:
    • 索引名称:idx_MYSET_ListField
    • 命名空间:myns
    • 集合:MYSET
    • Bin:ListField
    • 类型:string
    • 索引类型:list
    • 状态:RW
  • 示例记录(通过aql查询):
aql> select PK,ListField from myns.MYSET where PK = 12345
+--------------------+-------------------------------------------------------------------+
| PK | ListField |
+--------------------+-------------------------------------------------------------------+
| 12345 | LIST('["myid:1234", "testid2", "some-other-value", "more-values"]') |
+--------------------+-------------------------------------------------------------------+

解决方案

问题根源在于ExpRegexCompare只能直接作用于字符串类型的Bin,无法直接处理列表。要实现列表元素的前缀匹配,需要用ExpListIterate遍历列表中的每个元素,对单个元素执行正则匹配,再判断是否存在至少一个匹配项。

正确代码实现如下:

// 构建针对列表单个元素的正则匹配表达式
regexExp := as.ExpRegexCompare(
    "^"+regexp.QuoteMeta("search_term"),
    as.ExpRegexFlagICASE|as.ExpRegexFlagEXTENDED,
    as.ExpListIterateVar(),
)

// 遍历列表,只要有一个元素匹配就返回true
filterExp := as.ExpListIterate(
    as.ExpListBin("ListField"),
    regexExp,
    as.ListIterationFlagsOr, // 匹配到第一个符合条件的元素后立即终止遍历
)

// 将表达式绑定到查询策略
queryPolicy := as.NewQueryPolicy()
queryPolicy.FilterExpression = filterExp

// 执行查询
stmt := as.NewStatement("myns", "MYSET")
records, err := client.Query(queryPolicy, stmt)

关键说明

  1. ExpListIterateVar()代表遍历过程中的当前列表元素,作为正则匹配的目标对象。
  2. ListIterationFlagsOr的逻辑与旧代码中的NewPredExpListIterateOr完全一致:只要找到一个匹配元素,就停止遍历并返回true。
  3. 正则标志需包含ExpRegexFlagEXTENDED,对应旧代码中的QueryRegexOptionExtended,保证正则语法兼容。

此实现完全复刻了旧版PredExp的列表前缀匹配功能,同时符合Aerospike 6.x的表达式规范。

内容的提问来源于stack exchange,提问作者Joehl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:52:46