Filtre mensagens de uma subscrição

Esta página explica como criar subscrições do Pub/Sub com filtros.

Quando recebe mensagens de uma subscrição com um filtro, só recebe as mensagens que correspondem ao filtro. O serviço Pub/Sub confirma automaticamente as mensagens que não correspondem ao filtro. Pode filtrar mensagens pelos respetivos atributos, mas não pelos dados na mensagem.

Pode ter várias subscrições associadas a um tópico, e cada subscrição pode ter um filtro diferente.

Por exemplo, se tiver um tópico que recebe notícias de diferentes partes do mundo, pode configurar uma subscrição para filtrar notícias publicadas apenas numa região específica. Para esta configuração, tem de garantir que um dos atributos da mensagem do tópico transmite a região da publicação de notícias.

Quando recebe mensagens de uma subscrição com um filtro, não incorre em taxas de mensagens de saída para as mensagens que o Pub/Sub reconhece automaticamente. Incorre em taxas de entrega de mensagens e taxas de armazenamento relacionadas com a procura para estas mensagens.

Crie uma subscrição com um filtro

As subscrições de obtenção e emissão podem ter filtros. Todos os subscritores podem receber mensagens de subscrições com filtros, incluindo os subscritores que usam a API StreamingPull.

Pode criar uma subscrição com um filtro através da Trusted Cloud consola, da CLI do Google Cloud, das bibliotecas de cliente ou da API Pub/Sub.

Consola

Para criar uma subscrição de obtenção com um filtro, siga estes passos:

  1. Na Trusted Cloud consola, aceda à página Subscrições.

    Aceda à página Subscrições

  2. Clique em Criar subscrição.

  3. Introduza o ID da subscrição.

  4. Escolha ou crie um tópico no menu pendente. A subscrição recebe mensagens do tópico.

  5. Na secção Filtro de subscrição, introduza a expressão de filtro.

  6. Clique em Criar.

Para criar uma subscrição push com um filtro, siga estes passos:

  1. Na Trusted Cloud consola, aceda à página Subscrições.

    Aceda à página Subscrições

  2. Clique em Criar subscrição.

  3. Introduza o ID da subscrição.

  4. Escolha ou crie um tópico no menu pendente. A subscrição recebe mensagens do tópico.

  5. Na secção Tipo de fornecimento, clique em Push.

  6. No campo URL do ponto final, introduza o URL do ponto final de envio.

  7. Na secção Filtro de subscrição, introduza a expressão de filtro.

  8. Clique em Criar.

gcloud

Para criar uma subscrição pull com um filtro, use o comando gcloud pubsub subscriptions create com a flag --message-filter:

gcloud pubsub subscriptions create SUBSCRIPTION_ID \
  --topic=TOPIC_ID \
  --message-filter='FILTER'

Substitua o seguinte:

  • SUBSCRIPTION_ID: o ID da subscrição a criar
  • TOPIC_ID: o ID do tópico a anexar à subscrição
  • FILTER: uma expressão na sintaxe de filtragem

Para criar uma subscrição push com um filtro, use o comando gcloud pubsub subscriptions create com as flags --push-endpoint e --message-filter:

gcloud pubsub subscriptions create SUBSCRIPTION_ID \
  --topic=TOPIC_ID \
  --push-endpoint=PUSH_ENDPOINT \
  --message-filter='FILTER'

Substitua o seguinte:

  • SUBSCRIPTION_ID: o ID da subscrição a criar
  • TOPIC_ID: o ID do tópico a anexar à subscrição
  • PUSH_ENDPOINT: o URL do servidor no qual o subscritor de envio por push é executado
  • FILTER: uma expressão na sintaxe de filtragem

REST

Para criar uma subscrição com um filtro, use o método projects.subscriptions.create.

PUT https://pubsub.googleapis.com/v1/projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID
Authorization: Bearer $(gcloud auth print-access-token)

Substitua o seguinte:

  • PROJECT_ID: o ID do projeto no qual criar a subscrição
  • SUBSCRIPTION_ID: o ID da subscrição a criar

Para criar uma subscrição de obtenção com um filtro, especifique o filtro no corpo do pedido:

{
  "topic": "projects/PROJECT_ID/topics/TOPIC_ID",
  "filter": "FILTER"
}

Substitua o seguinte:

  • PROJECT_ID: o ID do projeto com o tópico
  • TOPIC_ID: o ID do tópico a anexar à subscrição
  • FILTER: uma expressão na sintaxe de filtragem

Para criar uma subscrição push com um filtro, especifique o ponto final push e o filtro no corpo do pedido:

{
  "topic": "projects/PROJECT_ID/topics/TOPIC_ID",
  "pushConfig": {
    "pushEndpoint": "PUSH_ENDPOINT"
  },
  "filter": "FILTER"
}

Substitua o seguinte:

  • PROJECT_ID: o ID do projeto com o tópico
  • TOPIC_ID: o ID do tópico a anexar à subscrição
  • PUSH_ENDPOINT: o URL do servidor no qual o subscritor de envio por push é executado
  • FILTER: uma expressão na sintaxe de filtragem

C++

Antes de experimentar este exemplo, siga as instruções de configuração do C++ no artigo Início rápido: usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API C++ do Pub/Sub.

namespace pubsub = ::google::cloud::pubsub;
namespace pubsub_admin = ::google::cloud::pubsub_admin;
[](pubsub_admin::SubscriptionAdminClient client,
   std::string const& project_id, std::string topic_id,
   std::string subscription_id) {
  google::pubsub::v1::Subscription request;
  request.set_name(
      pubsub::Subscription(project_id, std::move(subscription_id))
          .FullName());
  request.set_topic(
      pubsub::Topic(project_id, std::move(topic_id)).FullName());
  request.set_filter(R"""(attributes.is-even = "false")""");
  auto sub = client.CreateSubscription(request);
  if (sub.status().code() == google::cloud::StatusCode::kAlreadyExists) {
    std::cout << "The subscription already exists\n";
    return;
  }
  if (!sub) throw std::move(sub).status();

  std::cout << "The subscription was successfully created: "
            << sub->DebugString() << "\n";
}

C#

Antes de experimentar este exemplo, siga as instruções de configuração do C# em Início rápido: usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API C# do Pub/Sub.


using Google.Cloud.PubSub.V1;
using Grpc.Core;

public class CreateSubscriptionWithFilteringSample
{
    public Subscription CreateSubscriptionWithFiltering(string projectId, string topicId, string subscriptionId, string filter)
    {
        SubscriberServiceApiClient subscriber = SubscriberServiceApiClient.Create();
        TopicName topicName = TopicName.FromProjectTopic(projectId, topicId);
        SubscriptionName subscriptionName = SubscriptionName.FromProjectSubscription(projectId, subscriptionId);
        Subscription subscription = null;

        var subscriptionRequest = new Subscription
        {
            SubscriptionName = subscriptionName,
            TopicAsTopicName = topicName,
            Filter = filter
        };

        try
        {
            subscription = subscriber.CreateSubscription(subscriptionRequest);
        }
        catch (RpcException e) when (e.Status.StatusCode == StatusCode.AlreadyExists)
        {
            // Already exists.  That's fine.
        }
        return subscription;
    }
}

Ir

O exemplo seguinte usa a versão principal da biblioteca de cliente Go Pub/Sub (v2). Se ainda estiver a usar a biblioteca v1, consulte o guia de migração para a v2. Para ver uma lista de exemplos de código da v1, consulte os exemplos de código descontinuados.

Antes de experimentar este exemplo, siga as instruções de configuração do Go em Início rápido: usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Go do Pub/Sub.

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/pubsub/v2"
	"cloud.google.com/go/pubsub/v2/apiv1/pubsubpb"
)

func createWithFilter(w io.Writer, projectID, topic, subscription, filter string) error {
	// Receive messages with attribute key "author" and value "unknown".
	// projectID := "my-project-id"
	// topic := "projects/my-project-id/topics/my-topic"
	// subscription := "projects/my-project/subscriptions/my-sub"
	// filter := "attributes.author=\"unknown\""
	ctx := context.Background()
	client, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("pubsub.NewClient: %w", err)
	}
	defer client.Close()

	sub, err := client.SubscriptionAdminClient.CreateSubscription(ctx, &pubsubpb.Subscription{
		Name:   subscription,
		Topic:  topic,
		Filter: filter,
	})
	if err != nil {
		return fmt.Errorf("CreateSubscription: %w", err)
	}
	fmt.Fprintf(w, "Created subscription with filter: %v\n", sub)
	return nil
}

