如何使用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)
关键说明
ExpListIterateVar()代表遍历过程中的当前列表元素,作为正则匹配的目标对象。ListIterationFlagsOr的逻辑与旧代码中的NewPredExpListIterateOr完全一致:只要找到一个匹配元素,就停止遍历并返回true。- 正则标志需包含
ExpRegexFlagEXTENDED,对应旧代码中的QueryRegexOptionExtended,保证正则语法兼容。
此实现完全复刻了旧版PredExp的列表前缀匹配功能,同时符合Aerospike 6.x的表达式规范。
内容的提问来源于stack exchange,提问作者Joehl
相关产品推荐
相关产品推荐

