필터

필터 (Filters)

검색 결과를 그냥 받기보다, 특정 조건에 맞는 객체만 포함하거나 제외하고 싶을 때가 있죠. 필터는 바로 그 일을 합니다. 벡터 검색·키워드 검색·하이브리드 검색 어디에나 붙일 수 있어서, 결과 집합을 원하는 대로 좁히는 가장 기본적인 도구예요.

필터 연산자 전체 목록은 API 레퍼런스 페이지에서 확인할 수 있습니다.

출처: 공식문서

단일 조건 필터

쿼리에 filter 하나를 추가해 결과 집합을 제한합니다.

from weaviate.classes.query import Filter

jeopardy = client.collections.use("JeopardyQuestion")
response = jeopardy.query.fetch_objects(
    filters=Filter.by_property("round").equal("Double Jeopardy!"),
    limit=3
)

여러 조건 필터

두 개 이상의 조건을 조합할 때는 조건 간 관계를 And, Or, Not으로 정의합니다.

v4 파이썬 클라이언트는 any_of/all_of와 함께 &(AND), |(OR) 연산자도 제공해요.

# `&` / `|` 연산자로 쌍 조합
filters=(
    Filter.by_property("round").equal("Double Jeopardy!") &
    Filter.by_property("points").less_than(600) &
    Filter.not_(Filter.by_property("answer").equal("Yucatan"))
)

# any_of: 아래 중 하나라도 만족하면 매칭 (| 로 결합)
filters=(
    Filter.any_of([
        Filter.by_property("points").greater_or_equal(700),
        Filter.by_property("points").less_than(500),
        Filter.by_property("round").equal("Double Jeopardy!"),
    ])
)

# all_of: 아래를 모두 만족해야 매칭 (& 로 결합)
filters=(
    Filter.all_of([
        Filter.by_property("points").greater_than(300),
        Filter.by_property("points").less_than(700),
        Filter.by_property("round").equal("Double Jeopardy!"),
    ])
)

JS/TS v3 API에서는 Filters.and/Filters.or 메서드로 조합하고, Filters.not으로 논리 부정을 씁니다. 가변 인자를 받으므로 배열은 전개(spread)해서 넘겨야 해요(Filters.and(...fs)).

And/Or로 조건 그룹핑·중첩

복합 논리를 표현하려면 And/Or 연산자로 조건을 그룹핑하고 중첩합니다.

response = jeopardy.query.fetch_objects(
    filters=Filter.by_property("answer").like("*bird*") &
            (Filter.by_property("points").greater_than(700) | Filter.by_property("points").less_than(300)),
    limit=3
)

중첩 필터를 만들려면: 바깥 operatorAnd/Or로 설정 → operands 추가 → operand 안에서 operatorAnd/Or로 설정해 중첩 그룹 추가 → 필요한 만큼 operands 추가.

검색 연산자와 결합

필터는 nearXXX, hybrid, bm25 같은 검색 연산자와 함께 동작합니다.

response = jeopardy.query.near_text(
    query="fashion icons",
    filters=Filter.by_property("points").greater_than(200),
    limit=3
)

ContainsAny · ContainsAll · ContainsNone

이 연산자들은 텍스트 프로퍼티에 값 배열을 입력으로 받습니다.

  • ContainsAny: 프로퍼티가 배열 값 중 하나라도(하나 이상) 포함하면 매칭.
  • ContainsAll: 프로퍼티가 배열 값을 전부 포함하면 매칭.
  • ContainsNone: 프로퍼티가 배열 값 중 아무것도 포함하지 않으면 매칭.
token_list = ["australia", "india"]
response = jeopardy.query.fetch_objects(
    filters=Filter.by_property("answer").contains_any(token_list),
    limit=3
)

token_list = ["blue", "red"]
response = jeopardy.query.fetch_objects(
    filters=Filter.by_property("question").contains_all(token_list),
    limit=3
)

부분 일치(Like) 필터

객체 프로퍼티가 text거나 object ID 같은 text-유사 데이터 타입이면, Like로 부분 텍스트 매칭을 할 수 있어요.

response = jeopardy.query.fetch_objects(
    filters=Filter.by_property("answer").like("*ala*"),
    limit=3
)
  • * 와일드카드는 0개 이상 문자를 매칭합니다.
  • ?정확히 1개 문자를 매칭합니다.
  • 현재 Like 필터는 와일드카드 자체(?, *)를 리터럴 문자로는 매칭하지 못합니다.

크로스 레퍼런스로 필터링

크로스 레퍼런스된 객체의 프로퍼티로 필터링하려면, 필터에 컬렉션 이름을 추가합니다.

from weaviate.classes.query import Filter, QueryReference

response = jeopardy.query.fetch_objects(
    filters=Filter.by_ref(link_on="hasCategory").by_property("title").like("*Sport*"),
    return_references=QueryReference(link_on="hasCategory", return_properties=["title"]),
    limit=3
)

