径向搜索

径向搜索扩展了向量搜索的能力,超越了近似的 top-k 搜索。通过径向搜索,您可以搜索向量空间中所有位于查询点指定最大距离或最小评分阈值内的点。这为搜索操作提供了更大的灵活性和实用性。

参数

径向搜索支持以下参数:

  • max_distance:指定向量空间中的一个物理距离,识别所有距离查询点在此距离内的点。这种方法特别适用于需要空间邻近性或绝对距离测量的应用场景。

  • min_score:指定一个相似性评分,有助于检索相对于查询点达到或超过此评分的点。在相对相似性(基于特定度量)比物理邻近性更关键的情况下,此方法非常理想。

在径向搜索中,只需指定一个查询变量:kmax_distancemin_score

支持的场景

您可以使用 Lucene 或 Faiss 引擎执行径向搜索。下表按引擎总结了径向搜索的用例。

支持的引擎 支持过滤器 支持嵌套字段 搜索类型
Lucene 近似
Faiss 近似

空间

关于支持的空间,请参阅 空间

示例

以下示例可以帮助您开始使用径向搜索。

前提条件

要使用支持径向搜索的向量索引,请通过将 index.knn 设置为 true 来创建向量索引。指定一个或多个 knn_vector 数据类型的字段,如下例所示:

PUT knn-index-test
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 1,
    "index.knn": true
  },
  "mappings": {
    "properties": {
      "my_vector": {
        "type": "knn_vector",
        "dimension": 2,
        "space_type": "l2",
        "method": {
            "name": "hnsw",
            "engine": "faiss",
            "parameters": {
              "ef_construction": 100,
              "m": 16,
              "ef_search": 100
            }
          }
      }
    }
  }
}

创建索引后,添加一些类似以下的数据:

PUT _bulk?refresh=true
{"index": {"_index": "knn-index-test", "_id": "1"}}
{"my_vector": [7.0, 8.2], "price": 4.4}
{"index": {"_index": "knn-index-test", "_id": "2"}}
{"my_vector": [7.1, 7.4], "price": 14.2}
{"index": {"_index": "knn-index-test", "_id": "3"}}
{"my_vector": [7.3, 8.3], "price": 19.1}
{"index": {"_index": "knn-index-test", "_id": "4"}}
{"my_vector": [6.5, 8.8], "price": 1.2}
{"index": {"_index": "knn-index-test", "_id": "5"}}
{"my_vector": [5.7, 7.9], "price": 16.5}

示例:使用 max_distance 进行径向搜索

以下示例展示了使用 max_distance 进行的径向搜索:

GET knn-index-test/_search
{
    "query": {
        "knn": {
            "my_vector": {
                "vector": [
                    7.1,
                    8.3
                ],
                "max_distance": 2
            }
        }
    }
}

所有落在平方欧几里得距离 l2^2 为 2 范围内的文档都会被返回,如以下响应所示:

{
    "took": 6,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 4,
            "relation": "eq"
        },
        "max_score": 0.98039204,
        "hits": [
            {
                "_index": "knn-index-test",
                "_id": "1",
                "_score": 0.98039204,
                "_source": {
                    "my_vector": [
                        7.0,
                        8.2
                    ],
                    "price": 4.4
                }
            },
            {
                "_index": "knn-index-test",
                "_id": "3",
                "_score": 0.9615384,
                "_source": {
                    "my_vector": [
                        7.3,
                        8.3
                    ],
                    "price": 19.1
                }
            },
            {
                "_index": "knn-index-test",
                "_id": "4",
                "_score": 0.62111807,
                "_source": {
                    "my_vector": [
                        6.5,
                        8.8
                    ],
                    "price": 1.2
                }
            },
            {
                "_index": "knn-index-test",
                "_id": "2",
                "_score": 0.5524861,
                "_source": {
                    "my_vector": [
                        7.1,
                        7.4
                    ],
                    "price": 14.2
                }
            }
        ]
    }
}

示例:使用 max_distance 和过滤器进行径向搜索

以下示例展示了使用 max_distance 和响应过滤器进行的径向搜索:

GET knn-index-test/_search
{
  "query": {
    "knn": {
      "my_vector": {
        "vector": [7.1, 8.3],
        "max_distance": 2,
        "filter": {
          "range": {
            "price": {
              "gte": 1,
              "lte": 5
            }
          }
        }
      }
    }
  }
}

所有落在平方欧几里得距离 l2^2 为 2 范围内且价格在 1 到 5 之间的文档都会被返回,如以下响应所示:

{
    "took": 4,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": 0.98039204,
        "hits": [
            {
                "_index": "knn-index-test",
                "_id": "1",
                "_score": 0.98039204,
                "_source": {
                    "my_vector": [
                        7.0,
                        8.2
                    ],
                    "price": 4.4
                }
            },
            {
                "_index": "knn-index-test",
                "_id": "4",
                "_score": 0.62111807,
                "_source": {
                    "my_vector": [
                        6.5,
                        8.8
                    ],
                    "price": 1.2
                }
            }
        ]
    }
}

示例:使用 min_score 进行径向搜索

以下示例展示了使用 min_score 进行的径向搜索:

GET knn-index-test/_search
{
  "query": {
    "knn": {
      "my_vector": {
        "vector": [7.1, 8.3],
        "min_score": 0.95
      }
    }
  }
}

所有评分达到或超过 0.9 的文档都会被返回,如以下响应所示:

{
    "took": 3,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": 0.98039204,
        "hits": [
            {
                "_index": "knn-index-test",
                "_id": "1",
                "_score": 0.98039204,
                "_source": {
                    "my_vector": [
                        7.0,
                        8.2
                    ],
                    "price": 4.4
                }
            },
            {
                "_index": "knn-index-test",
                "_id": "3",
                "_score": 0.9615384,
                "_source": {
                    "my_vector": [
                        7.3,
                        8.3
                    ],
                    "price": 19.1
                }
            }
        ]
    }
}

示例:使用 min_score 和过滤器进行径向搜索

以下示例展示了使用 min_score 和响应过滤器进行的径向搜索:

GET knn-index-test/_search
{
    "query": {
        "knn": {
            "my_vector": {
                "vector": [
                    7.1,
                    8.3
                ],
                "min_score": 0.95,
                "filter": {
                    "range": {
                        "price": {
                            "gte": 1,
                            "lte": 5
                        }
                    }
                }
            }
        }
    }
}

所有评分达到或超过 0.9 且价格在 1 到 5 之间的文档都会被返回,如下例所示:

{
    "took": 4,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 0.98039204,
        "hits": [
            {
                "_index": "knn-index-test",
                "_id": "1",
                "_score": 0.98039204,
                "_source": {
                    "my_vector": [
                        7.0,
                        8.2
                    ],
                    "price": 4.4
                }
            }
        ]
    }
}