向量查询 #
使用 kNN 检索 API 来进行向量查询。
先决条件 #
要运行 kNN 搜索,必须安装 knn 插件,参考 插件安装 。
创建 Mapping 和 Setting #
在索引向量之前,首先定义一个 Mapping,指定向量数据类型、索引模型和模型的参数。这决定了索引向量支持哪些查询。
并指定 index.knn 为 true ,这是为了启用近似相似度模型。
请求示例 #
PUT /knn-test
{
"settings": {
"index.knn": true
},
"mappings": {
"properties": {
"my_vec": {
"type": "knn_dense_float_vector",
"knn": {
"dims": 50,
"model": "lsh",
"similarity": "cosine",
"L": 99,
"k": 1
}
}
}
}
}
参数说明 #
- my_vec 存储向量的字段名称
- knn_dense_float_vector 表示数据类型为密集型浮点向量.
knn 字典对象,对象中的各个参数含义如下:
- dims:向量的维度。
- model:模型类型。
- similarity:相似度类型。
- L:哈希表的数量。一般来说,增加此值会增加召回率。
- k:用于形成单个哈希值的哈希函数的数量。一般来说,增加此值会增加精度。
导入测试向量数据 #
我这里采用斯坦福大学预训练好的词向量来演示 https://huggingface.co/stanfordnlp/glove/resolve/main/glove.6B.zip
下载后解压,导入 glove.6B.50d.txt 到 Easysearch,这个文件里每个词是 50 维度的向量。
将单词存为 word 字段,向量存为 my_vec 字段。
检索向量 #
以 bread 单词为例,先从索引中查出 bread 单词的向量。
请求示例 #
GET knn-test/_search
{
"query": {
"match": {
"word": "bread"
}
}
}
然后用 bread 的向量到索引中查询和它相近的词。
请求示例 #
GET knn-test/_search
{
"size": 10,
"_source": "word",
"query": {
"bool": {
"must": [
{
"knn_nearest_neighbors": {
"field": "my_vec",
"vec": {
"values": [
-0.37436,
-0.11959,
-0.87609,
-1.1217,
1.2788,
0.48323,
-0.53903,
0.053659,
-0.23929,
-0.12414,
......
]
},
"model": "lsh",
"similarity": "cosine",
"candidates": 50
}
}
]
}
}
}
示例响应 #
返回的词都是和 bread 含义相近或者经常一起出现的。
{
"took": 214,
......
"hits": {
"total": {
"value": 400,
"relation": "eq"
},
"max_score": 2,
"hits": [
{
"_index": "knn-test",
"_type": "_doc",
"_id": "WYPvCYkBkPNAx5w6LJ6H",
"_score": 2,
"_source": {
"word": "bread"
}
},
{
"_index": "knn-test",
"_type": "_doc",
"_id": "PYPvCYkBkPNAx5w6Mbui",
"_score": 1.8483887,
"_source": {
"word": "baked"
}
},
{
"_index": "knn-test",
"_type": "_doc",
"_id": "RoPvCYkBkPNAx5w6NsYl",
"_score": 1.8451341,
"_source": {
"word": "toast"
}
},
{
"_index": "knn-test",
"_type": "_doc",
"_id": "o4PvCYkBkPNAx5w6LKCI",
"_score": 1.84022,
"_source": {
"word": "butter"
}
},
{
"_index": "knn-test",
"_type": "_doc",
"_id": "koPvCYkBkPNAx5w6LKeK",
"_score": 1.8374994,
"_source": {
"word": "soup"
}
}
]
}
}
精确映射(Exact Mapping) #
精确模型允许您运行精确搜索。这些搜索不使用任何索引结构,其运行时间为 O(n^2),其中 n 是文档总数。
使用该模型不需要提供任何模型参数。
请求示例 #
PUT /my-index/_mapping
{
"properties": {
"my_vec": {
"type": "knn_(dense_float | sparse_bool)_vector", # 1. 向量数据类型
"knn": {
"dims": 100 # 2. 向量的维度
}
}
}
}
注意,使用精确模型可以进行精确搜索,但计算开销较大,适用于文档数量较少的情况。
精确查询(Exact Query) #
计算查询向量与所有索引向量之间的精确相似度。相对于近似搜索,该算法效率较低,但实现已经经过广泛的优化和分析。
请求示例 #
GET /my-index/_search
{
"query": {
"knn_nearest_neighbors": {
"field": "my_vec",
"vec": { # 1
"values": [0.1, 0.2, 0.3, ...],
},
"model": "exact", # 2
"similarity": "(cosine | l1 | l2)", # 3
}
}
}
参数说明 #
#1 查询向量。必须匹配 my_vec 的数据类型
#2 模型名称。
#3 相似性函数。必须与向量类型兼容