我有数据库结构,接近于此:
+--------------+---------+------------------------------+
| hostname | cont | numbers |
+--------------+---------+------------------------------+
| host01 |{"k":"v"}|LIST(`[["1", "123456", ...]]`)|
| host02 |{"k":"v"}|LIST(`[["1", "654321", ...]]`)|
+--------------+---------+------------------------------+
我想通过过滤“数字”和“主机名”来获取某些记录。 它应该包含一个具有特定数字的字符串,该字符串是我从其他组件获得的。在上面的代码中,它是“123456”
基本上我都是这样搜索的,直到需要二维数组:
stmt := aerospike.NewStatement(namespaceName, setName)
stmt.SetPredExp(
aerospike.NewPredExpStringBin("hostname"),
aerospike.NewPredExpStringValue(inputHostName),
aerospike.NewPredExpStringRegex(0),
aerospike.NewPredExpStringBin("deleted"),
aerospike.NewPredExpStringValue("true"),
aerospike.NewPredExpStringEqual(),
aerospike.NewPredExpNot(),
aerospike.NewPredExpAnd(2))
)
我一直在寻找可能的方法来过滤数组,但没有得到任何解决方案。
我在网上找到的方法是这样的:
stmt := aerospike.NewStatement("test", "settest")
qPolicy := aerospike.NewQueryPolicy()
qPolicy.PredExp = append(qPolicy.PredExp,
aerospike.NewPredExpStringVar("v"),
aerospike.NewPredExpStringValue(id),
aerospike.NewPredExpStringEqual(),
aerospike.NewPredExpListBin("numbers"),
aerospike.NewPredExpListIterateOr("v"))
recordSet, err := aerospikeClient.client.Query(qPolicy, stmt)
但是这不起作用。
如果我使用主机名提供谓词表达式并以某种方式解析数组,是否可以搜索记录?
UPD:
我发现,这种情况可以通过使用过滤器表达式来解决,特别是使用 CDTContext。但是 Aerospike 文档中关于该工具使用的信息非常少,尤其是关于 Go 代码的信息。 我只找到了这个方法,它可以提供帮助,但我不明白如何在我的情况下正确使用它:
func aerospike.ExpListGetByValue(returnType aerospike.ListReturnType, value *aerospike.Expression, bin *aerospike.Expression, ctx ...*aerospike.CDTContext) *aerospike.Expression
UPD2 通过使用 ExpListGetByValue 我尝试进行查询,但找不到任何内容。它看起来像这样:
stmt := aerospike.NewStatement(namespaceName, setName)
qPolicy := aerospike.NewQueryPolicy()
qPolicy.FilterExpression = aerospike.ExpEq(
aerospike.ExpListGetByValue(
aerospike.ListReturnTypeCount,
aerospike.ExpStringVal(numbVal),
aerospike.ExpListBin("numbers")),
aerospike.ExpIntVal(1))
recordSet, err := aerospikeClient.client.Query(qPolicy, stmt)
此recordSet
为空,尽管“numbers”箱确实包含此numVal
UPD3 问题解决了。我添加了嵌套数组的上下文。完整的过滤器表达式将如下所示
qPolicy.FilterExpression = aerospike.ExpEq(
aerospike.ExpListGetByValue(
aerospike.ListReturnTypeCount,
aerospike.ExpStringVal("123456"),
aerospike.ExpListBin("numbers"),
aerospike.CtxListIndex(-1)),
aerospike.ExpIntVal(1))
最佳答案
我正在使用您在第二次更新中创建的新的和修订的过滤器来运行您的测试,它似乎有效。以下是我使用的完整代码(基于 Git 存储库中的 Aerospike 示例目录):
/*
* Copyright 2014-2022 Aerospike, Inc.
*
* Portions may be licensed to Aerospike, Inc. under one or more contributor
* license agreements.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package main
import (
"log"
as "github.com/aerospike/aerospike-client-go/v5"
shared "github.com/aerospike/aerospike-client-go/v5/examples/shared"
)
func main() {
testListExp(shared.Client)
log.Println("Example finished successfully.")
}
func testListExp(client *as.Client) {
log.Printf("Test List Expression")
key, _ := as.NewKey(*shared.Namespace, *shared.Set, "mapkey1")
client.Delete(shared.WritePolicy, key)
binHostname := as.NewBin("hostname", "host01")
amap := map[string]string{
"k": "v",
}
list := []string{
"1",
"123456",
"1111",
"222",
}
binCont := as.NewBin("cont", amap)
binNumbers := as.NewBin("numbers", list)
client.PutBins(shared.WritePolicy, key, binHostname, binCont, binNumbers)
key, _ = as.NewKey(*shared.Namespace, *shared.Set, "mapkey2")
binHostname = as.NewBin("hostname", "host02")
list = []string{
"1",
"654321",
"2222",
"3333",
}
binNumbers = as.NewBin("numbers", list)
client.PutBins(shared.WritePolicy, key, binHostname, binCont, binNumbers)
// numbVal := "654321"
getPolicy := as.NewQueryPolicy()
getPolicy.FilterExpression =
as.ExpEq(
as.ExpListGetByValue(
as.ListReturnTypeCount,
as.ExpStringVal("654321"),
as.ExpListBin("numbers")),
as.ExpIntVal(1))
stmt := as.NewStatement(*shared.Namespace, *shared.Set)
recordSet, err := client.Query(getPolicy, stmt)
shared.PanicOnError(err)
for res := range recordSet.Results() {
log.Println(res.Record.Bins)
}
}
输出是:
$ go run listExpression.go -h 172.17.0.3
2022/06/08 12:00:19 hosts: 172.17.0.3
2022/06/08 12:00:19 port: 3000
2022/06/08 12:00:19 user:
2022/06/08 12:00:19 password: *
2022/06/08 12:00:19 namespace: test
2022/06/08 12:00:19 set: testset
2022/06/08 12:00:19 Test List Expression
2022/06/08 12:00:19 map[cont:map[k:v] hostname:host02 numbers:[1 654321 2222 3333]]
2022/06/08 12:00:19 Example finished successfully.
关于go - 如何通过迭代 LIST 从 Aerospike 获取记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72464206/