Java

Antes de experimentar este exemplo, siga as instruções de configuração do Java no artigo Início rápido: usar bibliotecas cliente. Para mais informações, consulte a documentação de referência da API Java do Pub/Sub.

import com.google.cloud.pubsub.v1.SubscriptionAdminClient;
import com.google.pubsub.v1.ProjectSubscriptionName;
import com.google.pubsub.v1.ProjectTopicName;
import com.google.pubsub.v1.Subscription;
import java.io.IOException;

public class CreateSubscriptionWithFiltering {
  public static void main(String... args) throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String topicId = "your-topic-id";
    String subscriptionId = "your-subscription-id";
    String filter = "attributes.author=\"unknown\"";

    createSubscriptionWithFilteringExample(projectId, topicId, subscriptionId, filter);
  }

  public static void createSubscriptionWithFilteringExample(
      String projectId, String topicId, String subscriptionId, String filter) throws IOException {
    try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {

      ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);
      ProjectSubscriptionName subscriptionName =
          ProjectSubscriptionName.of(projectId, subscriptionId);

      Subscription subscription =
          subscriptionAdminClient.createSubscription(
              Subscription.newBuilder()
                  .setName(subscriptionName.toString())
                  .setTopic(topicName.toString())
                  // Receive messages with attribute key "author" and value "unknown".
                  .setFilter(filter)
                  .build());

      System.out.println(
          "Created a subscription with filtering enabled: " + subscription.getAllFields());
    }
  }
}

Node.js

Antes de experimentar este exemplo, siga as instruções de configuração do Node.js em Início rápido: usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Node.js do Pub/Sub.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';
// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';
// const filterString = 'YOUR_FILTER_STRING';   // e.g. 'attributes.author="unknown"'

// Imports the Google Cloud client library
const {PubSub} = require('@google-cloud/pubsub');

// Creates a client; cache this for further use
const pubSubClient = new PubSub();

async function createSubscriptionWithFilter(
  topicNameOrId,
  subscriptionNameOrId,
  filterString,
) {
  // Creates a new subscription
  await pubSubClient
    .topic(topicNameOrId)
    .createSubscription(subscriptionNameOrId, {
      filter: filterString,
    });
  console.log(
    `Created subscription ${subscriptionNameOrId} with filter ${filterString}.`,
  );
}

Node.js

Antes de experimentar este exemplo, siga as instruções de configuração do Node.js em Início rápido: usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Node.js do Pub/Sub.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';
// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';
// const filterString = 'YOUR_FILTER_STRING';   // e.g. 'attributes.author="unknown"'

// Imports the Google Cloud client library
import {PubSub} from '@google-cloud/pubsub';

// Creates a client; cache this for further use
const pubSubClient = new PubSub();

async function createSubscriptionWithFilter(
  topicNameOrId: string,
  subscriptionNameOrId: string,
  filterString: string,
) {
  // Creates a new subscription
  await pubSubClient
    .topic(topicNameOrId)
    .createSubscription(subscriptionNameOrId, {
      filter: filterString,
    });
  console.log(
    `Created subscription ${subscriptionNameOrId} with filter ${filterString}.`,
  );
}

PHP

Antes de experimentar este exemplo, siga as instruções de configuração do PHP no artigo Início rápido: usar bibliotecas cliente. Para mais informações, consulte a documentação de referência da API PHP Pub/Sub.

use Google\Cloud\PubSub\PubSubClient;

/**
 * Creates a Pub/Sub subscription.
 *
 * @param string $projectId  The Google project ID.
 * @param string $topicName  The Pub/Sub topic name.
 * @param string $subscriptionName  The Pub/Sub subscription name.
 * @param string $filter  The Pub/Sub subscription filter.
 */
