Conversão em tokens

Esta página descreve como adicionar a tokenização a tabelas. A tokenização é necessária para criar os tokens usados no índice de pesquisa.

A tokenização é o processo de transformação de valores em tokens. O método que usa para tokenizar um documento determina os tipos e a eficiência das pesquisas que os utilizadores podem realizar no mesmo.

O Spanner fornece tokenizadores para texto em linguagem natural, subcadeias, texto literal, números e valores booleanos. O esquema da base de dados usa o tokenizador que corresponde ao tipo de pesquisa necessário para a coluna. Os tokenizadores têm as seguintes caraterísticas:

  • Cada tokenizador é uma função SQL que recebe uma entrada, como uma string ou um número, e argumentos com nome para opções adicionais.
  • O tokenizador produz um TOKENLIST.

Por exemplo, a string de texto The quick brown fox jumps over the lazy dog é tokenizada em [the,quick,brown,fox,jumps,over,the,lazy,dog]. Uma string HTML The <b>apple</b> is <i>red</i> é dividida em tokens em [the,apple,is,red].

Os tokens têm as seguintes caraterísticas:

  • Os tokens são armazenados em colunas que usam o tipo de dados TOKENLIST.
  • Cada token é armazenado como uma sequência de bytes, com um conjunto opcional de atributos associados. Por exemplo, em aplicações de texto completo, um token é normalmente uma única palavra de um documento de texto.
  • Ao tokenizar valores HTML, o Spanner gera atributos que indicam a proeminência de um token no documento. O Spanner usa estes atributos para a classificação de modo a realçar termos mais proeminentes (como um título).

Tokenizadores

O Spanner suporta as seguintes funções de tokenização:

  • O tokenizador de texto completo (TOKENIZE_FULLTEXT) produz tokens de palavras inteiras para consultas de linguagem natural.

    Exemplo

    Ambas as funções seguintes

    GoogleSQL

    TOKENIZE_FULLTEXT("Yellow apple")
    TOKENIZE_FULLTEXT("Yellow <b>apple</b>", content_type=>"text/html")
    

    PostgreSQL

    Este exemplo usa spanner.tokenize_fulltext.

    spanner.tokenize_fulltext("Yellow apple")
    spanner.tokenize_fulltext('Yellow <b>apple</b>', context_type=>'text/html')
    

    produzem os mesmos tokens: [yellow,apple].

  • O tokenizador de subcadeias (TOKENIZE_SUBSTRING) gera tokens para cada n-grama de cada palavra. É usado para encontrar subcadeias de carateres de palavras num texto.

    Exemplo

    GoogleSQL

    TOKENIZE_SUBSTRING('hello world', ngram_size_min=>4, ngram_size_max=>6)
    

    PostgreSQL

    Este exemplo usa spanner.tokenize_substring.

    spanner.tokenize_substring('hello world', ngram_size_min=>4, ngram_size_max=>6)
    

    Produz os seguintes tokens: [ello,hell,hello,orld,worl,world].

  • O tokenizador de n-gramas (TOKENIZE_NGRAMS) gera n-gramas a partir de uma entrada (sem a dividir em palavras separadas). É usado para acelerar os predicados de expressões regulares.

    Exemplo

    A seguinte função:

    GoogleSQL

    TOKENIZE_NGRAMS("Big Time", ngram_size_min=>4, ngram_size_max=>4)
    

    PostgreSQL

    Este exemplo usa spanner.tokenize_ngrams.

    spanner.tokenize_ngrams('big time', ngram_size_min=>4, ngram_size_max=>4)
    

    Produz os seguintes tokens: ["Big ","ig T","g Ti"," Tim", "Time"].

  • Os tokenizadores de correspondência exata (TOKEN e TOKENIZE_BOOL) são usados para procurar linhas que contenham um determinado valor numa das respetivas colunas. Por exemplo, uma aplicação que indexa um catálogo de produtos pode querer pesquisar produtos de uma determinada marca e cor.

    Exemplos

    As seguintes funções:

    GoogleSQL

    TOKEN("hello")
    TOKEN(["hello", "world"])
    

    PostgreSQL

    Este exemplo usa spanner.token.

    spanner.token('hello')
    

    Produz os seguintes tokens: [hello].

    A seguinte função:

    GoogleSQL

    TOKENIZE_BOOL(true)
    

    PostgreSQL

    Este exemplo usa spanner.tokenize_bool.

    spanner.tokenize_bool(true)
    

    Produz o seguinte token: [y].

  • Os tokenizadores de números (TOKENIZE_NUMBER) são usados para gerar um conjunto de tokens que aceleram as pesquisas de comparação numérica. Para condições de igualdade, o token é o próprio número. Para condições de intervalo (como rating >= 3.5), o conjunto de tokens é mais elaborado.

    Exemplos

    As seguintes declarações de funções:

    GoogleSQL

    TOKENIZE_NUMBER(42, comparison_type=>'equality')
    TOKENIZE_NUMBER(42, comparison_type=>'all', granularity=>10, min=>1, max=>100)
    

    PostgreSQL

    Este exemplo usa spanner.tokenize_number.

    spanner.tokenize_number(42, comparison_type=>'equality')
    spanner.tokenize_number(42, comparison_type=>'all', granularity=>10, min=>1, max=>100)
    

    Produza os seguintes tokens, respetivamente: "==42" e "==42", "[1,75]","[36, 45]","[36,55]","[36, 75]".

  • Os analisadores JSON e JSONB (TOKENIZE_JSON e TOKENIZE_JSONB) são usados para gerar um conjunto de tokens que aceleram a contenção JSON e os predicados de existência de chaves, como doc[@key] IS NOT NULL (GoogleSQL) ou doc ? 'key' (PostgreSQL).

