Go SDK对接向量数据库

本文介绍如何使用Go语言调用openGauss向量数据库。

环境要求

  • 安装Go 1.19及以上版本。

安装SDK

开发者可以运行以下命令安装Go SDK官方仓库,并在项目中导入该包。

1. 安装SDK
2. go get gitcode.com/opengauss/openGauss-connector-go-pq@master

4. 在项目中导入该包
5. import (
6. "database/sql"

8. _ "gitcode.com/opengauss/openGauss-connector-go-pq"
9. )

Go SDK - 图1 说明: 目前 gitcode 不支持 go get,请参考下方用例指导手动安装。

基本操作

Go SDK - 图2 说明: 该仓库中所有资料和测试文件(copy_test.go,encode_test_go等)使用的密码及sslmode=disable仅为示例,在使用时,请根据实际情况配置正确的密码,使用安全的sslmode(默认值prefer)。

1.连接数据库

1. // connectInfo格式:
2. // "host=127.0.0.1 port=5432 user=username password=userpassword dbname=userdbname sslmode=disable"
3. func CreateDBClient(connectInfo string) (*sql.DB, error) {
4. return sql.Open("opengauss", connectInfo)
5. }

2.创建表

1. func CreateTable(client *sql.DB, dim int) error {
2. execSql := fmt.Sprintf("CREATE TABLE IF NOT EXISTS demotable(id INTEGER, content TEXT, embedding vector(%d))", dim)
3. _, err := client.Exec(execSql)
4. return err
5. }

3.创建索引

1. // 用L2距离创建HNSW类型的向量索引
2. func CreateIndex(client *sql.DB) error {
3. execSql := fmt.Sprint("CREATE INDEX ON demotable USING hnsw (embedding vector_l2_ops)")
4. _, err := client.Exec(execSql)
5. return err
6. }

4.插入/删除/更新

  • 插入
1. // 单条插入
2. type TableData struct {
3. Id      int
4. Content string
5. Vector  string
6. }
7. func InsertDataSingle(client *sql.DB, data TableData) error {
8. execSql := fmt.Sprintf("INSERT INTO demotable VALUES(%d, '%s', '%s')", data.Id, data.Content, data.Vector)
9. _, err := client.Exec(execSql)
10. return err
11. }
  • 删除
1. func DeleteData(client *sql.DB) error {
2. execSql := fmt.Sprint("DELETE FROM demotable where id > 10")
3. _, err := client.Exec(execSql)
4. return err
5. }
  • 更新
1. func UpdateData(client *sql.DB, vector string) error {
2. execSql := fmt.Sprintf("UPDATE demotable set embedding = '%s' where id = 10", vector)
3. _, err := client.Exec(execSql)
4. return err
5. }

5.查询

1. func SearchVectors(client *sql.DB, efsearch int, vector string, topK int) []string {
2. var res []string
3. // 设置查询参数
4. paramsql := fmt.Sprintf("set hnsw_ef_search = %d", efsearch);
5. querysql := fmt.Sprintf("SELECT * FROM demotable ORDER BY embedding <-> '%s' LIMIT %d;", vector, topK);
6. _, _ = client.Exec(paramsql)
7. rows, _ := client.Query(querysql)
8. for rows.Next() {
9. var id int
10. var content string
11. var vector []byte
12. _ = rows.Scan(&id, &content, &vector)
13. embedding := string(vector)
14. row := fmt.Sprintf("id: %d, content: %s, embedding: %s", id, content, embedding);
15. res = append(res, row)
16. }
17. return res
18. }

6.删除表

1. func DropTable(client *sql.DB, tableName string) error {
2. execSql := fmt.Sprintf("DROP TABLE IF EXISTS %s", tableName)
3. _, err := client.Exec(execSql)
4. return err
5. }

7.多向量并发查询

多向量召回支持在单次搜索请求中同时提交多个查询向量,openGauss将并行对查询向量进行搜索,并返回多组结果。

函数名

1. func ExecuteMultiSearch(conninfo string, query string, args [][]interface{}, scanParams map[string]interface{}, threadCount int)

