Mit Vektoreinbettungen suchen

Auf dieser Seite erfahren Sie, wie Sie mit Firestore K-Nearest-Neighbor-Vektorsuchen (KNN) mit den folgenden Techniken durchführen:

  • Vektorwerte speichern
  • KNN-Vektorindexe erstellen und verwalten
  • Eine KNN-Abfrage (K-Nearest-Neighbor) mit einem der unterstützten Vektordistanzmesswerte erstellen

Hinweis

Bevor Sie Einbettungen in Firestore speichern, müssen Sie Vektoreinbettungen generieren. Firestore generiert die Einbettungen nicht. Sie können einen Dienst wie Vertex AI verwenden, um Vektorwerte zu erstellen, z. B. Texteinbettungen aus Ihren Firestore-Daten. Anschließend können Sie diese Einbettungen wieder in Firestore-Dokumenten speichern.

Weitere Informationen zu Einbettungen finden Sie unter Was sind Einbettungen?

Informationen zum Abrufen von Texteinbettungen mit Vertex AI finden Sie unter Texteinbettungen abrufen.

Vektoreinbettungen speichern

Die folgenden Beispiele zeigen, wie Sie Vektoreinbettungen in Firestore speichern.

Schreibvorgang mit einer Vektoreinbettung

Das folgende Beispiel zeigt, wie Sie eine Vektoreinbettung in einem Firestore-Dokument speichern:

Python
from google.cloud import firestore
from google.cloud.firestore_v1.vector import Vector

firestore_client = firestore.Client()
collection = firestore_client.collection("coffee-beans")
doc = {
    "name": "Kahawa coffee beans",
    "description": "Information about the Kahawa coffee beans.",
    "embedding_field": Vector([0.18332680, 0.24160706, 0.3416704]),
}

collection.add(doc)
Node.js
import {
  Firestore,
  FieldValue,
} from "@google-cloud/firestore";