지리 좌표로 필터

지리 좌표 프로퍼티는 within_geo_range로 반경 필터링합니다. 거리 단위는 미터예요.

from weaviate.classes.query import GeoCoordinate

response = publications.query.fetch_objects(
    filters=(
        Filter
        .by_property("headquartersGeoLocation")
        .within_geo_range(
            coordinate=GeoCoordinate(latitude=52.39, longitude=4.84),
            distance=1000  # meters
        )
    )
)

DATE 데이터 타입으로 필터

DATE 타입 프로퍼티는 RFC 3339 타임스탬프 또는 Python datetime 같은 클라이언트 호환 타입으로 지정합니다.

from datetime import datetime, timezone

filter_time = datetime(2022, 6, 10).replace(tzinfo=timezone.utc)
# RFC 3339 문자열도 가능: filter_time = "2022-06-10T00:00:00.00Z"

response = collection.query.fetch_objects(
    limit=3,
    filters=Filter.by_property("some_date").greater_than(filter_time),
)

메타데이터로 필터

필터는 object id, 프로퍼티 길이, 타임스탬프 같은 메타데이터 프로퍼티에서도 동작합니다.

객체 id 기준

target_id = "00037775-1432-35e5-bc59-443baaef7d80"
response = collection.query.fetch_objects(
    filters=Filter.by_id().equal(target_id)
)

객체 타임스탬프 기준

이 필터는 property timestamp 인덱싱이 필요합니다.

filter_time = datetime(2020, 1, 1).replace(tzinfo=timezone.utc)
response = collection.query.fetch_objects(
    limit=3,
    filters=Filter.by_creation_time().greater_than(filter_time),
    return_metadata=MetadataQuery(creation_time=True)
)

프로퍼티 길이 기준

property length 인덱싱이 필요합니다.

length_threshold = 20
response = collection.query.fetch_objects(
    limit=3,
    filters=Filter.by_property("answer", length=True).greater_than(length_threshold),
)

null 상태 기준

property null state 인덱싱이 필요합니다.

response = collection.query.fetch_objects(
    limit=3,
    filters=Filter.by_property("country").is_none(True)  # country가 null인 객체 찾기
)

중첩 객체 프로퍼티 필터링

:::caution 프리뷰 기능 Weaviate v1.38부터 프리뷰로 제공되며, 서버에서 WEAVIATE_PREVIEW_NESTED_FILTERING=on 환경변수로 켭니다. 경로 문법과 연산자 의미는 안정적이지만 GA 전에 디스크 인코딩이 바뀔 수 있어요. :::

object/object[] 프로퍼티는 자체 중첩 스키마를 가집니다. 중첩 객체 안의 값을 필터링하려면 부모 프로퍼티에서 비교할 리프까지 내려가는 점(.) 구분 단일 경로를 사용합니다.

[N]은 세그먼트를 배열 인덱스(0부터)에 고정합니다.

경로 의미
cars.make cars 배열의 어떤 요소든 make를 가지면 매칭
cars[0].make 첫 번째 차의 make (위치 고정)
cars.tires.width 어떤 차의 어떤 타이어든 (두 단계 object[] 재귀)
cars[1].tires[2].brand 두 번째 차의 세 번째 타이어 brand
  • [N]이 붙은 세그먼트는 object[](배열)여야 해요.
  • 중간 모든 세그먼트는 object 또는 object[]여야 하며 스칼라를 통한 피벗은 불가능합니다.
  • 리프는 지원되는 스칼라 타입이면 무엇이든 가능합니다.
  • 두 리프 필터를 And로 결합하면 부모 배열의 같은 요소가 두 조건을 모두 만족해야 매칭됩니다. (요소 상관관계)
  • object/object[] 세그먼트를 가리키는 경로는 IsNull과만 유효합니다(하위 객체 존재 여부).

제한 사항

  • 리프 데이터 타입: text, int, number, boolean, date, uuid와 배열 변형. blob, blobHash, geoCoordinates, phoneNumber, 크로스 레퍼런스(cref)는 중첩 필터링에 허용되지 않습니다.
  • IndexFilterable 필요: 중첩 필터링은 각 리프의 filterable 역파일 인덱스를 사용해요. IndexRangeFilters/IndexSearchable 플래그는 아직 중첩 검색기에서 사용되지 않습니다.
  • 토큰화 중요: 중첩 text 리프도 플랫 프로퍼티와 같은 토큰화 옵션을 사용해요. 이름·코드·식별자 정확 일치 필터는 리프에 tokenization: field를 설정하세요.
  • 참조 경로 vs 중첩 경로: 참조 경로 필터는 여러 요소 Path(["inCity", "City", "name"])이고, 중첩 경로는 단일 요소 경로(점 포함, ["cars.make"])입니다.

필터 성능 개선

필터가 느리면 limit 파라미터를 추가하거나 where 연산자를 추가해 데이터셋 크기를 제한해 보세요.

더 알아보기 (Learn more)