输入参数

  • conninfo:数据库连接配置,包含host、port、user、password、dbname
  • query:查询语句,要求是单条查询语句(select为首单词)、包含向量操作符(<->/<=>/<#>/<+>/<~>/<%>)
  • args:查询参数,要求不为空
  • scanParams:需要通过set设置的参数(如hnsw_ef_search、nprobes)
  • threadCount:连接池最大连接数,和数据库最大连接数(由参数max_connections设置)有关,一般来说,连接池最大连接数要小于数据库最大连接数,但是数据库对于管理员用户的连接限制会略超过max_connections设置。

输出参数

  • 查询结果,形式为[[map[id:1, embedding:'[1,2,3]'],map[id:2, embedding:'[2,2,2]']], [],...],表示n个查询向量对应的limit个结果。

使用案例

1. import (
2. "gitcode.com/opengauss/openGauss-connector-go-pq"
3. )
4. conninfo := "host=localhost port=5432 user=test password=yourpassword dbname=testdb"
5. scanParams := map[string]interface{}{
6. "hnsw_ef_search":"40",
7. "enable_seqscan":"off"
8. }
9. query := "select id from demotable order by embedding <-> $1 limit $2;"
10. threadCount := 2
11. args := [][]interface{}{
12. {"[1,2,3]", 2},
13. {"[2,2,2]", 3},
14. }
15. res := pq.ExecuteMultiSearch(conninfo, query, args, scanParams, threadCount)

用例指导

  • 安装 openGauss-connector-go-pq
1. # 创建部署脚本
2. cat << 'EOL' > setup_opengauss_go.sh
3. #!/bin/bash

5. # 设置项目名称和驱动信息
6. PROJECT_NAME="opengauss-go"
7. MODULE_NAME="opengauss"
8. DRIVER_MODULE_PATH="gitcode.com/opengauss/openGauss-connector-go-pq"
9. DRIVER_REPO_URL="https://$DRIVER_MODULE_PATH.git"
10. DRIVER_VERSION="v1.0.7"

12. # 获取 GOPATH
13. GOPATH=$(go env GOPATH)
14. DRIVER_LOCAL_PATH="$GOPATH/src/$DRIVER_MODULE_PATH"

16. # 创建项目目录并初始化 go mod
17. echo "🚀 初始化 Go 项目..."
18. mkdir -p "$PROJECT_NAME"
19. cd "$PROJECT_NAME" || exit 1
20. go mod init "$MODULE_NAME"

22. # 克隆 openGauss 驱动到本地路径
23. echo "📦 正在克隆 openGauss Go 驱动..."
24. mkdir -p "$DRIVER_LOCAL_PATH"
25. git clone "$DRIVER_REPO_URL" "$DRIVER_LOCAL_PATH"

27. # 修改 go.mod 添加 require 和 replace
28. echo "⚙️ 更新 go.mod 文件..."
29. cat <<EOL2 >> go.mod

31. require $DRIVER_MODULE_PATH $DRIVER_VERSION

33. replace $DRIVER_MODULE_PATH => $DRIVER_LOCAL_PATH
34. EOL2

36. # 清理模块缓存以确保生效
37. echo "🧹 清理模块缓存..."
38. go clean -modcache

40. # 下载依赖
41. echo "📥 安装依赖包..."
42. go get "$DRIVER_MODULE_PATH"

44. echo "✅ 初始化和依赖安装完成!"
45. EOL

47. # 赋予可执行权限
48. chmod +x setup_opengauss_go.sh

50. # 执行脚本,开始安装
51. ./setup_opengauss_go.sh
  • **使用 Go SDK 连接 openGauss 执行向量操作 **
1. # 创建main.go,填入一下内容
2. vim main.go
3. package main
4. import (
5. "fmt"
6. "log"
7. "database/sql"

9. _ "gitcode.com/opengauss/openGauss-connector-go-pq"
10. )

12. /*
13. * 将上述创建、删除等函数复制到此处
14. */

16. func main(){
17. connStr := "host=YourIP port=YourPort user=YourUserName password=YourPassWord dbname=YourDBName sslmode=disable"
18. dbClient, err := CreateDBClient(connStr)
19. if err != nil {
20. log.Fatal(err)
21. }

23. err = DropTable(dbClient, "demotable")
24. err = CreateTable(dbClient, 3)
25. err = CreateIndex(dbClient)

27. data := TableData{
28. Id:      1,
29. Content: "test",
30. Vector:  "[1,2,3]",
31. }
32. err = InsertDataSingle(dbClient, data)

34. data = TableData{
35. Id:      11,
36. Content: "test1",
37. Vector:  "[3,4,5]",
38. }
39. err = InsertDataSingle(dbClient, data)

41. data = TableData{
42. Id:      10,
43. Content: "test3",
44. Vector:  "[2,2,2]",
45. }
46. err = InsertDataSingle(dbClient, data)

48. err = UpdateData(dbClient, "[3,3,3]")

50. err = DeleteData(dbClient)

52. vectors := SearchVectors(dbClient, 1, "[3,2,4]", 5)
53. fmt.Println(vectors)
54. err = DropTable(dbClient, "demotable")
55. }

更多操作示例参考