const db = new Firestore();
const coll = db.collection('coffee-beans');
await coll.add({
  name: "Kahawa coffee beans",
  description: "Information about the Kahawa coffee beans.",
  embedding_field: FieldValue.vector([1.0 , 2.0, 3.0])
});
Go
import (
	"context"
	"fmt"
	"io"

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

type CoffeeBean struct {
	Name           string             `firestore:"name,omitempty"`
	Description    string             `firestore:"description,omitempty"`
	EmbeddingField firestore.Vector32 `firestore:"embedding_field,omitempty"`
	Color          string             `firestore:"color,omitempty"`
}

func storeVectors(w io.Writer, projectID string) error {
	ctx := context.Background()

	// Create client
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	// Vector can be represented by Vector32 or Vector64
	doc := CoffeeBean{
		Name:           "Kahawa coffee beans",
		Description:    "Information about the Kahawa coffee beans.",
		EmbeddingField: []float32{1.0, 2.0, 3.0},
		Color:          "red",
	}
	ref := client.Collection("coffee-beans").NewDoc()
	if _, err = ref.Set(ctx, doc); err != nil {
		fmt.Fprintf(w, "failed to upsert: %v", err)
		return err
	}

	return nil
}
Java
import com.google.cloud.firestore.CollectionReference;
import com.google.cloud.firestore.DocumentReference;
import com.google.cloud.firestore.FieldValue;
import com.google.cloud.firestore.VectorQuery;

CollectionReference coll = firestore.collection("coffee-beans");

Map<String, Object> docData = new HashMap<>();
docData.put("name", "Kahawa coffee beans");
docData.put("description", "Information about the Kahawa coffee beans.");
docData.put("embedding_field", FieldValue.vector(new double[] {1.0, 2.0, 3.0}));

ApiFuture<DocumentReference> future = coll.add(docData);
DocumentReference documentReference = future.get();

Vektoreinbettungen mit einer Cloud Function berechnen

Wenn Sie Vektoreinbettungen berechnen und speichern möchten, wenn ein Dokument aktualisiert oder erstellt wird, können Sie eine Cloud Run-Funktion einrichten:

Python
@functions_framework.cloud_event
def store_embedding(cloud_event) -> None:
  """Triggers by a change to a Firestore document.
  """
  firestore_payload = firestore.DocumentEventData()
  payload = firestore_payload._pb.ParseFromString(cloud_event.data)

  collection_id, doc_id = from_payload(payload)
  # Call a function to calculate the embedding
  embedding = calculate_embedding(payload)
  # Update the document
  doc = firestore_client.collection(collection_id).document(doc_id)
  doc.set({"embedding_field": embedding}, merge=True)
Node.js
/**
 * A vector embedding will be computed from the
 * value of the `content` field. The vector value
 * will be stored in the `embedding` field. The
 * field names `content` and `embedding` are arbitrary
 * field names chosen for this example.
 */
async function storeEmbedding(event: FirestoreEvent<any>): Promise<void> {
  // Get the previous value of the document's `content` field.
  const previousDocumentSnapshot = event.data.before as QueryDocumentSnapshot;
  const previousContent = previousDocumentSnapshot.get("content");

  // Get the current value of the document's `content` field.
  const currentDocumentSnapshot = event.data.after as QueryDocumentSnapshot;
  const currentContent = currentDocumentSnapshot.get("content");

  // Don't update the embedding if the content field did not change
  if (previousContent === currentContent) {
    return;
  }

  // Call a function to calculate the embedding for the value
  // of the `content` field.
  const embeddingVector = calculateEmbedding(currentContent);

  // Update the `embedding` field on the document.
  await currentDocumentSnapshot.ref.update({
    embedding: embeddingVector,
  });
}
Go
  // Not yet supported in the Go client library
Java
  // Not yet supported in the Java client library

Vektorindexe erstellen und verwalten

Bevor Sie eine Suche nach dem nächsten Nachbarn mit Ihren Vektoreinbettungen durchführen können, müssen Sie einen entsprechenden Index erstellen. Die folgenden Beispiele zeigen, wie Sie Vektorindexe mit der Google Cloud CLI und der Console erstellen und verwalten. Sie können Vektorindexe auch mit der Firebase CLI und Terraform verwalten.

Vektorindex erstellen

Google Cloud Console

So erstellen Sie manuell einen neuen Index über die Google Cloud Console:

  1. Rufen Sie in der Google Cloud Console die Seite Datenbanken auf.

    Zur Seite „Datenbanken“

  2. Wählen Sie die benötigte Datenbank aus der Liste der Datenbanken aus.
  3. Klicken Sie im Navigationsmenü auf Indexe und dann auf den Manuell Tab.
  4. Klicken Sie auf Index erstellen.

    Wenn Sie ein Vektorfeld für Vektorsuchen indexieren möchten, wählen Sie Vektorindex erstellen aus.

  5. Geben Sie eine Sammlungs-ID ein. Geben Sie einen Vektorfeldpfad und die Anzahl der Vektoreinbettungsdimensionen ein. Fügen Sie die Namen aller zusätzlichen Felder, die Sie indexieren möchten, sowie einen Indexmodus für jedes Feld hinzu.

    Klicken Sie auf Index speichern.

Ihr neuer Index wird in der Liste der manuellen Indexe angezeigt und Firestore beginnt mit dem Erstellen des Index. Wenn der Index angelegt ist, wird neben dem Index ein grünes Häkchen angezeigt.

gcloud

Bevor Sie einen Vektorindex erstellen, führen Sie ein Upgrade auf die neueste Version der Google Cloud CLI durch:

gcloud components update

Verwenden Sie gcloud firestore indexes composite create, um einen Vektorindex zu erstellen:

gcloud firestore indexes composite create \
--collection-group=collection-group \
--query-scope=COLLECTION \
--field-config field-path=vector-field,vector-config='vector-configuration' \
--database=database-id

Dabei gilt:

  • collection-group ist die ID der Sammlungsgruppe.
  • vector-field ist der Name des Felds, das die Vektoreinbettung enthält.
  • database-id ist die ID der Datenbank.
  • vector-configuration enthält den Vektor dimension und den Indextyp. Das dimension ist eine Ganzzahl bis zu 2048. Der Indextyp muss flat sein. Formatieren Sie die Indexkonfiguration so: {"dimension":"DIMENSION", "flat": "{}"}.

Im folgenden Beispiel wird ein zusammengesetzter Index erstellt, einschließlich eines Vektorindex für das Feld vector-field und eines aufsteigenden Index für das Feld color. Mit dieser Art von Index können Sie Daten vorfiltern vor einer Suche nach dem nächsten Nachbarn.

gcloud firestore indexes composite create \
--collection-group=collection-group \
--query-scope=COLLECTION \
--field-config=order=ASCENDING,field-path="color" \
--field-config field-path=vector-field,vector-config='{"dimension":"1024", "flat": "{}"}' \
--database=database-id

Alle Vektorindexe auflisten

Google Cloud Console

  1. Rufen Sie in der Google Cloud Console die Seite Datenbanken auf.

    Zur Seite „Datenbanken“

  2. Wählen Sie die benötigte Datenbank aus der Liste der Datenbanken aus.
  3. Klicken Sie im Navigationsmenü auf Indexe und dann auf den Manuell Tab.

    In der Tabelle „Indexe“ sind alle Indexe für die Datenbank aufgeführt. Vektorindexe enthalten ein Vektorfeld mit einem Symbol.

gcloud

So listen Sie alle Indexe auf und rufen Index-IDs ab:

gcloud firestore indexes composite list --database=database-id

Ersetzen Sie database-id durch die ID der Datenbank.

Mit der Index-ID können Sie weitere Details zu einem Index aufrufen:

gcloud firestore indexes composite describe index-id --database=database-id

Dabei gilt:

  • index-id ist die ID des zu beschreibenden Index.
  • database-id ist die ID der Datenbank.

Vektorindex löschen

Google Cloud Console

  1. Rufen Sie in der Google Cloud Console die Seite Datenbanken auf.

    Zur Seite „Datenbanken“

  2. Wählen Sie die benötigte Datenbank aus der Liste der Datenbanken aus.
  3. Klicken Sie im Navigationsmenü auf Indexe und dann auf den Manuell Tab.

  4. Klicken Sie in der Liste Ihrer manuellen Indexe auf die Schaltfläche Mehr für den Index, den Sie löschen möchten. Klicken Sie auf Löschen.
  5. Bestätigen Sie, dass dieser Index gelöscht werden soll. Klicken Sie dafür in der Benachrichtigung auf Index löschen .
gcloud
gcloud firestore indexes composite delete index-id --database=database-id

Dabei gilt:

  • index-id ist die ID des zu löschenden Index. Verwenden Sie indexes composite list, um die Index-ID abzurufen.
  • database-id ist die ID der Datenbank.

Suche nach dem nächsten Nachbarn durchführen

Sie können eine Ähnlichkeitssuche durchführen, um die nächsten Nachbarn einer Vektoreinbettung zu finden. Für Ähnlichkeitssuchen sind Vektorindexe erforderlich. Wenn kein Index vorhanden ist, schlägt Firestore einen Index vor, der mit der gcloud CLI erstellt werden kann.

Im folgenden Beispiel werden die 10 nächsten Nachbarn des Abfragevektors gesucht.

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector

collection = db.collection("coffee-beans")

# Requires a single-field vector index
vector_query = collection.find_nearest(
    vector_field="embedding_field",
    query_vector=Vector([0.3416704, 0.18332680, 0.24160706]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=5,
)
Node.js
import {
  Firestore,
  FieldValue,
  VectorQuery,
  VectorQuerySnapshot,
} from "@google-cloud/firestore";

// Requires a single-field vector index
const vectorQuery: VectorQuery = coll.findNearest({
  vectorField: 'embedding_field',
  queryVector: [3.0, 1.0, 2.0],
  limit: 10,
  distanceMeasure: 'EUCLIDEAN'
});

const vectorQuerySnapshot: VectorQuerySnapshot = await vectorQuery.get();
Go
import (
	"context"
	"fmt"
	"io"

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

func vectorSearchBasic(w io.Writer, projectID string) error {
	ctx := context.Background()

	// Create client
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Requires a vector index
	// https://firebase.google.com/docs/firestore/vector-search#create_and_manage_vector_indexes
	vectorQuery := collection.FindNearest("embedding_field",
		[]float32{3.0, 1.0, 2.0},
		5,
		// More info: https://firebase.google.com/docs/firestore/vector-search#vector_distances
		firestore.DistanceMeasureEuclidean,
		nil)

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintln(w, doc.Data()["name"])
	}
	return nil
}
Java
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery vectorQuery = coll.findNearest(
        "embedding_field",
        new double[] {3.0, 1.0, 2.0},
        /* limit */ 10,
        VectorQuery.DistanceMeasure.EUCLIDEAN);

ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

Vektorentfernungen

Bei Suchanfragen nach dem nächsten Nachbarn werden die folgenden Optionen für die Vektorentfernung unterstützt:

  • EUCLIDEAN: Misst die EUCLIDEAN-Entfernung zwischen den Vektoren. Weitere Informationen finden Sie unter Euklidische Entfernung.
  • COSINE: Vergleicht Vektoren anhand des Winkels zwischen ihnen. So können Sie die Ähnlichkeit messen, die nicht auf der Größe der Vektoren basiert. Wir empfehlen, DOT_PRODUCT mit einheitsnormalisierten Vektoren anstelle der Kosinus-Entfernung zu verwenden. Das ist mathematisch gleichwertig und bietet eine bessere Leistung. Weitere Informationen finden Sie unter Kosinus-Ähnlichkeit.
  • DOT_PRODUCT: Ähnlich wie COSINE, wird aber von der Größe der Vektoren beeinflusst. Weitere Informationen finden Sie unter Punktprodukt.

Distanzmesswert auswählen

Je nachdem, ob alle Vektoreinbettungen normalisiert sind oder nicht, können Sie bestimmen, welcher Distanzmesswert verwendet werden soll. Eine normalisierte Vektoreinbettung hat eine Größe (Länge) von genau 1,0.

Wenn Sie außerdem wissen, mit welchem Distanzmesswert Ihr Modell trainiert wurde, verwenden Sie diesen Distanzmesswert, um die Entfernung zwischen Ihren Vektoreinbettungen zu berechnen.

Normalisierte Daten

Wenn Sie ein Dataset haben, in dem alle Vektoreinbettungen normalisiert sind, liefern alle drei Distanzmesswerte dieselben semantischen Suchergebnisse. Obwohl jeder Distanzmesswert einen anderen Wert zurückgibt, werden diese Werte auf dieselbe Weise sortiert. Wenn Einbettungen normalisiert sind, ist DOT_PRODUCT in der Regel die recheneffizienteste Methode, aber der Unterschied ist in den meisten Fällen vernachlässigbar. Wenn Ihre Anwendung jedoch sehr leistungsabhängig ist, kann DOT_PRODUCT bei der Leistungsoptimierung helfen.

Nicht normalisierte Daten

Wenn Sie ein Dataset haben, in dem Vektoreinbettungen nicht normalisiert sind, ist es mathematisch nicht korrekt, DOT_PRODUCT als Distanzmesswert zu verwenden, da das Punktprodukt keine Entfernung misst. Je nachdem, wie die Einbettungen generiert wurden und welche Art von Suche bevorzugt wird, liefert entweder der Distanzmesswert COSINE oder EUCLIDEAN Suchergebnisse, die subjektiv besser sind als die anderen Distanzmesswerte. Möglicherweise müssen Sie mit COSINE oder EUCLIDEAN experimentieren, um zu ermitteln, welcher Messwert für Ihren Anwendungsfall am besten geeignet ist.

Nicht sicher, ob Daten normalisiert oder nicht normalisiert sind

Wenn Sie nicht sicher sind, ob Ihre Daten normalisiert sind, und Sie DOT_PRODUCT verwenden möchten, empfehlen wir stattdessen COSINE. COSINE ist wie DOT_PRODUCT, aber mit integrierter Normalisierung. Die mit COSINE gemessene Entfernung liegt zwischen 0 und 2. Ein Ergebnis, das nahe bei 0 liegt, deutet darauf hin, dass die Vektoren sehr ähnlich sind.

Dokumente vorfiltern

Wenn Sie Dokumente vorfiltern möchten, bevor Sie die nächsten Nachbarn suchen, können Sie eine Ähnlichkeitssuche mit anderen Abfrageoperatoren kombinieren. Die zusammengesetzten Filter and und or werden unterstützt. Weitere Informationen zu unterstützten Feldfiltern finden Sie unter Abfrageoperatoren.

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector

collection = db.collection("coffee-beans")

# Similarity search with pre-filter
# Requires a composite vector index
vector_query = collection.where("color", "==", "red").find_nearest(
    vector_field="embedding_field",
    query_vector=Vector([0.3416704, 0.18332680, 0.24160706]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=5,
)
Node.js
// Similarity search with pre-filter
// Requires composite vector index
const preFilteredVectorQuery: VectorQuery = coll
    .where("color", "==", "red")
    .findNearest({
      vectorField: "embedding_field",
      queryVector: [3.0, 1.0, 2.0],
      limit: 5,
      distanceMeasure: "EUCLIDEAN",
    });

const vectorQueryResults = await preFilteredVectorQuery.get();
Go
import (
	"context"
	"fmt"
	"io"

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

func vectorSearchPrefilter(w io.Writer, projectID string) error {
	ctx := context.Background()

	// Create client
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Similarity search with pre-filter
	// Requires a composite vector index
	vectorQuery := collection.Where("color", "==", "red").
		FindNearest("embedding_field",
			[]float32{3.0, 1.0, 2.0},
			5,
			// More info: https://firebase.google.com/docs/firestore/vector-search#vector_distances
			firestore.DistanceMeasureEuclidean,
			nil)

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintln(w, doc.Data()["name"])
	}
	return nil
}
Java
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery preFilteredVectorQuery = coll
        .whereEqualTo("color", "red")
        .findNearest(
                "embedding_field",
                new double[] {3.0, 1.0, 2.0},
                /* limit */ 10,
                VectorQuery.DistanceMeasure.EUCLIDEAN);

ApiFuture<VectorQuerySnapshot> future = preFilteredVectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

Berechnete Vektorentfernung abrufen

Sie können die berechnete Vektorentfernung abrufen, indem Sie der Abfrage FindNearest einen Namen für die Ausgabeeigenschaft distance_result_field zuweisen, wie im folgenden Beispiel gezeigt:

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector

collection = db.collection("coffee-beans")

vector_query = collection.find_nearest(
    vector_field="embedding_field",
    query_vector=Vector([0.3416704, 0.18332680, 0.24160706]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=10,
    distance_result_field="vector_distance",
)

docs = vector_query.stream()

for doc in docs:
    print(f"{doc.id}, Distance: {doc.get('vector_distance')}")
Node.js
const vectorQuery: VectorQuery = coll.findNearest(
    {
      vectorField: 'embedding_field',
      queryVector: [3.0, 1.0, 2.0],
      limit: 10,
      distanceMeasure: 'EUCLIDEAN',
      distanceResultField: 'vector_distance'
    });

const snapshot: VectorQuerySnapshot = await vectorQuery.get();

snapshot.forEach((doc) => {
  console.log(doc.id, ' Distance: ', doc.get('vector_distance'));
});
Go
import (
	"context"
	"fmt"
	"io"

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

func vectorSearchDistanceResultField(w io.Writer, projectID string) error {
	ctx := context.Background()

	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Requires a vector index
	// https://firebase.google.com/docs/firestore/vector-search#create_and_manage_vector_indexes
	vectorQuery := collection.FindNearest("embedding_field",
		[]float32{3.0, 1.0, 2.0},
		10,
		firestore.DistanceMeasureEuclidean,
		&firestore.FindNearestOptions{
			DistanceResultField: "vector_distance",
		})

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintf(w, "%v, Distance: %v\n", doc.Data()["name"], doc.Data()["vector_distance"])
	}
	return nil
}
Java
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQueryOptions;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery vectorQuery = coll.findNearest(
        "embedding_field",
        new double[] {3.0, 1.0, 2.0},
        /* limit */ 10,
        VectorQuery.DistanceMeasure.EUCLIDEAN,
        VectorQueryOptions.newBuilder().setDistanceResultField("vector_distance").build());

ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

for (DocumentSnapshot document : vectorQuerySnapshot.getDocuments()) {
    System.out.println(document.getId() + " Distance: " + document.get("vector_distance"));
}

Wenn Sie eine Feldmaske verwenden möchten, um eine Teilmenge von Dokumentfeldern zusammen mit einem distanceResultField zurückzugeben, müssen Sie auch den Wert von distanceResultField in die Feldmaske einbeziehen, wie im folgenden Beispiel gezeigt:

Python
vector_query = collection.select(["color", "vector_distance"]).find_nearest(
    vector_field="embedding_field",
    query_vector=Vector([0.3416704, 0.18332680, 0.24160706]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=10,
    distance_result_field="vector_distance",
)
Node.js
const vectorQuery: VectorQuery = coll
    .select('name', 'description', 'vector_distance')
    .findNearest({
      vectorField: 'embedding_field',
      queryVector: [3.0, 1.0, 2.0],
      limit: 10,
      distanceMeasure: 'EUCLIDEAN',
      distanceResultField: 'vector_distance'
    });
Go
import (
	"context"
	"fmt"
	"io"

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

func vectorSearchDistanceResultFieldMasked(w io.Writer, projectID string) error {
	ctx := context.Background()

	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Requires a vector index
	// https://firebase.google.com/docs/firestore/vector-search#create_and_manage_vector_indexes
	vectorQuery := collection.Select("color", "vector_distance").
		FindNearest("embedding_field",
			[]float32{3.0, 1.0, 2.0},
			10,
			firestore.DistanceMeasureEuclidean,
			&firestore.FindNearestOptions{
				DistanceResultField: "vector_distance",
			})

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintf(w, "%v, Distance: %v\n", doc.Data()["color"], doc.Data()["vector_distance"])
	}
	return nil
}
Java
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQueryOptions;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery vectorQuery = coll
        .select("name", "description", "vector_distance")
        .findNearest(
          "embedding_field",
          new double[] {3.0, 1.0, 2.0},
          /* limit */ 10,
          VectorQuery.DistanceMeasure.EUCLIDEAN,
          VectorQueryOptions.newBuilder()
            .setDistanceResultField("vector_distance")
            .build());

ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

for (DocumentSnapshot document : vectorQuerySnapshot.getDocuments()) {
    System.out.println(document.getId() + " Distance: " + document.get("vector_distance"));
}

Entfernungsschwellenwert angeben

Sie können einen Ähnlichkeitsschwellenwert angeben, der nur Dokumente innerhalb des Schwellenwerts zurückgibt. Das Verhalten des Schwellenwertfelds hängt vom ausgewählten Distanzmesswert ab:

  • Bei den Entfernungen EUCLIDEAN und COSINE wird der Schwellenwert auf Dokumente beschränkt, bei denen die Entfernung kleiner oder gleich dem angegebenen Schwellenwert ist. Diese Distanzmesswerte nehmen ab, je ähnlicher die Vektoren werden.
  • Bei der Entfernung DOT_PRODUCT wird der Schwellenwert auf Dokumente beschränkt, bei denen die Entfernung größer oder gleich dem angegebenen Schwellenwert ist. Die Punktprodukt-Entfernungen nehmen zu, je ähnlicher die Vektoren werden.

Im folgenden Beispiel wird gezeigt, wie Sie einen Entfernungsschwellenwert angeben, um mit dem Distanzmesswert EUCLIDEAN bis zu 10 der nächsten Dokumente zurückzugeben, die maximal 4,5 Einheiten entfernt sind:

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector

collection = db.collection("coffee-beans")

vector_query = collection.find_nearest(
    vector_field="embedding_field",
    query_vector=Vector([0.3416704, 0.18332680, 0.24160706]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=10,
    distance_threshold=4.5,
)

docs = vector_query.stream()

for doc in docs:
    print(f"{doc.id}")
Node.js
const vectorQuery: VectorQuery = coll.findNearest({
  vectorField: 'embedding_field',
  queryVector: [3.0, 1.0, 2.0],
  limit: 10,
  distanceMeasure: 'EUCLIDEAN',
  distanceThreshold: 4.5
});

const snapshot: VectorQuerySnapshot = await vectorQuery.get();

snapshot.forEach((doc) => {
  console.log(doc.id);
});
Go
import (
	"context"
	"fmt"
	"io"

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

func vectorSearchDistanceThreshold(w io.Writer, projectID string) error {
	ctx := context.Background()

	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Requires a vector index
	// https://firebase.google.com/docs/firestore/vector-search#create_and_manage_vector_indexes
	vectorQuery := collection.FindNearest("embedding_field",
		[]float32{3.0, 1.0, 2.0},
		10,
		firestore.DistanceMeasureEuclidean,
		&firestore.FindNearestOptions{
			DistanceThreshold: firestore.Ptr[float64](4.5),
		})

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintln(w, doc.Data()["name"])
	}
	return nil
}
Java
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQueryOptions;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery vectorQuery = coll.findNearest(
        "embedding_field",
        new double[] {3.0, 1.0, 2.0},
        /* limit */ 10,
        VectorQuery.DistanceMeasure.EUCLIDEAN,
        VectorQueryOptions.newBuilder()
          .setDistanceThreshold(4.5)
          .build());

ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

for (DocumentSnapshot document : vectorQuerySnapshot.getDocuments()) {
    System.out.println(document.getId());
}

Beschränkungen

Beachten Sie bei der Arbeit mit Vektoreinbettungen die folgenden Beschränkungen:

  • Die maximal unterstützte Einbettungsdimension beträgt 2048. Verwenden Sie die Dimensionsreduktion, um größere Indexe zu speichern.
  • Die maximale Anzahl der Dokumente, die von einer Suche nach dem nächsten Nachbarn zurückgegeben werden können, beträgt 1.000 (nur Einschränkung für die Standard Edition).
  • Die Vektorsuche unterstützt keine Echtzeit-Snapshot-Listener.
  • Die Vektorsuche wird nur von den Clientbibliotheken Python, Node.js, Go und Java unterstützt.

Nächste Schritte