As funções de tokenização são normalmente usadas numa expressão de coluna gerada. Estas colunas são definidas como HIDDEN para não serem incluídas nos resultados da consulta SELECT *.

O exemplo seguinte usa um tokenizador de texto completo e um tokenizador numérico para criar uma base de dados que armazena os nomes e as classificações de álbuns de música. A declaração DDL faz duas coisas:

  1. Define as colunas de dados AlbumTitle e Rating.
  2. Define AlbumTitle_Tokens e AlbumRating_Tokens. Estas TOKENLIST colunas tokenizam os valores nas colunas de dados para que o Spanner possa indexá-los.

    GoogleSQL

    CREATE TABLE Albums (
      AlbumId STRING(MAX) NOT NULL,
      AlbumTitle STRING(MAX),
      Rating FLOAT64,
      AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN,
      Rating_Tokens TOKENLIST AS (TOKENIZE_NUMBER(Rating)) HIDDEN
    ) PRIMARY KEY(AlbumId);
    

    PostgreSQL

    CREATE TABLE albums (
      albumid character varying NOT NULL,
      albumtitle character varying,
      albumtitle_Tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN,
    PRIMARY KEY(albumid));
    

Sempre que os valores base são modificados, AlbumTitle_Tokens e Rating_Tokens são atualizados automaticamente.

Tokenize texto simples ou conteúdo HTML

A tokenização de texto suporta tipos de conteúdo de texto simples e HTML. Use a função Spanner TOKENIZE_FULLTEXT para criar tokens. Em seguida, use a declaração DDL CREATE SEARCH INDEX para gerar o índice de pesquisa.

Por exemplo, a seguinte declaração LDD CREATE TABLE usa a função TOKENIZE_FULLTEXT para criar tokens a partir de AlbumTitles na tabela Albums. A declaração DDL CREATE SEARCH INDEX cria um índice de pesquisa com o novo AlbumTitles_Tokens.

GoogleSQL

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  AlbumTitle STRING(MAX),
  AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN
) PRIMARY KEY(AlbumId);

CREATE SEARCH INDEX AlbumsIndex ON Albums(AlbumTitle_Tokens)

PostgreSQL

CREATE TABLE albums (
  albumid character varying NOT NULL,
  albumtitle character varying,
  albumtitle_tokens spanner.tokenlist
      GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));

CREATE SEARCH INDEX albumsindex ON albums(albumtitle_tokens)