function create_subscription_with_filter(
    string $projectId,
    string $topicName,
    string $subscriptionName,
    string $filter
): void {
    $pubsub = new PubSubClient([
        'projectId' => $projectId,
    ]);
    $topic = $pubsub->topic($topicName);
    $subscription = $topic->subscription($subscriptionName);

    $subscription->create(['filter' => $filter]);

    printf('Subscription created: %s' . PHP_EOL, $subscription->name());
    printf('Subscription info: %s' . PHP_EOL, json_encode($subscription->info()));
}

Python

Antes de experimentar este exemplo, siga as instruções de configuração do Python em Início rápido: usar bibliotecas cliente. Para mais informações, consulte a documentação de referência da API Python Pub/Sub.

from google.cloud import pubsub_v1

# TODO(developer): Choose an existing topic.
# project_id = "your-project-id"
# topic_id = "your-topic-id"
# subscription_id = "your-subscription-id"
# filter = "attributes.author=\"unknown\""

publisher = pubsub_v1.PublisherClient()
subscriber = pubsub_v1.SubscriberClient()
topic_path = publisher.topic_path(project_id, topic_id)
subscription_path = subscriber.subscription_path(project_id, subscription_id)

with subscriber:
    subscription = subscriber.create_subscription(
        request={"name": subscription_path, "topic": topic_path, "filter": filter}
    )
    print(f"Created subscription with filtering enabled: {subscription}")

Ruby

O exemplo seguinte usa a biblioteca cliente Ruby Pub/Sub v3. Se ainda estiver a usar a biblioteca v2, consulte o guia de migração para a v3. Para ver uma lista de exemplos de código do Ruby v2, consulte os exemplos de código descontinuados.

Antes de experimentar este exemplo, siga as instruções de configuração do Ruby em Início rápido: usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API Ruby Pub/Sub.

# project_id = "your-project-id"
# topic_id = "your-topic-id"
# subscription_id = "your-subscription-id"
# filter = "attributes.author=\"unknown\""

pubsub = Google::Cloud::PubSub.new project_id: project_id
subscription_admin = pubsub.subscription_admin

subscription = subscription_admin.create_subscription \
  name: pubsub.subscription_path(subscription_id),
  topic: pubsub.topic_path(topic_id),
  filter: filter

puts "Created subscription with filtering enabled: #{subscription_id}"

O comprimento máximo de um filtro é de 256 bytes. O filtro é uma propriedade imutável de uma subscrição. Depois de criar uma subscrição, não pode atualizá-la para modificar o filtro.

Como os filtros afetam as métricas de pendências

Para monitorizar a subscrição que acabou de criar, consulte o artigo Monitorize subscrições com filtros.

Se tiver a filtragem ativada, as métricas da fila de processamento pendente só incluem dados de mensagens que correspondem ao filtro. Segue-se uma lista das métricas de pendências:

  • subscription/backlog_bytes
  • subscription/unacked_bytes_by_region
  • subscription/num_undelivered_messages
  • subscription/num_unacked_messages_by_region
  • subscription/oldest_unacked_message_age
  • subscription/oldest_unacked_message_age_by_region
  • topic/unacked_bytes_by_region
  • topic/num_unacked_messages_by_region
  • topic/oldest_unacked_messages_age_by_region

Para saber mais acerca destas métricas, consulte a lista de métricas do Pub/Sub.

Atualize o filtro de uma subscrição

Não pode atualizar o filtro de uma subscrição existente. Em alternativa, siga esta solução alternativa.

  1. Tire uma captura de ecrã da subscrição para a qual quer alterar o filtro.

    Para saber como tirar uma captura de ecrã através da consola, consulte o artigo Crie uma captura de ecrã.

  2. Crie uma nova subscrição com o novo filtro.

    Para saber mais sobre como criar uma subscrição com um filtro, consulte o artigo Crie uma subscrição com um filtro.

  3. Na Trusted Cloud consola, aceda à página Subscrições do Pub/Sub.

    Aceder às subscrições

  4. Clique na subscrição que acabou de criar.

  5. Na página de detalhes da subscrição, clique em Repetir mensagens.

  6. Para Procurar, clique em Para um resumo.

  7. Selecione a captura de ecrã que criou para a subscrição original no passo 1 e, de seguida, clique em Procurar.

    Não perde nenhuma mensagem durante a transição.

  8. Altere os subscritores para usarem a nova subscrição.

