Mit Vektoreinbettungen suchen

Auf der Seite wird gezeigt, wie Sie mit Cloud Firestore KNN-Vektorsuchen (K-Nearest-Neighbor) mit den folgenden Methoden ausführen:

  • Vektorwerte speichern
  • KNN-Vektorindizes erstellen und verwalten
  • KNN-Abfrage (K-Nearest-Neighbor) mit einer der unterstützten Vektormesswerte für die Entfernung ausführen

Vektoreinbettungen speichern

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

Schreibvorgang mit einer Vektoreinbettung

Das folgende Beispiel zeigt, wie eine Vektor-Embedding in einem Cloud 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();

Vektor-Embeddings mit einer Cloud-Funktion berechnen

Wenn Sie Vektor-Embeddings jedes Mal berechnen und speichern möchten, wenn ein Dokument aktualisiert oder erstellt wird, können Sie eine Cloud Functions-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 mit Ihren Vektoreinbettungen eine Suche nach dem nächsten Nachbarn durchführen können, müssen Sie einen entsprechenden Index erstellen. In den folgenden Beispielen wird gezeigt, 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, aktualisieren Sie auf die neueste Version der Google Cloud CLI:

gcloud components update

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

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 Vektor-Embeddings enthält.
  • database-id ist die ID der Datenbank.
  • vector-configuration enthält den Vektor dimension und den Indextyp. dimension ist eine Ganzzahl bis 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 diesem Indextyp können Sie Daten vor einer Suche nach dem nächsten Nachbarn filtern.

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 oder indexes composite list, um die Index-ID abzurufen.
  • database-id ist die ID der Datenbank.

Abfrage nach nächsten Nachbarn

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

Im folgenden Beispiel werden die 10 nächsten Nachbarn des Abfragevektors 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();

Vektorabstände

Für Abfragen nach dem nächsten Nachbarn werden die folgenden Optionen für die Vektordistanz unterstützt:

  • EUCLIDEAN: Misst die EUKLIDISCHE Distanz zwischen den Vektoren. Weitere Informationen finden Sie unter Euklidischer Abstand.
  • COSINE: Vektoren werden anhand des Winkels zwischen ihnen verglichen. So lässt sich die Ähnlichkeit unabhängig von der Größe der Vektoren messen. Wir empfehlen, DOT_PRODUCT mit normalisierten Vektoren anstelle der KOSINUS-Distanz zu verwenden. Dies ist mathematisch äquivalent und bietet eine bessere Leistung. Weitere Informationen finden Sie unter Kosinusialhörigkeit.
  • DOT_PRODUCT: Ähnlich wie COSINE, wird aber von der Größe der Vektoren beeinflusst. Weitere Informationen finden Sie unter Skalarprodukt.

Maßeinheit für die Entfernung auswählen

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

Wenn Sie außerdem wissen, mit welchem Distanzmaß Ihr Modell trainiert wurde, verwenden Sie dieses Maß, um die Distanz zwischen Ihren Vektoreinbettungen zu berechnen.

Normalisierte Daten

Wenn Sie einen Datensatz haben, in dem alle Vektor-Ebenen normalisiert sind, liefern alle drei Abstandsmaße dieselben semantischen Suchergebnisse. Obwohl jedes Maß für die Entfernung einen anderen Wert zurückgibt, werden diese Werte im Grunde auf dieselbe Weise sortiert. Wenn Einbettungen normalisiert sind, ist DOT_PRODUCT in der Regel die leistungseffizienteste Option. Der Unterschied ist jedoch 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 einen Datensatz haben, in dem Vektoreinbettungen nicht normalisiert sind, ist es mathematisch nicht korrekt, DOT_PRODUCT als Maß für die Entfernung zu verwenden, da mit dem Skalarprodukt keine Entfernung gemessen wird. Je nachdem, wie die Einbettungen generiert wurden und welche Art von Suche bevorzugt wird, liefern entweder die COSINE- oder die EUCLIDEAN-Distanzmessung Suchergebnisse, die subjektiv besser sind als die der anderen Distanzmessungen. Es kann sein, dass Sie mit COSINE oder EUCLIDEAN experimentieren müssen, um herauszufinden, welche Option für Ihren Anwendungsfall am besten geeignet ist.

Nicht sicher, ob die Daten normalisiert sind

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

Dokumente vorfiltern

Wenn Sie Dokumente vor dem Finden der nächsten Nachbarn vorfiltern möchten, 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 Vektordistanz abrufen

Sie können die berechnete Vektordistanz abrufen, indem Sie der FindNearest-Abfrage 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 mithilfe eines Feldmaskens eine Teilmenge der Dokumentfelder zusammen mit einem distanceResultField zurückgeben möchten, müssen Sie auch den Wert von distanceResultField in die Feldmaske aufnehmen, 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"));
}

Einen Entfernungsgrenzwert angeben

Sie können einen Ähnlichkeitsgrenzwert angeben, mit dem nur Dokumente innerhalb des Grenzwerts zurückgegeben werden. Das Verhalten des Schwellenwertfelds hängt von der ausgewählten Entfernungsmessung ab:

  • Bei den Entfernungen EUCLIDEAN und COSINE wird der Grenzwert auf Dokumente beschränkt, bei denen die Entfernung kleiner oder gleich dem angegebenen Grenzwert ist. Diese Distanzmaße nehmen ab, je ähnlicher die Vektoren sind.
  • Mit DOT_PRODUCT distance wird der Grenzwert auf Dokumente beschränkt, bei denen der Abstand mindestens dem angegebenen Grenzwert entspricht. Die Punktprodukt-Distanzen steigen, je ähnlicher die Vektoren sind.

Im folgenden Beispiel wird gezeigt, wie Sie einen Grenzwert für die Entfernung angeben, um mithilfe des Entfernungsmesswerts EUCLIDEAN bis zu zehn der nächstgelegenen 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 ist 2.048. Wenn Sie größere Indexe speichern möchten, verwenden Sie die Dimensionseinschränkung.
  • Die maximale Anzahl von Dokumenten, die bei einer Abfrage vom Typ „Nächster Nachbar“ zurückgegeben werden, 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