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)
}
相关推荐
Grassto1 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
API开发2 天前
apiSQL网关 for Docker 离线安装和升级教程
运维·docker·容器·api·api网关·apisql·替代graphql
Grassto3 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
新诺韦尔API3 天前
手机三要素验证接口详细技术对接指南
大数据·智能手机·api
没有bug.的程序员3 天前
Spring Boot 与 Swagger:API 文档自动化生成、版本管理与云原生协作深度实战指南
spring boot·云原生·自动化·api·swagger·版本管理·自动化生产
程序设计实验室4 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题4 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo
Li emily5 天前
如何通过外汇API平台快速实现实时数据接入?
开发语言·python·api·fastapi·美股
啊汉6 天前
古文观芷App搜索方案深度解析:打造极致性能的古文搜索引擎
go·软件随想
asaotomo6 天前
一款 AI 驱动的新一代安全运维代理 —— DeepSentry(深哨)
运维·人工智能·安全·ai·go