Skip to content

Nested Field로 다중 벡터 다루기

벡터 기반 검색 시스템을 구축할 때, 하나의 문서가 여러 개의 구성 요소(예: 문단, 이미지, 설명 등)로 이뤄져 있다면 각 요소마다 벡터를 생성하여 문서 내에 함께 저장하고 싶을 수 있다.

OpenSearch는 이를 위해 nested 필드 기반 벡터 검색 기능을 제공한다.

1. Nested Field란?

  • 하나의 문서 내에 배열 형태로 객체를 포함할 수 있는 구조

  • 각 객체 안에 knn_vector를 포함하여 다수의 벡터를 한 문서에 저장 가능

  • 검색 시 각 문서의 가장 유사한 벡터만 기준으로 스코어 결정

2. 인덱스 생성 예시

PUT my-knn-index-1
{
  "settings": {
    "index": {
      "knn": true
    }
  },
  "mappings": {
    "properties": {
      "nested_field": {
        "type": "nested",
        "properties": {
          "my_vector": {
            "type": "knn_vector",
            "dimension": 3,
            "space_type": "l2",
            "method": {
              "name": "hnsw",
              "engine": "lucene",
              "parameters": {
                "ef_construction": 100,
                "m": 16
              }
            }
          },
          "color": {
            "type": "text",
            "index": false
          }
        }
      }
    }
  }
}

3. 문서 색인 예시

PUT _bulk?refresh=true
{ "index": { "_index": "my-knn-index-1", "_id": "1" } }
{
  "nested_field": [
    { "my_vector": [1,1,1], "color": "blue" },
    { "my_vector": [2,2,2], "color": "yellow" },
    { "my_vector": [3,3,3], "color": "white" }
  ]
}
{ "index": { "_index": "my-knn-index-1", "_id": "2" } }
{
  "nested_field": [
    { "my_vector": [10,10,10], "color": "red" },
    { "my_vector": [20,20,20], "color": "green" },
    { "my_vector": [30,30,30], "color": "black" }
  ]
}

4. 기본 벡터 검색 쿼리

GET my-knn-index-1/_search
{
  "query": {
    "nested": {
      "path": "nested_field",
      "query": {
        "knn": {
          "nested_field.my_vector": {
            "vector": [1, 1, 1],
            "k": 2
          }
        }
      }
    }
  }
}

이 쿼리는 벡터 유사도가 높은 상위 2개 벡터가 포함된 문서를 반환
→ 벡터가 모두 문서 1에 있더라도 서로 다른 문서가 포함될 수 있음

5. Inner Hits로 매칭된 Nested 객체 확인

기본적으로 어떤 하위 객체가 매칭되었는지 알 수 없다. inner_hits를 통해 해당 정보를 확인할 수 있다.

GET my-knn-index-1/_search
{
  "_source": false,
  "query": {
    "nested": {
      "path": "nested_field",
      "query": {
        "knn": {
          "nested_field.my_vector": {
            "vector": [1,1,1],
            "k": 2
          }
        }
      },
      "inner_hits": {
        "_source": false,
        "fields": ["nested_field.color"]
      }
    }
  }
}

6. 모든 Nested 벡터 점수 확인 (확장 검색)

기본 설정에서는 문서 내에서 가장 높은 벡터 점수만 사용한다. 모든 벡터 스코어를 반영하려면 expand_nested_docs: true를 설정하고,
문서 점수로 어떤 값을 사용할지 score_mode로 지정합니다.

"score_mode": "max" // 또는 "avg", "sum", "none"
"knn": {
  "nested_field.my_vector": {
    "vector": [1,1,1],
    "k": 2,
    "expand_nested_docs": true
  }
}

7. Top-level 또는 Nested 필드 필터링

knn 쿼리에 filter를 추가하여 문서 단위로 필터링할 수 있다.

GET my-knn-index-1/_search
{
  "query": {
    "nested": {
      "path": "nested_field",
      "query": {
        "knn": {
          "nested_field.my_vector": {
            "vector": [1,1,1],
            "k": 3,
            "filter": {
              "term": {
                "parking": true
              }
            }
          }
        }
      }
    }
  }
}

위 예시에서는 parking: true 조건을 만족하는 문서만 벡터 유사도로 검색

요약

기능 설명
nested_field 벡터 여러 벡터를 하나의 문서에 저장 가능
inner_hits 어떤 하위 객체가 매칭되었는지 확인
expand_nested_docs 모든 벡터 점수 고려 가능
filter 벡터 검색 시 조건 필터 가능 (top-level 및 nested)