이 문서에서는 Search API 관련 권장사항을 설명합니다. 또한 문서 전체에서 쿼리 문자열을 구분할 때 작은따옴표('')를 사용합니다. 이렇게 함으로써 'field:"some text" some-value'
와 같이 큰따옴표로 묶인 어구가 여러 개 포함된 쿼리를 혼동 없이 구분할 수 있습니다.
Index.put() 및 Index.delete() 호출을 일괄 처리하기
색인에 문서를 추가하거나 삭제할 때 한 번에 최대 200개의 문서를 전달할 수 있습니다. 이렇게 하면 한 번에 하나씩 처리하는 것보다 훨씬 더 효율적입니다.
문서 순위를 사용하여 문서를 사전에 정렬하기
기본적으로, 검색결과는 내림차순으로 정렬됩니다. 그리고 Search API는 기본적으로 모든 문서의 순위를 2011년 1월 1일 이후로 경과된 초 수로 설정합니다. 따라서 가장 최신 문서가 제일 처음 표시됩니다. 그러나 문서를 추가된 시간을 기준으로 정렬할 필요가 없다면 순위를 다른 목적으로 사용할 수 있습니다. 부동산 애플리케이션이 있다고 가정해 보겠습니다. 고객이 가장 원하는 것은 가격을 기준으로 한 분류입니다. 기본 정렬의 효율성을 위해서 주택 가격에 따라 순위를 설정할 수 있을 것입니다.
낮은 가격에서 높은 가격 또는 높은 가격에서 낮은 가격 등 여러 가지 정렬 순서가 필요한 경우 각 순서마다 별도의 색인을 만들 수 있습니다. 어떤 색인은 순위 = 가격, 그리고 또 다른 색인은 순위 = MAXINT-가격(순위는 양수여야 하므로)을 가질 것입니다.
순위를 정렬 키로 사용하면 검색 성능이 개선됩니다. 다른 정렬 키를 지정하려면 정렬 옵션을 사용해야 하는데, 이 때 검색결과의 수가 문서 10,000개로 제한됩니다. 이 경우 순위에 의해 결정된 정렬 순서가 어떤 문서가 정렬에 포함될지를 결정합니다. 자세한 내용은 정렬 옵션을 읽어보세요.
부울 데이터에 atom 필드 사용하기
부울 데이터를 숫자 필드에 저장하는 것은 매우 비효율적입니다. 대신 atom 필드를 사용하고 선호하는 상수(True/False, yes/no, 0/1)를 할당하세요.
부정 검색을 긍정 검색으로 바꾸기
어떤 요리를 제공하는지 알 수 없는 레스토랑을 구분해야 하는 특수한 조건을 가정해 보겠습니다. 이러한 레스토랑을 제외하려면 'NOT cuisine:undefined'
를 쿼리로 사용하면 됩니다. 하지만 이 방법은 그 반대의 경우, 즉 어떤 요리를 제공하는지 아는 레스토랑을 찾는 것보다 청구 가능 작업과 계산 시간이라는 모든 측면에서 평가 비용이 더 비쌉니다. 따라서 cuisine이라는 필드 하나가 아닌 cuisine
과 cuisine_known
이라는 필드 2개를 사용할 수 있습니다(두 번째는 atom 필드). 어떤 요리를 제공하는지 아는 레스토랑의 경우 첫 번째 필드를 실제 요리로 설정하고 두 번째 필드를 "yes"
로 설정합니다. 어떤 요리를 제공하는지 알 수 없는 레스토랑의 경우 요리를 ""
(빈 문자열)으로 설정하고 cuisine_known
을 "no"
로 설정합니다. 이제 'cuisine_known:yes'
쿼리를 실행하면 어떤 요리를 제공하는지 아는 식당을 찾을 수 있으며, 이렇게 하면 검색이 부정 검색보다 훨씬 더 빠릅니다.
논리합을 논리곱으로 바꾸기
'OR' 논리합은 청구 가능 작업과 계산 시간이라는 모든 측면에서 비용이 많이 드는 연산입니다 'cuisine:Japanese OR cuisine:Korean'
을 검색한다고 가정해 보겠습니다. 한 가지 대안은 문서에 더 일반적인 범주의 요리로 색인을 생성하는 것입니다. 이 경우 쿼리는 'cuisine:Asian'
으로 더 간소화될 수 있습니다.
쿼리에서 유의어 반복을 없애기
토론토에 있는 모든 식당을 찾으려고 한다고 가정해 보겠습니다. 문서에 'city'라고 하는 단일 필드만 있는 경우 쿼리 'city:toronto AND NOT city:montreal'
을 사용하면 'city:toronto'
와 같은 결과를 얻을 수 있습니다. 도시가 "toronto"
로 설정된 경우 "montreal"
로 설정할 수 없습니다. 두 번째 쿼리는 단어가 하나뿐이므로 훨씬 더 빨리 실행됩니다. 첫 번째 쿼리는 3가지 단계를 수행합니다. 첫째, 도시가 'toronto'로 설정된 문서 목록을 찾고, 그 다음에 도시가 'montreal'로 설정되지 않은 모든 도시의 목록을 찾고, 마지막으로 두 목록의 중첩되는 부분을 계산합니다.
정렬하기 전에 범위 좁히기
애플리케이션이 전 세계의 식당에 관한 정보를 저장하고 있고 현재 사용자에게 가장 가까이 있는 식당을 보여주려고 한다고 가정해 보겠습니다. 한 가지 방법은 일치하는 여러 문서를 사용자 위치와의 거리를 기준으로 정렬하는 것입니다. 하지만 레스토랑이 1,000,000개 있을 경우 'cuisine:japanese'
와 같은 쿼리를 정렬 표현식 distance(geopoint(x, y), restaurant_loc)와 함께 실행하면 시간이 오래 걸립니다. 그러므로 쿼리에 여러 가지 필터를 추가하여 좀더 핵심적인 문서들을 추려낸 뒤 정렬을 실행하는 것이 좋습니다. 한 가지 해결책은 국가, 주, 도시(사용자의 위치에서 주와 도시 추론 가능)와 같은 지리적 범주를 만드는 것입니다. 그러면 쿼리는 'cuisine:japanese AND city:<user-city>'
가 됩니다. 이렇게 하면 더 이상 문서 1,000,000개를 정렬할 필요가 없을 것입니다.
좁은 범주를 사용하여 정렬 방지 또는 최소화
순위를 사용하여 레스토랑을 가격별로 정렬할 경우 가격 범주(price_0_10
, price_11_20
, price_21_30
, price_31_40
, price_41_lots
)를 포함하는 price_range
필드를 만들 수 있습니다. 그러면 쿼리 'price_range:price_21_30 OR price_range:price_31_40'
을 사용하여 정렬 작업을 수행하지 않고도 가격이 $21~$40인 모든 레스토랑을 찾을 수 있습니다. 알맞은 범주가 명확하지 않은 경우가 많지만 이 기법을 사용하면 '... AND price>25 AND price<35'
와 같은 값비싼 쿼리를 사용하여 검색을 고르기 전에 다수의 문서를 거부할 수 있습니다.
필요하지 않은 경우 일치율에 점수 매기지 않기
점수는 쿼리에 대한 해당 문서의 일치율을 나타내는 데 사용됩니다. 하지만 점수를 기준으로 정렬할 것이 아니라면 점수를 요청하지 마세요. 검색 처리 속도만 느려집니다.