Buscar con incrustaciones de vectores

En esta página se muestra cómo usar Firestore para realizar búsquedas vectoriales de los k vecinos más cercanos (KNN) mediante las siguientes técnicas:

  • Almacenar valores de vector
  • Crear y gestionar índices vectoriales de vecinos más cercanos (KNN)
  • Haz una consulta de k vecinos más cercanos (KNN) con una de las medidas de distancia de vector admitidas.

Antes de empezar

Antes de almacenar las inserciones en Firestore, debes generar inserciones de vectores. Firestore no genera las inserciones. Puedes usar un servicio como Vertex AI para crear valores vectoriales, por ejemplo, inserciones de texto a partir de tus datos de Firestore. Después, puedes volver a almacenar estas inserciones en documentos de Firestore.

Para obtener más información sobre las inserciones, consulta el artículo ¿Qué son las inserciones?

Para saber cómo obtener incrustaciones de texto con Vertex AI, consulta Obtener incrustaciones de texto.

Almacenar incrustaciones de vectores

En los siguientes ejemplos se muestra cómo almacenar inserciones vectoriales en Firestore.

Operación de escritura con una incrustación de vector

En el siguiente ejemplo se muestra cómo almacenar una inserción vectorial en un documento de Firestore:

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();

Calcular las inserciones vectoriales con una función de Cloud

Para calcular y almacenar las inserciones vectoriales cada vez que se actualice o se cree un documento, puedes configurar una función de Cloud Run:

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

Crear y gestionar índices vectoriales

Para poder realizar una búsqueda de los vecinos más cercanos con tus inserciones de vectores, debes crear un índice correspondiente. En los siguientes ejemplos se muestra cómo crear y gestionar índices vectoriales con Google Cloud CLI. Los índices vectoriales también se pueden gestionar con la CLI de Firebase y Terraform.

Crear un índice vectorial

Antes de crear un índice vectorial, actualiza a la versión más reciente de la CLI de Google Cloud:

gcloud components update

Para crear un índice vectorial, usa 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

donde:

  • collection-group es el ID del grupo de colecciones.
  • vector-field es el nombre del campo que contiene la incrustación de vector.
  • database-id es el ID de la base de datos.
  • vector-configuration incluye el vector dimension y el tipo de índice. dimension es un número entero de hasta 2048. El tipo de índice debe ser flat. Formatea la configuración del índice de la siguiente manera: {"dimension":"DIMENSION", "flat": "{}"}.

En el siguiente ejemplo se crea un índice compuesto que incluye un índice vectorial para el campo vector-field y un índice ascendente para el campo color. Puedes usar este tipo de índice para prefiltrar datos antes de una búsqueda de vecinos más próximos.

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

Mostrar todos los índices vectoriales

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

Sustituye database-id por el ID de la base de datos.

Eliminar un índice vectorial

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

donde:

  • index-id es el ID del índice que se va a eliminar. Usa indexes composite list para obtener el ID del índice.
  • database-id es el ID de la base de datos.

Describe un índice de vectores

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

donde:

  • index-id es el ID del índice que se va a describir. Usa o indexes composite list para obtener el ID de índice.
  • database-id es el ID de la base de datos.

Hacer una consulta de vecinos más cercanos

Puedes hacer una búsqueda de similitud para encontrar los vecinos más cercanos de una inserción de vector. Las búsquedas por similitud requieren índices vectoriales. Si no existe ningún índice, Firestore sugiere crear uno con la CLI de gcloud.

En el ejemplo siguiente se buscan los 10 vecinos más cercanos del vector de consulta.

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();

Distancias de vectores

Las consultas de vecinos más cercanos admiten las siguientes opciones de distancia vectorial:

  • EUCLIDEAN: mide la distancia EUCLIDIANA entre los vectores. Para obtener más información, consulta Euclídea.
  • COSINE: compara vectores en función del ángulo entre ellos, lo que te permite medir la similitud que no se basa en la magnitud de los vectores. Te recomendamos que uses DOT_PRODUCT con vectores normalizados por unidad en lugar de la distancia COSENO, que es matemáticamente equivalente y ofrece un mejor rendimiento. Para obtener más información, consulta el artículo Similitud de coseno.
  • DOT_PRODUCT: es similar a COSINE, pero se ve afectada por la magnitud de los vectores. Para obtener más información, consulta el artículo Producto escalar.

