Este documento descreve as práticas recomendadas para a API Search. Usamos aspas simples (‘") para delimitar strings de consulta. Dessa forma, uma consulta que contém frases com várias palavras entre aspas duplas pode ser delimitada sem confusão: 'field:"some text" some-value'
.
Fazer chamadas em lote para Index.put() e Index.delete()
Você pode passar até 200 documentos ao mesmo tempo ao adicioná-los ou exclui-los de um índice. Isso é muito mais eficiente do que manipulá-los um por vez.
Usar a posição do documento para pré-classificar documentos
Por padrão, a pesquisa retorna seus resultados por posição decrescente. Também por padrão, a API Search define a posição de cada documento em segundos, começando em 1º de janeiro de 2011. Assim, os documentos mais recentes são retornados primeiro. No entanto, se você não precisa que os documentos sejam classificados no momento em que são adicionados, você pode usar a posição para outros fins. Imagine que você tenha um aplicativo imobiliário. Os clientes geralmente preferem classificar por preço. Para uma classificação padrão eficiente, defina a posição pelo preço do imóvel.
Se você precisar de várias ordens de classificação, como do menor para o maior preço e do maior para o menor preço, pode criar um índice separado para cada ordem. Um índice teria posição = preço e o outro posição = preço-MAXINT (uma vez que a posição tem que ser positiva).
Usar a posição como a chave de classificação melhora o desempenho da pesquisa. Para especificar outras chaves de classificação, use as opções de classificação, o que limita o número de resultados da pesquisa a 10.000 documentos. Nesse caso, a ordem de classificação determinada pela posição determinará quais documentos serão incluídos na classificação. Leia sobre as opções de classificação para saber mais.
Usar campos atômicos para dados booleanos
Armazenar dados booleanos em campos numéricos é muito ineficiente. Em vez disso, use campos atômicos e atribua suas constantes favoritas (True/False, yes/no, 0/1).
Transformar negativos em positivos
Imagine que você tem um termo especial para identificar restaurantes com culinária indefinida. Se você quiser excluir esses restaurantes, use 'NOT cuisine:undefined'
como consulta. Porém, é mais caro avaliar dessa forma (em termos de operações faturáveis e tempo de computação) do que fazer o contrário, isto é, encontrar restaurantes com culinária definida. Em vez de ter um campo, "cuisine", você pode usar dois, cuisine
e cuisine_known
, sendo que o último é um campo atômico. Para os restaurantes com culinária definida, configure o primeiro campo como a culinária real e o segundo campo como "yes"
. Para os restaurantes com culinária desconhecida, defina a culinária como ""
(uma string vazia) e cuisine_known
como "no"
. Agora, para encontrar restaurantes com culinária conhecida, gere uma consulta 'cuisine_known:yes'
, que é muito mais rápida do que a negação.
Transformar disjunções em conjunções
A disjunção "OR" é uma operação dispendiosa tanto em termos de operações faturáveis quanto em termos de tempo de computação. Suponha que você queira pesquisar 'cuisine:Japanese OR cuisine:Korean'
. Uma alternativa é indexar documentos com categorias mais gerais de culinária. Nesse caso, a consulta pode ser simplificada para 'cuisine:Asian'
.
Eliminar tautologias de suas consultas
Imagine que você queira encontrar todos os restaurantes em Toronto. Supondo que seus documentos tenham apenas um único campo chamado "city", se você usar a consulta 'city:toronto AND NOT city:montreal'
, terá os mesmos resultados que 'city:toronto'
. Afinal, se a cidade estiver definida como "toronto"
, não poderá ser definida como "montreal"
. A segunda consulta é muito mais rápida, porque envolve apenas um termo. A primeira consulta executa três etapas: primeiro encontra uma lista de documentos em que a cidade está definida como "toronto" e, em seguida, encontra uma lista de todas as cidades em que o campo "city" não está definido como "montreal" e, finalmente, calcula a interseção das duas listas.
Limitar o intervalo antes de classificar
Imagine que seu aplicativo armazene informações sobre restaurantes de todo o mundo, e você gostaria de mostrar os restaurantes mais próximos do usuário atual. Uma maneira de fazer isso é classificar os documentos correspondentes pela distância da localização do usuário. Porém, se você tiver 1 milhão de restaurantes, executar uma consulta como 'cuisine:japanese'
com a expressão de classificação distance(geopoint(x, y), restaurant_loc) irá demorar muito. É uma boa ideia adicionar filtros a uma consulta para que você comece com um conjunto mais relevante de documentos selecionados para classificar. Uma solução é criar categorias geográficas, como país, estado e cidade. Você pode inferir a cidade e o estado pela localização do usuário. Depois, sua consulta se tornará 'cuisine:japanese AND city:<user-city>'
. Muito provavelmente, você não precisará mais classificar 1 milhão de documentos.
Usar categorias restritas para evitar ou minimizar a classificação
Se você usar a posição para classificar os restaurantes por preço, poderá criar um campo price_range
que contenha categorias de preço: price_0_10
, price_11_20
, price_21_30
, price_31_40
, price_41_lots
. Em seguida, você poderá encontrar todos os restaurantes que custam entre US$ 21 e US$ 40 sem nenhuma classificação usando a consulta 'price_range:price_21_30 OR price_range:price_31_40'
. Em muitos casos, as categorias apropriadas não são tão claras, mas com essa técnica, é possível rejeitar uma grande quantidade de documentos antes de restringir a pesquisa com consultas caras, como '... AND price>25 AND price<35'
.
Não pontuar correspondências, a menos que necessário
A pontuação é usada para indicar o nível de correspondência de determinado documento a uma consulta. No entanto, a menos que você pretenda classificar pelo valor da pontuação, não a solicite. Isso só tornará sua pesquisa mais lenta.