Mit Vektoreinbettungen suchen

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

  • Vektorwerte speichern
  • KNN-Vektorindizes erstellen und verwalten
  • Eine KNN-Abfrage (K-Nearest-Neighbor) mit einer der unterstützten Vektordistanzmessungen erstellen

Vektoreinbettungen speichern

Sie können Vektorwerte wie Texteinbettungen aus Ihren Firestore-Daten erstellen und in Firestore-Dokumenten speichern.

Schreibvorgang mit einer Vektoreinbettung

Das folgende Beispiel zeigt, wie ein Vektorembedding in einem Firestore-Dokument gespeichert wird:

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-Funktion berechnen

Wenn Sie Vektoreinbettungen berechnen und speichern möchten, sobald 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 erstellen und verwalten. Vektorindexe können auch mit der Firebase CLI und Terraform verwaltet werden.

Vektorindex erstellen

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

gcloud components update

Verwenden Sie zum Erstellen eines Vektorindex gcloud firestore indexes composite create:

gcloud
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. dimension ist eine Ganzzahl bis zu 2.048. Der Indextyp muss flat sein. Formatieren Sie die Indexkonfiguration so: {"dimension":"DIMENSION", "flat": "{}"}.

Im folgenden Beispiel wird ein zusammengesetzter Index erstellt, der einen Vektorindex für das Feld vector-field und einen aufsteigenden Index für das Feld color enthält. Mit dieser Art von Index können Sie Daten vorfiltern, bevor Sie eine Suche nach dem nächsten Nachbarn durchführen.

gcloud
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

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

Ersetzen Sie database-id durch die ID der Datenbank.

Vektorindex 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.

Vektorindex beschreiben

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

Dabei gilt:

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

Abfrage nach nächsten Nachbarn erstellen

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

Im folgenden Beispiel werden die 10 nächsten Nachbarn des Anfragevektors ermittelt.

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

Für Nearest-Neighbor-Abfragen werden die folgenden Optionen für die Vektordistanz unterstützt:

  • EUCLIDEAN: Misst die EUKLIDISCHE Distanz zwischen den Vektoren. Weitere Informationen finden Sie unter Euklidisch.
  • 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 einheitlich normalisierten Vektoren anstelle der COSINE-Distanz zu verwenden, da dies mathematisch gleichwertig ist, aber eine bessere Leistung bietet. 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 Skalarprodukt.

Entfernungseinheit auswählen

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

Wenn Sie wissen, mit welchem Distanzmesswert Ihr Modell trainiert wurde, sollten Sie diesen Messwert auch zum Berechnen der Distanz zwischen Ihren Vektoreinbettungen verwenden.

Normalisierte Daten

Wenn Sie ein Dataset haben, in dem alle Vektoreinbettungen normalisiert sind, liefern alle drei Distanzmessungen dieselben semantischen Suchergebnisse. Im Grunde sortieren diese Werte auf dieselbe Weise, auch wenn jede Distanzmessung einen anderen Wert zurückgibt. Wenn Einbettungen normalisiert werden, ist DOT_PRODUCT in der Regel die recheneffizienteste Methode. Der Unterschied ist in den meisten Fällen jedoch 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 Distanzmaß zu verwenden, da das Skalarprodukt keine Distanz misst. Je nachdem, wie die Einbettungen generiert wurden und welche Art von Suche bevorzugt wird, liefert entweder das Distanzmaß COSINE oder EUCLIDEAN Suchergebnisse, die subjektiv besser sind als die anderen Distanzmaße. Möglicherweise müssen Sie mit COSINE oder EUCLIDEAN experimentieren, um herauszufinden, welche Methode für Ihren Anwendungsfall am besten geeignet ist.

Sie sind sich nicht sicher, ob die Daten normalisiert oder nicht normalisiert sind?

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

Dokumente vorfiltern

Wenn Sie Dokumente vor dem Suchen nach den nächsten Nachbarn vorfiltern möchten, können Sie eine Ähnlichkeitssuche mit anderen Suchoperatoren 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 Vektordistanz abrufen

Sie können die berechnete Vektordistanz abrufen, indem Sie der FindNearest-Anfrage einen distance_result_field-Ausgabeeigenschaftsnamen 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 einfügen, 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"));
}

Distanzschwellenwert angeben

Sie können einen Ähnlichkeitsschwellenwert angeben, sodass nur Dokumente innerhalb des Schwellenwerts zurückgegeben werden. Das Verhalten des Schwellenwertfelds hängt von der ausgewählten Distanzmessung ab:

  • Mit den Distanzen EUCLIDEAN und COSINE wird der Grenzwert auf Dokumente beschränkt, deren Distanz kleiner oder gleich dem angegebenen Grenzwert ist. Diese Distanzmaße nehmen ab, je ähnlicher die Vektoren werden.
  • DOT_PRODUCT schränkt den Grenzwert auf Dokumente ein, deren Distanz größer oder gleich dem angegebenen Grenzwert ist. Die Punktprodukt-Distanz nimmt zu, je ähnlicher die Vektoren werden.

Im folgenden Beispiel wird gezeigt, wie Sie einen Distanzschwellenwert angeben, um mit der Distanzmessung EUCLIDEAN bis zu 10 ähnlichste 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 Einschränkungen:

  • Die maximal unterstützte Einbettungsdimension beträgt 2.048. Um größere Indexe zu speichern, verwenden Sie die Dimensionsreduzierung.
  • Die maximale Anzahl der Dokumente, die von einer Nearest-Neighbor-Anfrage zurückgegeben werden sollen, beträgt 1.000.
  • Die Vektorsuche unterstützt keine Echtzeit-Snapshot-Listener.
  • Nur die Python-, Node.js-, Go- und Java-Clientbibliotheken unterstützen die Vektorsuche.

Nächste Schritte