Elige la medida de distancia

En función de si todos tus embeddings de vectores están normalizados o no, puedes determinar qué medida de distancia usar para encontrar la medida de distancia. Una inserción de vector normalizada tiene una magnitud (longitud) de exactamente 1,0.

Además, si sabes con qué medida de distancia se ha entrenado tu modelo, úsala para calcular la distancia entre tus inserciones de vectores.

Datos normalizados

Si tiene un conjunto de datos en el que todas las inserciones vectoriales están normalizadas, las tres medidas de distancia proporcionarán los mismos resultados de búsqueda semántica. En esencia, aunque cada medida de distancia devuelve un valor diferente, esos valores se ordenan de la misma forma. Cuando se normalizan las inserciones, DOT_PRODUCT suele ser la opción más eficiente desde el punto de vista computacional, pero la diferencia es insignificante en la mayoría de los casos. Sin embargo, si tu aplicación es muy sensible al rendimiento, DOT_PRODUCT puede ayudarte a optimizarlo.

Datos no normalizados

Si tienes un conjunto de datos en el que las incrustaciones de vectores no están normalizadas, no es correcto matemáticamente usar DOT_PRODUCT como medida de distancia, ya que el producto escalar no mide la distancia. En función de cómo se hayan generado las inserciones y del tipo de búsqueda que se prefiera, la medida de distancia COSINE o EUCLIDEAN produce resultados de búsqueda que son subjetivamente mejores que las otras medidas de distancia. Puede que tengas que experimentar con COSINE o EUCLIDEAN para determinar cuál es la mejor opción para tu caso práctico.

No sabes si los datos están normalizados o no

Si no sabes si tus datos están normalizados o no y quieres usar DOT_PRODUCT, te recomendamos que uses COSINE. COSINE es como DOT_PRODUCT, pero con la normalización integrada. La distancia medida con COSINE va de 0 a 2. Un resultado cercano a 0 indica que los vectores son muy similares.

Prefiltrar documentos

Para prefiltrar documentos antes de encontrar los vecinos más cercanos, puedes combinar una búsqueda de similitud con otros operadores de consulta. Se admiten los filtros compuestos and y or. Para obtener más información sobre los filtros de campo admitidos, consulta Operadores de consulta.

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();

Recupera la distancia vectorial calculada.

Puedes obtener la distancia vectorial calculada asignando un nombre de propiedad de salida distance_result_fieldFindNearest a la consulta, como se muestra en el siguiente ejemplo:

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"));
}

Si quieres usar una máscara de campo para devolver un subconjunto de campos de documento junto con un distanceResultField, también debes incluir el valor de distanceResultField en la máscara de campo, como se muestra en el siguiente ejemplo:

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"));
}

Especificar un umbral de distancia

Puedes especificar un umbral de similitud que devuelva solo los documentos que estén dentro de ese umbral. El comportamiento del campo de umbral depende de la medida de distancia que elijas:

  • Las distancias EUCLIDEAN y COSINE limitan el umbral a los documentos en los que la distancia es inferior o igual al umbral especificado. Estas medidas de distancia disminuyen a medida que los vectores se vuelven más similares.
  • DOT_PRODUCT limita el umbral a los documentos en los que la distancia es mayor o igual que el umbral especificado. Las distancias del producto escalar aumentan a medida que los vectores se vuelven más similares.

En el siguiente ejemplo se muestra cómo especificar un umbral de distancia para devolver hasta 10 documentos más cercanos que estén a una distancia máxima de 4,5 unidades mediante la métrica de distancia EUCLIDEAN:

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());
}

Limitaciones

Cuando trabajes con incrustaciones de vectores, ten en cuenta las siguientes limitaciones:

  • La dimensión máxima admitida de las inserciones es 2048. Para almacenar índices más grandes, usa la reducción de dimensionalidad.
  • El número máximo de documentos que se pueden devolver en una consulta de vecinos más cercanos es 1000.
  • La búsqueda vectorial no admite listeners de la vista de tiempo real.
  • Solo las bibliotecas de cliente de Python, Node.js, Go y Java admiten la búsqueda vectorial.

Siguientes pasos