Filtra i messaggi di una sottoscrizione

Questa pagina spiega come creare sottoscrizioni Pub/Sub con i filtri.

Quando ricevi messaggi da una sottoscrizione con un filtro, ricevi solo i messaggi che corrispondono al filtro. Il servizio Pub/Sub riconosce automaticamente i messaggi che non corrispondono al filtro. Puoi filtrare i messaggi in base ai loro attributi, ma non in base ai dati del messaggio.

Puoi avere più sottoscrizioni collegate a un argomento e ogni sottoscrizione può avere un filtro diverso.

Ad esempio, se hai un argomento che riceve notizie da diverse parti del mondo, puoi configurare un abbonamento per filtrare le notizie pubblicate solo da una regione specifica. Per questa configurazione, devi assicurarti che uno degli attributi dei messaggi dell'argomento corrisponda alla regione della pubblicazione di notizie.

Quando ricevi messaggi da una sottoscrizione con un filtro, non ti vengono addebitate tariffe per i messaggi in uscita per i messaggi riconosciuti automaticamente da Pub/Sub. Per questi messaggi ti vengono addebitate tariffe per la consegna dei messaggi e per l'archiviazione di ricerca.

crea una sottoscrizione con un filtro

Le sottoscrizioni pull e push possono avere filtri. Tutti gli abbonati possono ricevere messaggi dalle sottoscrizioni con filtri, inclusi gli abbonati che utilizzano l'API StreamingPull.

Puoi creare una sottoscrizione con un filtro utilizzando la console Google Cloud, Google Cloud CLI, le librerie client o l'API Pub/Sub.

Console

Per creare una sottoscrizione pull con un filtro:

  1. Nella console Google Cloud, vai alla pagina Abbonamenti.

    Vai alla pagina Abbonamenti

  2. Fai clic su Crea sottoscrizione.

  3. Inserisci l'ID abbonamento.

  4. Scegli o crea un argomento dal menu a discesa. La sottoscrizione riceve i messaggi dall'argomento.

  5. Nella sezione Filtro abbonamenti, inserisci l'espressione di filtro.

  6. Fai clic su Crea.

Per creare una sottoscrizione push con un filtro:

  1. Nella console Google Cloud, vai alla pagina Abbonamenti.

    Vai alla pagina Abbonamenti

  2. Fai clic su Crea sottoscrizione.

  3. Inserisci l'ID abbonamento.

  4. Scegli o crea un argomento dal menu a discesa. La sottoscrizione riceve i messaggi dall'argomento.

  5. Nella sezione Tipo di pubblicazione, fai clic su Invia.

  6. Nel campo URL endpoint, inserisci l'URL dell'endpoint push.

  7. Nella sezione Filtro abbonamenti, inserisci l'espressione di filtro.

  8. Fai clic su Crea.

gcloud

Per creare una sottoscrizione pull con un filtro, utilizza il comando gcloud pubsub subscriptions create con il flag --message-filter:

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

Sostituisci quanto segue:

  • SUBSCRIPTION_ID: l'ID della sottoscrizione da creare
  • TOPIC_ID: l'ID dell'argomento da collegare alla sottoscrizione
  • FILTER: un'espressione nella sintassi di filtro

Per creare una sottoscrizione push con un filtro, utilizza il comando gcloud pubsub subscriptions create con i flag --push-endpoint e --message-filter:

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

Sostituisci quanto segue:

  • SUBSCRIPTION_ID: l'ID della sottoscrizione da creare
  • TOPIC_ID: l'ID dell'argomento da collegare alla sottoscrizione
  • PUSH_ENDPOINT: l'URL del server su cui viene eseguito il sottoscrittore push
  • FILTER: un'espressione nella sintassi di filtro

REST

Per creare una sottoscrizione con un filtro, utilizza il metodo projects.subscriptions.create.

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

Sostituisci quanto segue:

  • PROJECT_ID: l'ID del progetto in cui creare la sottoscrizione
  • SUBSCRIPTION_ID: l'ID della sottoscrizione da creare

Per creare una sottoscrizione pull con un filtro, specifica il filtro nel corpo della richiesta:

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

Sostituisci quanto segue:

  • PROJECT_ID: l'ID del progetto con l'argomento
  • TOPIC_ID: l'ID dell'argomento da collegare alla sottoscrizione
  • FILTER: un'espressione nella sintassi di filtro

