Filtering in neural sparse ANN search
출처: 문서
본문
neural sparse ANN 검색에서 필터링
필터링과 함께 neural sparse 근사 최근접 이웃(ANN) 검색 쿼리를 실행하는 방법은 다음과 같아요:
neural_sparse쿼리의method_parameters에filter를 제공하는 방법이에요. 이 필터는sparse_vector필드에 설정된 엔진이 평가하기 때문에, 필터가 적용되는 방식은 해당 엔진에 따라 달라져요.neural_sparse쿼리를 불리언 필터로 감싸는 방법이에요. 이 필터는 쿼리가 상위k개 결과를 반환한 후 엔진 외부에서 평가되며, 두 엔진 모두 같은 방식으로 적용해요.
필터 적용하기
3.9에 도입됨 {: .label .label-purple }
neural sparse ANN 검색은 두 가지 엔진을 지원하며, sparse_vector 필드의 method.engine 매핑 파라미터로 선택할 수 있어요. 두 엔진 모두 필터가 매우 선택적일 때는 정확 검색으로 전환하지만, 근사 검색을 실행하는 경우에는 필터를 검색 전에 적용하는지 검색 후에 적용하는지가 서로 달라요. 쿼리 문법은 두 엔진 모두 동일해요. 엔진에 대한 자세한 내용은 엔진을 참고하세요.
알고리즘은 다음 변수들을 사용해 필터 적용 방식을 결정해요:
- N: 인덱스에 있는 문서 수
- P: 필터가 적용된 후 문서 하위 집합에 있는 문서 수 (P <= N)
- k: 응답에 반환할 벡터의 최대 개수
P가 k보다 작으면 두 엔진 모두 필터링된 P개 문서를 대상으로 정확 검색을 실행해요. 근사 검색을 실행했다면 k보다 훨씬 적은 결과가 반환될 수 있기 때문이에요. P가 k보다 크면 엔진은 다음과 같이 필터를 적용해요.
| 엔진 | 필터 적용 방식 | 결과 개수 |
|---|---|---|
lucene (기본값) |
후처리 필터링이에요. 알고리즘은 N개 문서에서 실행되고, 그 결과에 필터가 적용되므로 결과는 상위 매치와 필터의 교집합이 돼요. | 선택적인 필터는 k개보다 적은 결과를 반환할 수 있어요. |
native |
사전 필터링이에요. 필터가 후보 집합 형태로 엔진에 푸시다운되기 때문에, 검색은 필터링된 집합 내에서 실행돼요. | 전체 k개 결과를 반환해요. |
Lucene 엔진을 사용한 후처리 필터링
P가 k보다 크면 Lucene 엔진은 N개 문서를 대상으로 neural sparse ANN 검색 알고리즘을 실행한 다음 결과에 필터를 적용해요. 필터가 근사 결과에 적용되기 때문에, 선택적인 필터는 k개보다 적은 결과를 반환할 수 있어요.
native 엔진을 사용한 사전 필터링
P가 k보다 크면 native 엔진은 검색이 시작되기 전에 필터를 후보 집합 형태로 푸시다운해요. 그런 다음 근사 검색이 필터링된 집합 내에서 실행되기 때문에, 선택적인 필터가 결과 개수를 줄이지 않고 쿼리는 전체 k개 결과를 반환해요.
필드에 native 엔진을 사용하려면 필드 매핑에서 method.engine을 native로 설정하면 돼요.
native 엔진은 기본적으로 비활성화되어 있으며 추가 노드 설정이 필요해요. 이 엔진을 사용하는 필드를 만들기 전에 엔진을 활성화해야 해요. 자세한 내용은 native 엔진 활성화하기를 참고하세요. {: .note}
다음 요청은 예제에서 사용되는 hotels-index 인덱스와 동일한, name_embedding 필드가 native 엔진을 사용하는 인덱스를 생성해요:
PUT /hotels-index-native
{
"settings": {
"index": {
"sparse": true
}
},
"mappings": {
"properties": {
"name":{
"type": "text"
},
"rating": {
"type": "integer"
},
"parking": {
"type": "boolean"
},
"name_embedding":{
"type": "sparse_vector",
"method": {
"name": "seismic",
"engine": "native",
"parameters": {
"quantization_ceiling_ingest": 16,
"n_postings": 4000,
"cluster_ratio": 0.1,
"summary_prune_ratio": 0.4,
"approximate_threshold": 1000000,
"forward_index": "per_block"
}
}
}
}
}
}
{% include copy-curl.html %}
neural sparse ANN 검색 필터 사용하기
이 예제에서는 인덱스를 만들고, 평점이 높고 주차가 가능하며 검색 조건에 맞는 이름을 가진 세 개의 호텔을 검색해 볼 거예요. 이 인덱스는 기본값인 Lucene 엔진을 사용하기 때문에 필터는 근사 검색 후에 적용돼요. 사전 필터링으로 동일한 쿼리를 실행하려면 native 엔진을 사용한 사전 필터링에서 설명한 것처럼 필드를 native 엔진으로 매핑하면 돼요.
1단계: 새 인덱스 생성하기
필터와 함께 neural sparse ANN 검색을 실행하려면 먼저 sparse_vector 필드가 있는 인덱스를 만들어야 해요.
다음 요청은 hotels-index라는 새 인덱스를 생성해요:
PUT /hotels-index
{
"settings": {
"index": {
"sparse": true
}
},
"mappings": {
"properties": {
"name":{
"type": "text"
},
"rating": {
"type": "integer"
},
"parking": {
"type": "boolean"
},
"name_embedding":{
"type": "sparse_vector",
"method": {
"name": "seismic",
"parameters": {
"quantization_ceiling_ingest": 16,
"n_postings": 4000,
"cluster_ratio": 0.1,
"summary_prune_ratio": 0.4,
"approximate_threshold": 1000000
}
}
}
}
}
}
{% include copy-curl.html %}
2단계: 인덱스에 데이터 추가하기
다음으로, 인덱스에 데이터를 추가해요.
다음 요청은 호텔 이름 임베딩, 평점, 주차 정보가 담긴 10개의 문서를 추가해요:
POST /_bulk
{ "index": { "_index": "hotels-index", "_id": "1" } }
{"parking":true, "name":"Grand Plaza Hotel", "rating":10, "name_embedding":{"8232":7.7817574, "2882":5.847375, "3309":5.575121}}
{ "index": { "_index": "hotels-index", "_id": "2" } }
{"parking":true, "name":"Azure Beach Hotel", "rating":7, "name_embedding":{"24296":8.380939, "3509":5.5722017, "3309":5.575121}}
{ "index": { "_index": "hotels-index", "_id": "3" } }
{"parking":false, "name":"Mountain Lodge", "rating":9, "name_embedding":{"3137":5.615391, "7410":7.636689}}
{ "index": { "_index": "hotels-index", "_id": "4" } }
{"parking":true, "name":"Tropical Beach Resort", "rating":4, "name_embedding":{"7001":6.25483, "5133":6.2035937, "3509":5.5722017}}
{ "index": { "_index": "hotels-index", "_id": "5" } }
{"parking":false, "name":"Coastal Retreat", "rating":5, "name_embedding":{"5780":6.767954, "7822":7.8309207}}
{ "index": { "_index": "hotels-index", "_id": "6" } }
{"parking":true, "name":"Sunset Resort", "rating":2, "name_embedding":{"7001":6.25483, "10434":7.0848904}}
{ "index": { "_index": "hotels-index", "_id": "7" } }
{"parking":true, "name":"Crystal Beach Resort", "rating":1, "name_embedding":{"6121":6.5081306, "7001":6.25483, "3509":5.5722017}}
{ "index": { "_index": "hotels-index", "_id": "8" } }
{"parking":true, "name":"Crystal Beach Resort", "rating":9, "name_embedding":{"6121":6.5081306, "7001":6.25483, "3509":5.5722017}}
{ "index": { "_index": "hotels-index", "_id": "9" } }
{"parking":true, "name":"Azure Beach Hotel", "rating":6, "name_embedding":{"24296":8.380939, "3509":5.5722017, "3309":5.575121}}
{ "index": { "_index": "hotels-index", "_id": "10" } }
{"parking":true, "name":"Garden Court Hotel", "rating":9, "name_embedding":{"2457":4.862541, "3871":5.785374, "3309":5.575121}}
{% include copy-curl.html %}
3단계: 필터로 데이터 검색하기
이제 필터가 있는 neural sparse ANN 검색을 만들 수 있어요. neural_sparse 쿼리 절의 method_parameters 필드에 최근접 이웃을 검색하는 데 사용할 포인트, 반환할 최근접 이웃 개수(k), 제한 조건이 담긴 필터를 포함하면 돼요. 필터를 얼마나 엄격하게 적용하고 싶은지에 따라 하나의 요청에 여러 쿼리 절을 추가할 수도 있어요.
다음 요청은 이름이 "beach resort" 텍스트와 일치하고, 평점이 8 이상 10 이하이며, 주차를 제공하는 상위 세 개 호텔을 검색하는 neural sparse ANN 검색 쿼리를 생성해요:
POST /hotels-index/_search
{
"size": 3,
"query": {
"neural_sparse": {
"name_embedding": {
"query_text": "beach resort",
"method_parameters": {
"k": 3,
"filter": {
"bool": {
"must": [
{
"range": {
"rating": {
"gte": 8,
"lte": 10
}
}
},
{
"term": {
"parking": "true"
}
}
]
}
}
}
}
}
}
}
{% include copy-curl.html %}
응답은 검색 포인트에 가장 가깝고 필터 조건을 충족하는 세 개의 호텔을 반환해요:
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"max_score": 70.08806,
"hits": [
{
"_index": "hotels-index",
"_id": "8",
"_score": 70.08806,
"_source": {
"parking": true,
"name": "Crystal Beach Resort",
"rating": 9,
"name_embedding": {
"3509": 5.5722017,
"6121": 6.5081306,
"7001": 6.25483
}
}
},
{
"_index": "hotels-index",
"_id": "1",
"_score": 0,
"_source": {
"parking": true,
"name": "Grand Plaza Hotel",
"rating": 10,
"name_embedding": {
"2882": 5.847375,
"3309": 5.575121,
"8232": 7.7817574
}
}
},
{
"_index": "hotels-index",
"_id": "10",
"_score": 0,
"_source": {
"parking": true,
"name": "Garden Court Hotel",
"rating": 9,
"name_embedding": {
"2457": 4.862541,
"3309": 5.575121,
"3871": 5.785374
}
}
}
]
}
}
쿼리 외부에서 후처리 필터링하기
불리언 필터를 사용해 후처리 필터링을 적용할 수도 있어요. 이 경우 필터는 엔진 외부에서 평가되기 때문에 Lucene 엔진과 native 엔진 모두 같은 방식으로 적용돼요. 필터링은 neural sparse ANN 검색이 상위 k개 결과를 검색한 후에 발생하기 때문에, 최종적으로 반환되는 결과 개수는 k보다 훨씬 적을 수 있어요.
neural sparse ANN 검색에서 불리언 필터 사용하기
불리언 필터는 neural_sparse 쿼리와 필터를 포함하는 bool 쿼리로 구성돼요. 예를 들어 다음 쿼리는 이름이 "beach resort" 텍스트와 일치하는 호텔을 검색한 다음, 결과를 필터링해 평점이 8 이상 10 이하이고 주차를 제공하는 호텔을 반환해요:
POST /hotels-index/_search
{
"size": 3,
"query": {
"bool": {
"filter": {
"bool": {
"must": [
{
"range": {
"rating": {
"gte": 8,
"lte": 10
}
}
},
{
"term": {
"parking": "true"
}
}
]
}
},
"must": [
{
"neural_sparse": {
"name_embedding": {
"query_text": "beach resort",
"method_parameters": {
"top_n": 3,
"heap_factor": 1.0,
"k": 20
}
}
}
}
]
}
}
}
{% include copy-curl.html %}
응답에는 일치하는 호텔이 담긴 문서가 포함돼요:
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 70.08806,
"hits": [
{
"_index": "hotels-index",
"_id": "8",
"_score": 70.08806,
"_source": {
"parking": true,
"name": "Crystal Beach Resort",
"rating": 9,
"name_embedding": {
"3509": 5.5722017,
"6121": 6.5081306,
"7001": 6.25483
}
}
}
]
}
}
다음 단계
- neural sparse ANN 검색에 대한 자세한 내용은 Neural sparse ANN 검색을 참고하세요.
- Lucene 엔진과 native 엔진에 대한 자세한 내용은 엔진을 참고하세요.