O processo de tokenização usa as seguintes regras:

  • A tokenização não inclui a derivação nem a correção de palavras com erros ortográficos. Por exemplo, numa frase como "Um gato estava a olhar para um grupo de gatos", o token "gato" é indexado separadamente do token "gatos". Em comparação com outros motores de pesquisa que normalizam os tokens durante as gravações, o Spanner oferece uma opção para expandir a consulta de pesquisa de modo a incluir diferentes formas de palavras. Para mais informações, consulte o artigo Modo de consulta melhorado.
  • As palavras irrelevantes (como "um") estão incluídas no índice de pesquisa.
  • A pesquisa de texto completo não é sensível a maiúsculas e minúsculas. O processo de tokenização converte todos os tokens em minúsculas.

O processo de tokenização acompanha as posições de cada token no texto original. Estas posições são usadas posteriormente para fazer corresponder expressões. As posições são armazenadas no índice de pesquisa juntamente com os docids.

A Google continua a melhorar os algoritmos de tokenização. Em alguns casos, isto pode levar a que uma string seja tokenizada de forma diferente no futuro em relação à forma como é tokenizada agora. Esperamos que estes casos sejam extremamente raros. Um exemplo disto é se houver uma melhoria na segmentação de idiomas chinês, japonês e coreano (CJK).

O argumento content_type especifica se o formato de conteúdo usa texto simples ou HTML. Use as seguintes definições para definir o content_type:

  • Para a tokenização de texto, defina o argumento content_type como "text/plain". Esta é a predefinição.
  • Para a tokenização de HTML, defina o argumento content_type como "text/html". Sem este argumento, as etiquetas HTML são tratadas como pontuação. No modo HTML, o Spanner usa heurísticas para inferir a proeminência do texto na página. Por exemplo, se o texto está num título ou o tamanho do tipo de letra. Os atributos suportados para HTML incluem small, medium, large, title e "link". Tal como a posição, o atributo é armazenado juntamente com o token no índice de pesquisa. A tokenização não cria tokens para etiquetas HTML.

Os atributos dos tokens não afetam a correspondência nem os resultados da função SEARCH ou SEARCH_SUBSTRING. Só são usadas para a classificação.

O exemplo seguinte mostra como tokenizar texto:

GoogleSQL

CREATE TABLE T (
  ...
  Text STRING(MAX),
  Html STRING(MAX),
  Text_Tokens TOKENLIST
    AS (TOKENIZE_FULLTEXT(Text, content_type=>"text/plain")) HIDDEN,
  Html_Tokens TOKENLIST
    AS (TOKENIZE_FULLTEXT(Html, content_type=>"text/html")) HIDDEN
) PRIMARY KEY(...);

PostgreSQL

CREATE TABLE t (
  ...
  text character varying,
  html character varying,
  text_tokens spanner.tokenlist
      GENERATED ALWAYS AS (spanner.tokenize_fulltext(text, content_type=>"text/plain")) VIRTUAL HIDDEN,
  html_tokens spanner.tokenlist
      GENERATED ALWAYS AS (spanner.tokenize_fulltext(html, content_type=>'type/html')) VIRTUAL HIDDEN,
PRIMARY KEY(...));

Refinamento da deteção de idioma com o argumento language_tag

Por predefinição, a tokenização deteta automaticamente o idioma de entrada. Quando o idioma de entrada é conhecido, pode usar um argumento language_tag para refinar este comportamento:

GoogleSQL

AlbumTitle_Tokens TOKENLIST
  AS (TOKENIZE_FULLTEXT(AlbumTitle, language_tag=>"en-us")) HIDDEN

PostgreSQL

albumtitle_tokens spanner.tokenlist
      GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle, language_tag=>'en-us')) VIRTUAL HIDDEN

A maioria das aplicações deixa o argumento language_tag não especificado e, em alternativa, usa a deteção automática de idioma. A segmentação para idiomas asiáticos, como chinês, coreano e japonês, não requer a definição do idioma de tokenização.

Os exemplos seguintes mostram casos em que o elemento language_tag afeta a tokenização:

Função de conversão em tokens Símbolos produzidos
TOKENIZE_FULLTEXT("A tout pourquoi il y a un parce que") [a, tout, pourquoi, il, ya, un, parce, que]
TOKENIZE_FULLTEXT("A tout pourquoi il y a un parce que", \ language_tag=>"fr") [a, tout, pourquoi, il, y, a, un, parce, que]
TOKENIZE_FULLTEXT("旅 行") Dois tokens: [旅, 行]
TOKENIZE_FULLTEXT("旅 行", language_tag=>"zh") Um token: [旅行]

O que se segue?