Após concluir este procedimento, pode avançar e eliminar a subscrição original.

Sintaxe para criar um filtro

Para filtrar mensagens, escreva uma expressão que opere em atributos. Pode escrever uma expressão que corresponda à chave ou ao valor dos atributos. O identificador attributes seleciona os atributos na mensagem.

Por exemplo, os filtros na tabela seguinte selecionam o atributo name:

Filtro Descrição
attributes:name Mensagens com o atributo name
NOT attributes:name Mensagens sem o atributo name
attributes.name = "com" Mensagens com o atributo name e o valor com
attributes.name != "com" Mensagens sem o atributo name e o valor de com
hasPrefix(attributes.name, "co") Mensagens com o atributo name e um valor que começa por co
NOT hasPrefix(attributes.name, "co") Mensagens sem o atributo name e um valor que comece por co

Operadores de comparação para a expressão de filtro

Pode filtrar atributos com os seguintes operadores de comparação:

  • :
  • =
  • !=

O operador : corresponde a uma chave numa lista de atributos.

attributes:KEY

Os operadores de igualdade correspondem a chaves e valores. O valor tem de ser um literal de string.

attributes.KEY = "VALUE"

Uma expressão com um operador de igualdade tem de começar com uma chave, e o operador de igualdade tem de comparar uma chave e um valor.

  • Válido: o filtro compara uma chave e um valor

    attributes.name = "com"
    
  • Inválido: o lado esquerdo do filtro é um valor

    "com" = attributes.name
    
  • Inválido: o filtro compara duas chaves

    attributes.name = attributes.website
    

A chave e o valor são sensíveis a maiúsculas e minúsculas e têm de corresponder exatamente ao atributo. Se uma chave contiver carateres que não sejam hífenes, sublinhados ou carateres alfanuméricos, use um literal de string.

attributes."iana.org/language_tag" = "en"

Para usar barras invertidas, aspas e carateres não imprimíveis num filtro, escape os carateres num literal de string. Também pode usar sequências de escape Unicode, hexadecimal e octal num literal de string.

  • Válido: o filtro escapa a carateres num literal de string

    attributes:"\u307F\u3093\u306A"
    
  • Inválido: o filtro escapa a carateres sem um literal de string

    attributes:\u307F\u3093\u306A
    

Operadores booleanos para a expressão de filtro

Pode usar os operadores booleanos AND, NOT e OR num filtro. Os operadores têm de estar em letras maiúsculas. Por exemplo, o filtro seguinte destina-se a mensagens com o atributo iana.org/language_tag, mas sem o atributo name e o valor com.

attributes:"iana.org/language_tag" AND NOT attributes.name = "com"

O operador NOT tem a precedência mais elevada. Para combinar os operadores AND e OR, use parênteses e expressões completas.

  • Válido: operadores AND e OR com parênteses

    attributes:"iana.org/language_tag" AND (attributes.name = "net" OR attributes.name = "org")
    
  • Inválido: operadores AND e OR sem parênteses

    attributes:"iana.org/language_tag" AND attributes.name = "net" OR attributes.name = "org"
    
  • Inválido: os operadores AND e OR combinam expressões incompletas

    attributes.name = "com" AND ("net" OR "org")
    

Em alternativa, também pode usar o operador menos unário em vez do operador NOT.

attributes.name = "com" AND -attributes:"iana.org/language_tag"

Funções para a expressão de filtro

Pode usar a função hasPrefix para filtrar atributos com valores que começam por uma subcadeia de carateres. hasPrefix é a única função suportada num filtro.

Embora a correspondência de prefixos seja suportada com a função hasPrefix, as expressões regulares gerais não são suportadas.

hasPrefix(attributes.KEY, "SUBSTRING")

Substitua o seguinte:

  • KEY: o nome do atributo
  • SUBSTRING: uma subcadeia de carateres do valor