A API Search fornece um modelo para
indexar documentos que contêm dados estruturados. Pode pesquisar um índice e
organizar e apresentar os resultados da pesquisa. A API suporta a correspondência de texto completo em campos de strings. Os documentos e os índices são guardados num armazenamento persistente separado
otimizado para operações de pesquisa. A API Search pode indexar qualquer número de documentos. O App Engine Datastore pode ser mais adequado para aplicações que precisam de obter conjuntos de resultados muito grandes. Para ver o conteúdo do pacote search
, consulte a search
referência do pacote.
Vista geral
A API Search baseia-se em quatro conceitos principais: documentos, índices, consultas e resultados.
Documentos
Um documento é um objeto com um ID exclusivo e uma lista de campos que contêm dados do utilizador. Cada campo tem um nome e um tipo. Existem vários tipos de campos, identificados pelos tipos de valores que contêm:
- Campo Atom: uma string de carateres indivisível.
- Campo de texto: uma string de texto simples que pode ser pesquisada palavra a palavra.
- Campo HTML: uma string que contém etiquetas de marcação HTML. Só é possível pesquisar o texto fora das etiquetas de marcação.
- Campo de número: um número de vírgula flutuante.
- Campo de tempo: um valor
time.Time
, que é armazenado com precisão de milissegundos. - Campo de geoponto: um objeto de dados com coordenadas de latitude e longitude.
O tamanho máximo de um documento é de 1 MB.
Índices
Um índice armazena documentos para obtenção. Pode obter um único documento pelo respetivo ID, um intervalo de documentos com IDs consecutivos ou todos os documentos num índice. Também pode pesquisar um índice para obter documentos que satisfaçam determinados critérios em campos e respetivos valores, especificados como uma string de consulta. Pode gerir grupos de documentos colocando-os em índices separados.
Não existe limite para o número de documentos num índice nem para o número de índices que pode usar. O tamanho total de todos os documentos num único índice está limitado a 10 GB por predefinição. Os utilizadores com a função Administrador do App Engine podem enviar um pedido a partir da página Pesquisa do App Engine da Google Cloud consola para aumentar o tamanho até 200 GB.
Consultas
Para pesquisar um índice, cria uma consulta, que tem uma string de consulta e, possivelmente, algumas opções adicionais. Uma string de consulta especifica condições para os valores de um ou mais campos de documentos. Quando pesquisa um índice, recebe apenas os documentos no índice com campos que satisfazem a consulta.
A consulta mais simples, por vezes denominada "pesquisa global", é uma string que contém apenas valores de campos. Esta pesquisa usa uma string que procura documentos que contenham as palavras "rosa" e "água":
Esta pesquisa procura documentos com campos de data que contenham a data 4 de julho de 1776 ou campos de texto que incluam a string "1776-07-04":
Uma string de consulta também pode ser mais específica. Pode conter um ou mais termos, cada um com o nome de um campo e uma restrição no valor do campo. A forma exata de um termo depende do tipo de campo. Por exemplo, supondo que existe um campo de texto denominado "Produto" e um campo numérico denominado "Preço", eis uma string de consulta com dois termos:
As opções de consulta, como o nome indica, não são obrigatórias. Permitem uma variedade de funcionalidades:
- Controlar o número de documentos devolvidos nos resultados da pesquisa.
- Especifique os campos de documentos a incluir nos resultados. A predefinição é incluir todos os campos do documento original. Pode especificar que os resultados incluem apenas um subconjunto de campos (o documento original não é afetado).
- Ordene os resultados.
- Crie "campos calculados" para documentos com
FieldExpressions
e campos de texto abreviados com fragmentos. - Suporte a paginação nos resultados da pesquisa devolvendo apenas uma parte dos documentos correspondentes em cada consulta (através de deslocamentos e cursores)
Recomendamos que registe as strings de consulta na sua aplicação se quiser manter um registo das consultas que foram executadas.
Resultados da pesquisa
Uma chamadaSearch
devolve um valor Iterator
, que pode ser usado para devolver o conjunto completo de documentos correspondentes.
Material de formação adicional
Além desta documentação, pode ler a aula de formação em duas partes sobre a API Search na Google Developers Academy. (Embora a classe use a API Python, pode achar útil a discussão adicional dos conceitos de pesquisa.)
Documentos e campos
Os documentos são representados por estruturas Go, que incluem uma lista de campos. Os documentos também podem ser representados por qualquer tipo que implemente a interfaceFieldLoadSaver
.
Identificador do documento
Cada documento num índice tem de ter um identificador de documento exclusivo ou docID
.
O identificador pode ser usado para obter um documento a partir de um índice sem realizar uma pesquisa. Por predefinição, a API Search gera automaticamente um docID
quando
é criado um documento. Também pode especificar o docID
quando
cria um documento. Um docID
tem de conter apenas carateres ASCII visíveis e imprimíveis (códigos ASCII de 33 a 126 inclusive) e não ter mais de 500 carateres. Um identificador de documento não pode começar com um ponto de exclamação ("!")
e não pode começar nem terminar com dois sublinhados ("__").
Embora seja conveniente criar identificadores de documentos únicos legíveis e significativos, não pode incluir o elemento docID
numa pesquisa. Considere este cenário: tem um índice com documentos que representam peças, usando o número de série da peça como o docID
. Será muito eficiente obter o documento para qualquer peça única, mas será impossível pesquisar um intervalo de números de série juntamente com outros valores de campos, como a data de compra. Armazenar o número de série num campo atom resolve o problema.
Campos de documentos
Um documento contém campos com um nome, um tipo e um único valor desse tipo. Dois ou mais campos podem ter o mesmo nome, mas tipos diferentes. Por exemplo, pode definir dois campos com o nome "age": um com um tipo de texto (o valor "twenty-two") e o outro com um tipo de número (o valor 22).
Nomes dos campos
Os nomes dos campos são sensíveis a maiúsculas e minúsculas e só podem conter carateres ASCII. Têm de começar por uma letra e podem conter letras, dígitos ou um sublinhado. O nome de um campo não pode ter mais de 500 carateres.
Campos com vários valores
Um campo só pode conter um valor, que tem de corresponder ao tipo do campo. Os nomes dos campos não têm de ser exclusivos. Um documento pode ter vários campos com o mesmo nome e o mesmo tipo, o que é uma forma de representar um campo com vários valores. (No entanto, os campos de data e número com o mesmo nome não podem ser repetidos.) Um documento também pode conter vários campos com o mesmo nome e tipos de campos diferentes.
Tipos de campos
Existem três tipos de campos que armazenam strings de carateres. Coletivamente, referimo-nos a eles como campos de string:
- Campo de texto: uma string com um comprimento máximo de 1024**2 carateres.
- Campo HTML: uma string formatada em HTML com um comprimento máximo de 1024**2 carateres.
- Campo Atom: uma string com um comprimento máximo de 500 carateres.
Existem também três tipos de campos que armazenam dados não textuais:
- Campo numérico: um valor de vírgula flutuante de precisão dupla entre -2 147 483 647 e 2 147 483 647.
- Campo de tempo: um valor
time.Time
, que é armazenado com precisão de milissegundos. - Campo geoponto: um ponto na Terra descrito por coordenadas de latitude e longitude.
Os tipos de campos de string são o tipo string
incorporado do Go e os tipos search
HTML
e Atom
do pacote. Os campos numéricos são representados com o tipo float64
incorporado do Go, os campos de tempo usam o tipo time.Time
e os campos de geoponto usam o tipo GeoPoint
do pacote appengine
.
Tratamento especial de campos de texto e hora
Quando um documento com campos de hora, texto ou HTML é adicionado a um índice, ocorre um processamento especial. É útil compreender o que se passa "nos bastidores" para usar a API Search de forma eficaz.
Tokenizar campos de string
Quando um campo de texto ou HTML é indexado, o respetivo conteúdo é transformado em tokens. A string é dividida em tokens sempre que aparecem espaços em branco ou carateres especiais (sinais de pontuação, símbolo de cardinal, barra invertida, etc.). O índice vai incluir uma entrada para cada token. Isto permite-lhe pesquisar palavras-chave e expressões que compreendem apenas parte do valor de um campo. Por exemplo, uma pesquisa por "escuro" vai corresponder a um documento com um campo de texto que contenha a string "era uma noite escura e tempestuosa", e uma pesquisa por "tempo" vai corresponder a um documento com um campo de texto que contenha a string "este é um sistema em tempo real".
Nos campos HTML, o texto nas etiquetas de marcação não é tokenizado, pelo que um documento com um campo HTML que contenha it was a <strong>dark</strong> night
corresponde a uma pesquisa de "noite", mas não de "forte". Se quiser poder pesquisar texto de marcação, armazene-o num campo de texto.
Os campos Atom não são tokenizados. Um documento com um campo atom que tenha o valor "mau tempo" só corresponde a uma pesquisa da string completa "mau tempo". Não corresponde a uma pesquisa de "mau" ou "tempo" isoladamente.
Regras de tokenização
Os carateres de sublinhado (_) e comercial (&) não dividem as palavras em tokens.
Estes carateres de espaços em branco dividem sempre as palavras em tokens: espaço, retorno de carro, quebra de linha, tabulação horizontal, tabulação vertical, mudança de página e NULL.
Estes carateres são tratados como pontuação e dividem as palavras em tokens:
! " % ( ) * , - | / [ ] ] ^ ` : = > ? @ { } ~ € Os carateres na tabela seguinte normalmente dividem as palavras em tokens, mas podem ser processados de forma diferente consoante o contexto em que aparecem:
Personagem Regra <
Num campo HTML, o sinal "menor que" indica o início de uma etiqueta HTML que é ignorada. +
Uma sequência de um ou mais sinais de "mais" é tratada como parte da palavra se aparecer no final da palavra (C++). #
O sinal "hash" é tratado como parte da palavra se for precedido por a, b, c, d, e, f, g, j ou x (a# - g# são notas musicais; j# e x# são linguagens de programação; c# é ambos). Se um termo for precedido por "#" (#google), é tratado como uma hashtag e o símbolo de cardinal passa a fazer parte da palavra. '
O apóstrofo é uma letra se preceder a letra "s" seguida de uma quebra de palavra, como em "o chapéu do João". .
Se aparecer um ponto entre dígitos, faz parte de um número (ou seja, o separador decimal). Também pode fazer parte de uma palavra se for usado num acrónimo (A.B.C). -
O travessão faz parte de uma palavra se for usado num acrónimo (I-B-M). Todos os outros carateres de 7 bits que não sejam letras nem dígitos ("A-Z", "a-z", "0-9") são processados como pontuação e dividem as palavras em tokens.
Tudo o resto é analisado como um caráter UTF-8.
Acrónimos
A tokenização usa regras especiais para reconhecer acrónimos (strings como "I.B.M.", "a-b-c" ou "C I A"). Uma sigla é uma string de carateres alfabéticos únicos, com o mesmo caráter separador entre todos eles. Os separadores válidos são o ponto, o traço ou qualquer número de espaços. O caráter separador é removido da string quando um acrónimo é tokenizado. Assim, as strings de exemplo mencionadas acima tornam-se os tokens "ibm", "abc" e "cia". O texto original permanece no campo do documento.
Quando trabalhar com acrónimos, tenha em atenção que:
- Um acrónimo não pode conter mais de 21 letras. Uma string de acrónimo válida com mais de 21 letras é dividida numa série de acrónimos, cada um com 21 letras ou menos.
- Se as letras de um acrónimo estiverem separadas por espaços, todas as letras têm de estar em maiúsculas ou minúsculas. Os acrónimos construídos com um ponto e um traço podem usar letras em maiúsculas e minúsculas.
- Quando pesquisa um acrónimo, pode introduzir a forma canónica do acrónimo (a string sem separadores) ou o acrónimo com pontuação com o traço ou o ponto (mas não ambos) entre as letras. Assim, o texto "I.B.M" pode ser obtido com qualquer um dos termos de pesquisa "I-B-M", "I.B.M" ou "IBM".
Precisão do campo de tempo
Quando cria um campo de tempo num documento, define o respetivo valor como time.Time
.
Para fins de indexação e pesquisa do campo de tempo, qualquer componente de tempo é ignorado e a data é convertida no número de dias desde 01/01/1970 UTC. Isto significa que, embora um campo de hora possa conter um valor de hora preciso, uma consulta de data só pode especificar um valor de campo de hora no formato yyyy-mm-dd
. Isto também significa que a ordem de classificação dos campos de tempo com a mesma data não está bem definida. Embora o tipo time.Time
represente a hora com precisão de nanossegundos, a API Google Search armazena-as apenas com precisão de milissegundos.
Outras propriedades do documento
A classificação de um documento é um número inteiro positivo que determina a ordenação predefinida dos documentos devolvidos por uma pesquisa. Por predefinição, a classificação é definida no momento em que o documento é criado para o número de segundos desde 1 de janeiro de 2011. Pode definir a classificação explicitamente quando cria um documento. É uma má ideia atribuir a mesma classificação a muitos documentos e nunca deve atribuir a mais de 10 000 documentos a mesma classificação.
Se especificar opções de ordenação,
pode usar a classificação como chave de ordenação. Tenha em atenção que, quando a classificação é usada numa expressão de ordenação
ou numa expressão de campo
, é referenciada como _rank
.
Consulte a DocumentMetadata
referência para mais informações sobre como definir a classificação.
A propriedade Language da estrutura Field
especifica o idioma no qual esse campo está codificado.
Criar links de um documento para outros recursos
Pode usar o docID
de um documento e outros campos como links para outros recursos na sua aplicação. Por exemplo, se usar o Blobstore, pode associar o documento a um blob específico definindo o docID
ou o valor de um campo Atom para o BlobKey dos dados.
Criar um documento
O exemplo de código seguinte mostra como criar um objeto de documento. O User
tipo
especifica a estrutura do documento e é construído um User
valor da forma habitual.
Trabalhar com um índice
Colocar documentos num índice
Quando coloca um documento num índice, o documento é copiado para o armazenamento persistente e cada um dos respetivos campos é indexado de acordo com o respetivo nome, tipo e docID
.
O exemplo de código seguinte mostra como aceder a um índice e colocar um documento no mesmo.
Quando coloca um documento num índice e o índice já contém um documento com o mesmo docID
, o novo documento substitui o antigo. Não é dado nenhum aviso. Pode chamar
Index.Get
antes de criar ou adicionar um documento a um índice para verificar se um
docID
específico já existe.
O método Put
devolve um docID
. Se não especificou o docID
, pode examinar o resultado para descobrir o docID
que foi gerado:
Tenha em atenção que a criação de uma instância do tipo Index
não garante que exista efetivamente um índice persistente. É criado um índice persistente da primeira vez que
lhe adiciona um documento com o método put
.
Atualizar documentos
Não é possível alterar um documento depois de o adicionar a um índice. Não pode adicionar nem remover campos, nem alterar o valor de um campo. No entanto, pode substituir o documento por um novo documento com o mesmo docID
.
Obter documentos por docID
Use o método Index.Get
para obter um documento de um índice pelo respetivo docID
:
Pesquisar documentos pelo respetivo conteúdo
Para obter documentos de um índice, cria uma string de consulta e chama o método
Index.Search
.
Search
devolve um iterador que produz documentos correspondentes por ordem de classificação decrescente.
Eliminar um índice
Cada índice consiste nos respetivos documentos indexados e num esquema de índice. Para eliminar um índice, elimine todos os documentos num índice e, em seguida, elimine o esquema do índice.
Pode eliminar documentos num índice especificando o docID
do documento que quer eliminar no método Index.Delete
.
Esta abordagem pode demorar muito tempo se precisar de eliminar um grande número de entradas do índice de pesquisa. Para resolver este problema, experimente o seguinte:
- Eliminar o projeto e as respetivas dependências.
- Peça uma quota mais elevada para eliminações mais rápidas.
Consistência eventual
Quando coloca, atualiza ou elimina um documento num índice, a alteração propaga-se por vários centros de dados. Normalmente, isto acontece rapidamente, mas o tempo que demora pode variar. A API Search garante a consistência eventual. Isto significa que, em alguns casos, uma pesquisa ou uma obtenção de um ou mais documentos pode devolver resultados que não refletem as alterações mais recentes.
Esquemas de índice
Cada índice tem um esquema que mostra todos os nomes e tipos de campos que aparecem nos documentos que contém. Não pode definir um esquema. Os esquemas são mantidos dinamicamente e são atualizados à medida que os documentos são adicionados a um índice. Um esquema simples pode ter o seguinte aspeto, num formato semelhante a JSON:
{'comment': ['TEXT'], 'date': ['DATE'], 'author': ['TEXT'], 'count': ['NUMBER']}
Cada chave no dicionário é o nome de um campo de documento. O valor da chave é uma lista dos tipos de campos usados com esse nome de campo. Se tiver usado o mesmo nome de campo com diferentes tipos de campos, o esquema apresenta mais do que um tipo de campo para um nome de campo, da seguinte forma:
{'ambiguous-integer': ['TEXT', 'NUMBER', 'ATOM']}
Depois de um campo aparecer num esquema, nunca pode ser removido. Não é possível eliminar um campo, mesmo que o índice já não contenha documentos com esse nome de campo específico.
Um esquema não define uma "classe" no sentido da programação orientada a objetos. No que diz respeito à API Search, cada documento é único e os índices podem conter diferentes tipos de documentos. Se quiser tratar coleções de objetos com a mesma lista de campos como instâncias de uma classe, essa é uma abstração que tem de aplicar no seu código. Por exemplo, pode garantir que todos os documentos com o mesmo conjunto de campos são mantidos no respetivo índice. O esquema do índice pode ser visto como a definição da classe e cada documento no índice seria uma instância da classe.
Visualizar índices na Google Cloud consola
Na Google Cloud consola, pode ver informações sobre os índices da sua aplicação e os documentos que contêm. Se clicar no nome de um índice, são apresentados os documentos que esse índice contém. São apresentados todos os campos do esquema definidos para o índice. Para cada documento com um campo desse nome, é apresentado o valor do campo. Também pode emitir consultas sobre os dados do índice diretamente a partir da consola.
Quotas da API Search
A API Search tem várias quotas gratuitas:
Recurso ou chamada API | Quota gratuita |
---|---|
Armazenamento total (documentos e índices) | 0,25 GB |
Consultas | 1000 consultas por dia |
Adicionar documentos a índices | 0,01 GB por dia |
A API Search impõe estes limites para garantir a fiabilidade do serviço. Estas aplicam-se a apps gratuitas e pagas:
Recurso | Quota de segurança |
---|---|
Utilização máxima de consultas | 100 minutos agregados de tempo de execução de consultas por minuto |
Número máximo de documentos adicionados ou eliminados | 15 000 por minuto |
Tamanho máximo por índice (número ilimitado de índices permitido) | 10 GB |
A utilização da API é contabilizada de diferentes formas consoante o tipo de chamada:
Index.Search
: cada chamada API conta como uma consulta; o tempo de execução é equivalente à latência da chamada.Index.Put
: quando adiciona documentos a índices, o tamanho de cada documento e o número de documentos contam para a quota de indexação.- Todas as outras chamadas da API Google Search são contabilizadas com base no número de operações que envolvem:
Index.Get
: 1 operação contabilizada para cada documento efetivamente devolvido ou 1 operação se nada for devolvido.Index.Delete
: 1 operação contabilizada para cada documento no pedido ou 1 operação se o pedido estiver vazio.
A quota de débito de consultas é imposta para que um único utilizador não possa monopolizar o serviço de pesquisa. Uma vez que as consultas podem ser executadas em simultâneo, cada aplicação pode executar consultas que consomem até 100 minutos de tempo de execução por um minuto de tempo real. Se estiver a executar muitas consultas curtas, provavelmente não vai atingir este limite. Quando excede a quota, as consultas subsequentes falham até ao próximo intervalo de tempo, quando a quota é restaurada. A quota não é imposta estritamente em intervalos de um minuto. É usada uma variação do algoritmo de leaky bucket para controlar a largura de banda de pesquisa em intervalos de cinco segundos.
Pode encontrar mais informações sobre as quotas na página Quotas. Quando uma app tenta exceder estes valores, é devolvido um erro de quota insuficiente.
Tenha em atenção que, embora estes limites sejam aplicados por minuto, a consola apresenta os totais diários de cada um. Os clientes com apoio técnico Silver, Gold ou Platinum podem solicitar limites de débito mais elevados contactando o respetivo representante do apoio técnico.
Preços da API Search
As seguintes cobranças são aplicadas à utilização que exceda as quotas gratuitas:
Recurso | Custo |
---|---|
Armazenamento total (documentos e índices) | 0,18 $ por GB por mês |
Consultas | 0,50 $ por 10 mil consultas |
Indexação de documentos pesquisáveis | 2,00 USD por GB |
Pode encontrar informações adicionais sobre os preços na página Preços.