Go-qdrant-API开启客服系统新模式

最近算法后台更化成了go语言的,整理了一些关于向量数据库的接口函数,有需要的可以借鉴,目前已经整理的是我在开发客服系统一用到的,为用到的暂时没有写。

官方更多 API:https://api.qdrant.tech/api-reference

使用 http 端口号是 3334,使用包需要 3335

案例代码:https://github.com/qdrant/go-client/blob/master/examples/main.go

1. getClient
复制代码
func getClient() *qdrant.Client {
	// 创建客户端
	client, err := qdrant.NewClient(&qdrant.Config{
		Host:   "192.168.0.91", // Can be omitted, default is "localhost"
		Port:   56334,          // Can be omitted, default is 6334
		APIKey: "axUut0X8Mws7DBND1MWvYO7G",
		// APIKey: "<API_KEY>",
		// UseTLS: true,
		// PoolSize: 3,
		// KeepAliveTime: 10,
		// KeepAliveTimeout: 2,
		// TLSConfig: &tls.Config{...},
		// GrpcOptions: []grpc.DialOption{},
	})
	if err != nil {
		panic(err)
	}
	// defer client.Close()
	return client
}
2. createCollection
复制代码
func createCollection(client *qdrant.Client, ctx context.Context, collectionName string) {
	// 创建集合
	defaultSegmentNumber := uint64(2)
	err := client.CreateCollection(ctx, &qdrant.CreateCollection{
		CollectionName: collectionName,
		VectorsConfig: qdrant.NewVectorsConfig(&qdrant.VectorParams{
			Size:     uint64(4),
			Distance: qdrant.Distance_Dot,
		}),
		OptimizersConfig: &qdrant.OptimizersConfigDiff{
			DefaultSegmentNumber: &defaultSegmentNumber,
		},
	})
	if err != nil {
		panic(fmt.Errorf("could not create collection: %w", err))
	}
	log.Println("Collection", collectionName, "created")
}
3. listCollection
复制代码
func listCollection(client *qdrant.Client, ctx context.Context) {
	// 列出所有集合
	collections, err := client.ListCollections(ctx)
	if err != nil {
		panic(fmt.Errorf("could not list collections: %w", err))
	}
	log.Printf("List of collections: %s", collections)
}
4. upsertData
复制代码
func upsertData(client *qdrant.Client, ctx context.Context, collectionName string) {
	waitUpsert := true
	upsertPoints := []*qdrant.PointStruct{
		{
			Id:      qdrant.NewIDNum(1),
			Vectors: qdrant.NewVectors(0.05, 0.61, 0.76, 0.74),
			Payload: qdrant.NewValueMap(map[string]any{
				"city":    "Berlin",
				"country": "Germany",
				"count":   1000000,
				"square":  12.5,
			}),
		},
		{
			Id:      qdrant.NewIDNum(2),
			Vectors: qdrant.NewVectors(0.19, 0.81, 0.75, 0.11),
			Payload: qdrant.NewValueMap(map[string]any{
				"city":    "Berlin",
				"country": "London",
			}),
		},
		{
			Id:      qdrant.NewIDNum(3),
			Vectors: qdrant.NewVectors(0.36, 0.55, 0.47, 0.94),
			Payload: qdrant.NewValueMap(map[string]any{
				"city": []any{"Berlin", "London"},
			}),
		},
		{
			Id:      qdrant.NewID("58384991-3295-4e21-b711-fd3b94fa73e3"),
			Vectors: qdrant.NewVectors(0.35, 0.08, 0.11, 0.44),
			Payload: qdrant.NewValueMap(map[string]any{
				"bool":   true,
				"list":   []any{true, 1, "string"},
				"count":  1000000,
				"square": 12.5,
			}),
		},
	}

	_, err := client.Upsert(ctx, &qdrant.UpsertPoints{
		CollectionName: collectionName,
		Wait:           &waitUpsert,
		Points:         upsertPoints,
	})
	if err != nil {
		panic(fmt.Errorf("could not upsert points: %w", err))
	}
	log.Println("Upsert", len(upsertPoints), "points")

}
5. queryData
复制代码
func queryData(client *qdrant.Client, ctx context.Context, collectionName string) {
	searchedPoints, err := client.Query(ctx, &qdrant.QueryPoints{
		CollectionName: collectionName,
		Query:          qdrant.NewQuery(0.2, 0.1, 0.9, 0.7),
		WithPayload:    qdrant.NewWithPayloadInclude("city"),
	})
	if err != nil {
		panic(fmt.Errorf("could not search points: %w", err))
	}
	// log.Printf("Found points: %s", searchedPoints)
	fmt.Printf("结构: %+v\n", searchedPoints)
	for i, group := range searchedPoints {
		fmt.Println(i, group)
	}

}
6. queryFilterData
复制代码
func queryFilterData(client *qdrant.Client, ctx context.Context, collectionName string) {
	valueVector := []float32{0.2, 0.1, 0.9, 0.7}
	filteredPoints, err := client.Query(ctx, &qdrant.QueryPoints{
		CollectionName: collectionName,
		Query:          qdrant.NewQuery(valueVector...),
		Filter: &qdrant.Filter{
			Should: []*qdrant.Condition{
				qdrant.NewMatchKeyword("city", "Berlin"),
			},
		},
	})
	if err != nil {
		panic(fmt.Errorf("could not search points: %w", err))
	}
	// log.Printf("Found points: %s", filteredPoints)
	fmt.Printf("结构: %+v\n", filteredPoints)
	for i, group := range filteredPoints {
		fmt.Println(i, group)
	}



func queryFilterData2(client *qdrant.Client, ctx context.Context, collectionName string) {
	valueVector := []float32{0.2, 0.1, 0.9, 0.7}
	filteredPoints, err := client.Query(ctx, &qdrant.QueryPoints{
		CollectionName: collectionName,
		Query:          qdrant.NewQueryDense(valueVector),
		Filter: &qdrant.Filter{
			Should: []*qdrant.Condition{
				qdrant.NewMatchKeyword("city", "Berlin"),
			},
		},
	})
	if err != nil {
		panic(fmt.Errorf("could not search points: %w", err))
	}
	// log.Printf("Found points: %s", filteredPoints)
	fmt.Printf("结构: %+v\n", filteredPoints)
	for i, group := range filteredPoints {
		fmt.Println(i, group)
	}
}
7. queryByID
复制代码
func queryByID(client *qdrant.Client, ctx context.Context, collectionName string) {
	// 获取根据ID查询单点
	point, err := client.Get(ctx, &qdrant.GetPoints{
		CollectionName: collectionName,
		Ids: []*qdrant.PointId{
			qdrant.NewIDNum(1),
		},
		WithPayload: qdrant.NewWithPayload(true),
		WithVectors: qdrant.NewWithVectors(false),
	})
	if err != nil {
		panic(fmt.Errorf("could not get point: %w", err))
	}
	fmt.Printf("结构: %+v\n", point)
}

func queryByIDS(client *qdrant.Client, ctx context.Context, collectionName string) {
	// 获取根据ID查询多点
	points, err := client.Get(ctx, &qdrant.GetPoints{
		CollectionName: collectionName,
		Ids: []*qdrant.PointId{
			qdrant.NewIDNum(1), qdrant.NewIDNum(2), qdrant.NewIDNum(3),
		},
		WithPayload: qdrant.NewWithPayload(true),
		WithVectors: qdrant.NewWithVectors(false),
	})
	if err != nil {
		panic(fmt.Errorf("could not get points: %w", err))
	}
	fmt.Printf("结构: %+v\n", points)
}
8. deleteByIdOrFilter
复制代码
func deleteByIdOrFilter(client *qdrant.Client, ctx context.Context, collectionName string) {
	// 删除根据ID删除单点
	_, err := client.Delete(context.Background(), &qdrant.DeletePoints{
		CollectionName: collectionName,
		Points: qdrant.NewPointsSelectorIDs([]*qdrant.PointId{
			qdrant.NewIDNum(1),
		}),
	})
	if err != nil {
		panic(fmt.Errorf("could not delete points: %w", err))
	}
	// _, err = client.Delete(ctx, &qdrant.DeletePoints{
	// 	CollectionName: collectionName,
	// 	Points: qdrant.NewPointsSelectorFilter(&qdrant.Filter{
	// 		Must: []*qdrant.Condition{
	// 			qdrant.NewMatch("color", "red"),
	// 		},
	// 	}),
	// })
	// if err != nil {
	// 	panic(err)
	// }
}
9. createMultiSpaceCollection
复制代码
func createMultiSpaceCollection(client *qdrant.Client, ctx context.Context, coll string) error {
	_, err := client.CreateCollection(ctx, &qdrant.CreateCollection{
		CollectionName: coll,
		VectorsConfig: qdrant.NewVectorsConfigMap(map[string]*qdrant.VectorParams{
			"image": {
				Size:     512,
				Distance: qdrant.Distance_Cosine,
			},
			"text": {
				Size:     768,
				Distance: qdrant.Distance_Cosine,
			},
		}),
	})
	return err
}
10. insertMultiSpaceData
复制代码
func insertMultiSpaceData(client *qdrant.Client, ctx context.Context, coll string) error {
	// 第一条:两个命名空间都有向量
	pt1 := &qdrant.PointStruct{
		Id: qdrant.NewIDNum(1),
		Vectors: qdrant.NewVectorsMap(map[string]*qdrant.Vector{
			"image": qdrant.NewVector(makeVector(512)...), // 512 维
			"text":  qdrant.NewVector(makeVector(768)...), // 768 维
		}),
		Payload: qdrant.NewValueMap(map[string]interface{}{
			"desc": "both vectors",
		}),
	}

	// 第二条:只有 text 向量
	pt2 := &qdrant.PointStruct{
		Id: qdrant.NewIDNum(2),
		Vectors: qdrant.NewVectorsMap(map[string]*qdrant.Vector{
			"text": qdrant.NewVector(makeVector(768)...),
		}),
		Payload: qdrant.NewValueMap(map[string]interface{}{
			"desc": "text only",
		}),
	}

	_, err := client.Upsert(ctx, &qdrant.UpsertPoints{
		CollectionName: coll,
		Points:         []*qdrant.PointStruct{pt1, pt2},
	})
	return err
}

// 快速生成指定维度的假向量
func makeVector(dim int) []float32 {
	v := make([]float32, dim)
	for i := 0; i < dim; i++ {
		v[i] = float32(i%10) * 0.1 // 0.0, 0.1, 0.2 ...
	}
	return v
}
11. searchByText
复制代码
func searchByText(client *qdrant.Client, ctx context.Context, coll string) error {
	resp, err := client.Search(ctx, &qdrant.SearchPoints{
		CollectionName: coll,
		Vector:         qdrant.NewSearchVector(makeVector(768)...), // 768 维
		VectorName:     qdrant.PtrOf("text"),                       // 指定命名空间
		Limit:          qdrant.PtrOf(uint64(2)),
		WithPayload:    qdrant.NewWithPayload(true),
		WithVectors:    qdrant.NewWithVectors([]string{"text"}), // 只返回 text 向量
	})
	if err != nil {
		return err
	}
	fmt.Println("=== search by text ===")
	for _, r := range resp {
		fmt.Printf("id=%v score=%.3f payload=%v text=%v\n",
			r.Id, r.Score, r.Payload, r.Vectors["text"])
	}
	return nil
}
12. searchByImage
复制代码
func searchByImage(client *qdrant.Client, ctx context.Context, coll string) error {
	resp, err := client.Search(ctx, &qdrant.SearchPoints{
		CollectionName: coll,
		Vector:         qdrant.NewSearchVector(makeVector(512)...), // 512 维
		VectorName:     qdrant.PtrOf("image"),                      // 指定命名空间
		Limit:          qdrant.PtrOf(uint64(2)),
		WithPayload:    qdrant.NewWithPayload(true),
		WithVectors:    qdrant.NewWithVectors([]string{"image", "text"}), // 返回两个空间
	})
	if err != nil {
		return nil
	}
	fmt.Println("=== search by image ===")
	for _, r := range resp {
		fmt.Printf("id=%v score=%.3f payload=%v image=%v text=%v\n",
			r.Id, r.Score, r.Payload, r.Vectors["image"], r.Vectors["text"])
	}
	return nil
}
13. countData
复制代码
func countData(client *qdrant.Client, ctx context.Context, collectionName string) {
	// count, err := client.Count(ctx, &qdrant.CountPoints{
	// 	CollectionName: collectionName,
	// 	Filter: &qdrant.Filter{
	// 		Must: []*qdrant.Condition{
	// 			qdrant.NewMatch("color", "red"),
	// 		},
	// 	},
	// })
	count, err := client.Count(ctx, &qdrant.CountPoints{
		CollectionName: collectionName,
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("Count:", count)
}
14. main
复制代码
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/qdrant/go-client/qdrant"
)


func main() {
	collectionName := "go_test_db"
	fmt.Print(collectionName)
	client := getClient()
	// Get a context for a minute
	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()
	// Execute health check
	healthCheckResult, err := client.HealthCheck(ctx)
	if err != nil {
		panic(fmt.Errorf("could not get health: %w", err))
	}
	log.Printf("Qdrant version: %s", healthCheckResult.GetVersion())

	// createCollection(client, ctx, collectionName)
	// listCollection(client, ctx)
	// upsertData(client, ctx, collectionName)
	// queryData(client, ctx, collectionName)
	// queryFilterData(client, ctx, collectionName)
	// queryFilterData2(client, ctx, collectionName)
	deleteCollection(client, ctx, collectionName)
}
相关推荐
喵个咪7 小时前
开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:Makefile 在后端开发中的应用与 Windows 环境配置
后端·go
梦想的旅途28 小时前
Access Token 生命周期管理:详细设计 Token 的获取、缓存、续期和过期处理机制
机器人·企业微信·api·rpa
未来魔导18 小时前
go语言中json操作总结
数据分析·go·json
王中阳Go背后的男人1 天前
GoFrame vs Laravel:从ORM到CLI工具的全面对比与迁移指南
后端·go
天远API1 天前
Java后端进阶:处理多数据源聚合API —— 以天远小微企业报告为例
大数据·api
卡尔特斯1 天前
Go 安装插件更换国内镜像
go
王中阳Go1 天前
都2026年了,PHP还纠结转Go还是Java呢?安利一个无缝迁移的框架~
java·后端·go
卡尔特斯1 天前
go get 快速入门(自用笔记)
go
得物技术1 天前
Go语言在高并发高可用系统中的实践与解决方案|得物技术
go