Per creare una sottoscrizione push con un filtro, specifica l'endpoint push e il filtro nel corpo della richiesta:

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

Sostituisci quanto segue:

  • PROJECT_ID: l'ID del progetto con l'argomento
  • TOPIC_ID: l'ID dell'argomento da collegare alla sottoscrizione
  • PUSH_ENDPOINT: l'URL del server su cui viene eseguito il sottoscrittore push
  • FILTER: un'espressione nella sintassi di filtro

C++

Prima di provare questo esempio, segui le istruzioni di configurazione di C++ riportate nella Guida rapida sull'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API C++ 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#

Prima di provare questo esempio, segui le istruzioni di configurazione di C# nella Guida rapida sull'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API C# di 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;
    }
}

Go

Prima di provare questo esempio, segui le istruzioni di configurazione di Go nella Guida rapida sull'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Go Pub/Sub.

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/pubsub"
)

func createWithFilter(w io.Writer, projectID, subID, filter string, topic *pubsub.Topic) error {
	// Receive messages with attribute key "author" and value "unknown".
	// projectID := "my-project-id"
	// subID := "my-sub"
	// filter := "attributes.author=\"unknown\""
	// topic of type https://godoc.org/cloud.google.com/go/pubsub#Topic
	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.CreateSubscription(ctx, subID, pubsub.SubscriptionConfig{
		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

Prima di provare questo esempio, segui le istruzioni di configurazione Java in Guida rapida sull'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Java 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

Prima di provare questo esempio, segui le istruzioni di configurazione di Node.js in Guida rapida sull'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Node.js 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

Prima di provare questo esempio, segui le istruzioni di configurazione di Node.js in Guida rapida sull'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Node.js 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

Prima di provare questo esempio, segui le istruzioni di configurazione PHP nella Guida rapida sull'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'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

Prima di provare questo esempio, segui le istruzioni di configurazione di Python in Guida rapida sull'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'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

Prima di provare questo esempio, segui le istruzioni di configurazione di Ruby riportate in Guida rapida sull'utilizzo delle librerie client. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Ruby Pub/Sub.

require "google/cloud/pubsub"

# Shows how to create a new subscription with filter for a given topic
class PubsubCreateSubscriptionWithFilter
  def create_subscription_with_filter project_id:, topic_id:, subscription_id:, filter:
    pubsub = Google::Cloud::Pubsub.new project_id: project_id
    topic = pubsub.topic topic_id
    subscription = topic.subscribe subscription_id, filter: filter
    puts "Created subscription with filtering enabled: #{subscription_id}"
  end

  def self.run
    # TODO(developer): Replace these variables before running the sample.
    project_id = "your-project-id"
    topic_id = "your-topic-id"
    subscription_id = "id-for-new-subcription"
    filter = "attributes.author=\"unknown\""
    PubsubCreateSubscriptionWithFilter.new.create_subscription_with_filter project_id: project_id,
                                                                           topic_id: topic_id,
                                                                           subscription_id: subscription_id,
                                                                           filter: filter
  end
end

if $PROGRAM_NAME == __FILE__
  PubsubCreateSubscriptionWithFilter.run
end

La lunghezza massima di un filtro è 256 byte. Il filtro è una proprietà immutabile di una sottoscrizione. Dopo aver creato una sottoscrizione, non puoi aggiornarla per modificare il filtro.

Impatto dei filtri sulle metriche del backlog

Per monitorare l'abbonamento appena creato, consulta Monitorare gli abbonamenti con i filtri.

Se hai abilitato i filtri, le metriche del backlog includono solo i dati dei messaggi che corrispondono al filtro. Di seguito è riportato un elenco delle metriche del backlog:

  • 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

Per saperne di più su queste metriche, consulta l'elenco delle metriche Pub/Sub.

Aggiornare il filtro per un abbonamento

Non puoi aggiornare il filtro per un abbonamento esistente. Segui invece questa soluzione alternativa.

  1. Acquisisci un'istantanea della sottoscrizione per cui vuoi modificare il filtro.

    Per saperne di più su come acquisire uno snapshot utilizzando la console, consulta Creazione di uno snapshot.

  2. Crea una nuova sottoscrizione con il nuovo filtro.

    Per saperne di più sulla creazione di una sottoscrizione con un filtro, consulta Creare un abbonamento con un filtro.

  3. Nella console Google Cloud, vai alla pagina Abbonamenti Pub/Sub.

    Vai agli abbonamenti

  4. Fai clic sull'abbonamento appena creato.

  5. Nella pagina dei dettagli dell'abbonamento, fai clic su Riproduci i messaggi.

  6. In Ricerca, fai clic su A un'istantanea.

  7. Seleziona lo snapshot che hai creato per l'abbonamento originale nel passaggio 1, quindi fai clic su Cerca.

    Non perderai alcun messaggio durante la transizione.

  8. Modifica gli abbonati per usare il nuovo abbonamento.

Dopo aver completato la procedura, puoi procedere ed eliminare l'abbonamento originale.

Sintassi per creare un filtro

Per filtrare i messaggi, scrivi un'espressione che operi sugli attributi. Puoi scrivere un'espressione che corrisponda alla chiave o al valore degli attributi. L'identificatore attributes seleziona gli attributi nel messaggio.

Ad esempio, i filtri nella seguente tabella selezionano l'attributo name:

Filtro Descrizione
attributes:name Messaggi con l'attributo name
NOT attributes:name Messaggi senza l'attributo name
attributes.name = "com" Messaggi con l'attributo name e il valore di com
attributes.name != "com" Messaggi senza l'attributo name e il valore com
hasPrefix(attributes.name, "co") Messaggi con l'attributo name e un valore che inizia con co
NOT hasPrefix(attributes.name, "co") Messaggi senza l'attributo name e un valore che inizia con co

Operatori di confronto per l'espressione di filtro

Puoi filtrare gli attributi con i seguenti operatori di confronto:

  • :
  • =
  • !=

L'operatore : corrisponde a una chiave in un elenco di attributi.

attributes:KEY

Gli operatori di uguaglianza associano chiavi e valori. Il valore deve essere un valore letterale stringa.

attributes.KEY = "VALUE"

Un'espressione con un operatore di uguaglianza deve iniziare con una chiave e l'operatore di uguaglianza deve confrontare una chiave e un valore.

  • Valido: il filtro confronta una chiave e un valore

    attributes.name = "com"
    
  • Non valido: sul lato sinistro del filtro è presente un valore

    "com" = attributes.name
    
  • Non valida: il filtro confronta due chiavi

    attributes.name = attributes.website
    

La chiave e il valore sono sensibili alle maiuscole e devono corrispondere esattamente all'attributo. Se una chiave contiene caratteri diversi da trattini, trattini bassi o caratteri alfanumerici, utilizza un valore letterale stringa.

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

Per utilizzare barre rovesciate, virgolette e caratteri non stampabili in un filtro, esegui l'escape dei caratteri all'interno di un valore letterale stringa. Puoi anche utilizzare sequenze di escape Unicode, esadecimale e ottale all'interno di un valore letterale stringa.

  • Valido: il filtro esegue l'escape dei caratteri all'interno di un valore letterale stringa.

    attributes:"\u307F\u3093\u306A"
    
  • Non valido: il filtro esegue l'escape dei caratteri senza un valore letterale stringa.

    attributes:\u307F\u3093\u306A
    

Operatori booleani per l'espressione di filtro

Puoi utilizzare gli operatori booleani AND, NOT e OR in un filtro. Gli operatori devono essere in lettere maiuscole. Ad esempio, il seguente filtro è per i messaggi con l'attributo iana.org/language_tag, ma senza l'attributo name e il valore com.

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

L'operatore NOT ha la precedenza più alta. Per combinare gli operatori AND e OR, utilizza le parentesi e le espressioni complete.

  • Validi: operatori AND e OR con parentesi

    attributes:"iana.org/language_tag" AND (attributes.name = "net" OR attributes.name = "org")
    
  • Non valido: operatori AND e OR senza parentesi

    attributes:"iana.org/language_tag" AND attributes.name = "net" OR attributes.name = "org"
    
  • Non valido: gli operatori AND e OR combinano espressioni incomplete

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

Puoi anche utilizzare l'operatore meno unario anziché l'operatore NOT.

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

Funzioni per l'espressione di filtro

Puoi utilizzare la funzione hasPrefix per filtrare in base agli attributi con valori che iniziano con una sottostringa. hasPrefix è l'unica funzione supportata in un filtro.

Sebbene la corrispondenza dei prefissi sia supportata con la funzione hasPrefix, le espressioni regolari generali non sono supportate.

hasPrefix(attributes.KEY, "SUBSTRING")

Sostituisci quanto segue:

  • KEY: il nome dell'attributo
  • SUBSTRING: una sottostringa del valore