조건부 필터

조건부 필터 (Conditional filters)

검색 결과를 어떤 조건으로 걸러낼지 정하는 게 바로 조건부 필터예요. 객체 조회(Object-level), 집계(Aggregate), 배치 삭제 같은 질의에 조건부 필터를 붙일 수 있는데, 여기 쓰이는 연산자를 where 필터라고 불러요. 필터 하나가 조건 하나로 이뤄질 수도 있고, AndOr로 여러 조건을 묶을 수도 있어요.

출처: Weaviate 공식 문서 — Conditional filters

단일 조건 (operand)

대수적 조건 하나하나를 "operand"라고 불러요. operand마다 필요한 요소는 세 가지예요.

  • 연산자 타입 (operator type)
  • 프로퍼티 경로 (property path)
  • 값과 값의 타입 (value 및 value type)

예를 들어 아래 필터는 wordCount1000보다 큰(GreaterThan) Article 클래스 객체만 허용해요.

# Python 클라이언트 예시 — wordCount가 1000보다 큰 Article만

필터 구조와 동작

Equal 필터의 다중 단어 질의

where 필터에서 Equal 연산자를 다중 단어 프로퍼티에 쓰면 그 동작이 프로퍼티의 토큰화(tokenization) 설정에 따라 달라져요. 사용 가능한 토큰화 종류의 차이는 스키마 프로퍼티 토큰화 섹션을 참고하면 돼요.

Like 필터의 성능

Like 필터는 그 프로퍼티의 역인덱스 전체를 순회해요. 그래서 검색 시간이 데이터셋 크기에 따라 선형적으로 늘어나고, 데이터가 크면 느려질 수 있어요.

Like의 와일드카드 리터럴 매칭

현재 Like 필터는 와일드카드 문자(?, *)를 리터럴 문자로 매칭하지 못해요. 예를 들어 car*에 정확히 매칭하면서 car, care, carpet은 제외하는 식의 검색은 지금은 불가능해요. Weaviate가 알고 있는 알려진 제한 사항이고, 향후 버전에서 해결될 수 있어요.

ContainsAny / ContainsAll / ContainsNone

이 세 연산자는 텍스트를 배열로 취급해요. 텍스트를 선택한 토큰화 방식에 따라 토큰 배열로 쪼갠 뒤, 그 배열을 대상으로 검색을 수행해요.

  • ContainsAny: 입력 배열의 값 중 하나라도 있는 객체를 반환해요. 예를 들어 languages_spoken(text 타입)에 값 ["Chinese", "French", "English"]ContainsAny 질의를 하면, 그 언어 중 하나라도 말하는 사람이 결과로 나와요.
  • ContainsAll: 값을 전부 포함하는 객체만 반환해요.
  • ContainsNone: 값 중 어느 것도 없는 객체를 반환해요. 스페인어만 말하는 사람이 languages_spoken["Chinese", "French", "English"]ContainsNone 질의를 하면 결과에 포함되는 식이에요.

주의할 점이 있어요. REST API로 배치 삭제에 이 연산자들을 쓸 때는 프로퍼티 데이터 타입에 맞는 배열 접미사 인자(valueTextArray, valueIntArray 등)로 값을 지정해야 해요. 검색에서 쓰는 단일 인자(valueText, valueInt)와는 달라요.

또 geo 좌표와 전화번호 프로퍼티는 이 연산자들을 지원하지 않아요. geo 필터링은 WithinGeoRange를 써야 해요.

필터 성능 개선

가끔 필터 아키텍처와 데이터 구조가 어긋나서 필터 성능이 느려질 수 있어요. 예를 들어 프로퍼티의 카디널리티(고유 값 개수)가 매우 크면 범위 기반 필터가 느려질 수 있어요.

필터 성능이 느리다면 몇 가지 옵션이 있어요.

  • where 연산자에 조건을 더 추가해 질의를 더 좁힌다.
  • 질의에 limit 파라미터를 추가한다.
  • 범위 기반 필터링이 필요한 프로퍼티에 indexRangeFilters를 구성한다. 역인덱스 파라미터는 컬렉션을 만들 때 설정할 수 있어요.

특수 케이스

id로 필터링

객체 id를 기준으로도 필터를 걸 수 있어요.

속성 길이로 필터링 (len())

프로퍼티 길이를 기준으로 필터링할 수 있어요. 지원 범위는 이래요.

  • 문자열·텍스트: 문자 수 (유니코드 문자인 도 한 글자로 침)
  • 숫자, 불리언, geo 좌표, 전화번호, 데이터 블롭은 지원하지 않아요.

path 값은 프로퍼티 이름을 len()으로 감싼 문자열이에요. 예를 들어 title 프로퍼티 길이로 필터링하려면 path: ["len(title)"]을 써요. title 길이가 10보다 큰 Article을 찾으려면 이렇게 해요.

{
  Get {
    Article (
      where: {
        operator: GreaterThan,
        valueInt: 10,
        path: ["len(title)"]
      }
    )
  }
}

지원 연산자는 (not) equalgreater/less than (equal)이고, 값은 0 이상이어야 해요. 속성 길이로 필터링하려면 대상 클래스가 길이 인덱싱을 하도록 구성되어 있어야 해요.

크로스 레퍼런스로 필터링

크로스 레퍼런스(beacon)의 프로퍼티 값으로도 검색할 수 있어요. 예를 들어 inPublication이 "New Yorker"로 설정된 Article 객체를 선택하는 필터 같은 방식이에요.

중첩 객체 프로퍼티로 필터링 (Preview)

Weaviate v1.38부터 미리보기로 제공되는 기능이에요. 서버에서 WEAVIATE_PREVIEW_NESTED_FILTERING=on으로 게이트되고, object/object[] 프로퍼티 안쪽의 leaf를 대상으로 where 필터를 걸 수 있어요. path는 점으로 이어진 경로를 담은 단일 요소 배열이고, [N]은 세그먼트를 배열 인덱스에 고정해요. 예를 들어 "같은 차가 Toyota이면서 red인" 같은 같은 요소 상관(correlation)을 다룰 수 있어요.

geo 좌표로 필터링

geo 좌표는 Where 필터의 특수 케이스예요. 이 필터는 Get{} 함수에서만 지원돼요. geoCoordinates 프로퍼티 타입을 설정했다면 킬로미터 단위의 반경 안을 검색할 수 있어요. geo 좌표는 내부적으로 벡터 인덱스를 사용한다는 점이 특징이고, 현재 geo 좌표 필터링은 원점에서 가까운 800개 결과로 제한되며, 이후 다른 필터 조건과 검색 파라미터로 더 줄어들 수 있어요.

null 상태로 필터링

필터로 null 상태를 지정하려면 대상 클래스가 이를 인덱싱하도록 구성되어 있어야 해요.

더 알아보기