Encontrar a opção mais próxima

Descrição

Realiza uma pesquisa de vetor vizinho mais próximo no campo embedding especificado usando o distance_measure solicitado.

Sintaxe

Node.js

const results = await db.pipeline()
  .collection("cities")
  .findNearest({
      field: 'embedding',
      vectorValue: vector([1.5, 2.345]),
      distanceMeasure: 'euclidean',
  })
  .execute();

Exemplos de clientes

Node.js
const results = await db.pipeline()
  .collection("cities")
  .findNearest({
      field: "embedding",
      vectorValue: [1.5, 2.345],
      distanceMeasure: "euclidean"
  })
  .execute();

Web

const results = await execute(db.pipeline()
  .collection("cities")
  .findNearest({
      field: "embedding",
      vectorValue: [1.5, 2.345],
      distanceMeasure: "euclidean"
  }));
Swift
let results = try await db.pipeline()
  .collection("cities")
  .findNearest(
    field: Field("embedding"),
    vectorValue: VectorValue([1.5, 2.345]),
    distanceMeasure: .euclidean
  )
  .execute()

Kotlin

val results = db.pipeline()
    .collection("cities")
    .findNearest(
        "embedding",
        FieldValue.vector(doubleArrayOf(1.5, 2.345)),
        FindNearestStage.DistanceMeasure.EUCLIDEAN
    )
    .execute()

Java

Task<Pipeline.Snapshot> results = db.pipeline()
        .collection("cities")
        .findNearest(
            "embedding",
            new double[] {1.5, 2.345},
            FindNearestStage.DistanceMeasure.EUCLIDEAN
        )
        .execute();
Python
from google.cloud.firestore_v1.vector import Vector
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure

results = (
    client.pipeline()
    .collection("cities")
    .find_nearest(
        field="embedding",
        vector_value=Vector([1.5, 2.345]),
        distance_measure=DistanceMeasure.EUCLIDEAN,
    )
    .execute()
)
Java
Pipeline.Snapshot results =
    firestore
        .pipeline()
        .collection("cities")
        .findNearest(
            "embedding",
            new double[] {1.5, 2.345},
            FindNearest.DistanceMeasure.EUCLIDEAN,
            new FindNearestOptions())
        .execute()
        .get();

Comportamento

Medida de distância

A etapa find_nearest é compatível com as seguintes opções de distância vetorial:

  • euclidean: mede a distância euclidean entre os vetores. Para saber mais, consulte Euclidiano.
  • cosine: compara vetores com base no ângulo entre eles, o que permite medir a similaridade que não se baseia na magnitude dos vetores. Recomendamos usar dot_product com vetores normalizados unitários em vez da distância COSSENO, que é matematicamente equivalente a um melhor desempenho. Para saber mais, consulte Semelhança de cossenos.
  • dot_product: semelhante a cosine, mas é afetado pela magnitude de vetores. Para saber mais, consulte Produto escalar.

Escolha a medida de distância

Dependendo se todos os embeddings de vetor estiverem normalizadas ou não, você pode determinar qual medida de distância usar para encontrar a medida de distância. Um embedding de vetor normalizado tem uma magnitude (comprimento) de exatamente 1,0.

Além disso, se você souber com qual medida de distância o modelo foi treinado, use essa medida para calcular a distância entre os embeddings de vetor.

Dados normalizados

Se você tiver um conjunto de dados em que todos os embeddings de vetor estiverem normalizadas, as três medidas de distância vão fornecer os mesmos resultados de pesquisa semântica. Resumindo, embora cada medida de distância retorne um valor diferente, esses valores são classificados da mesma maneira. Quando os embeddings estão normalizados, o dot_product geralmente é o mais eficiente em termos computacionais, mas a diferença é insignificante na maioria dos casos. No entanto, se o aplicativo for altamente sensível ao desempenho, dot_product poderá ajudar no ajuste de desempenho.

Dados não normalizados

Se você tiver um conjunto de dados em que os embeddings de vetor não estiverem normalizados, não será matematicamente correto usar dot_product como uma medida de distância, porque o produto escalar não mede distância. Dependendo de como os embeddings foram gerados e de qual tipo de pesquisa é a preferida, a medida de distância cosine ou euclidean produzirá resultados de pesquisa subjetivamente melhores do que as outras medidas de distância. A experimentação com cosine ou euclidean pode ser necessária para determinar qual é a melhor para seu caso de uso.

Não tem certeza se os dados estão normalizados ou não

Se você não tiver certeza se os dados estão normalizados e quiser usar dot_product, recomendamos usar cosine. cosine é como dot_product com a normalização integrada. A distância medida usando cosine varia de 0 a 2. Um resultado próximo a 0 indica que os vetores são muito semelhantes.

Limitar os resultados

É possível limitar o número de documentos retornados pela consulta definindo o campo limit.

Node.js

const results = await db.pipeline()
  .collection("cities")
  .findNearest({
      field: 'embedding',
      vectorValue: vector([1.5, 2.345]),
      distanceMeasure: 'euclidean',
      limit: 10,
  })
  .execute();

Extrair a distância vetorial calculada

É possível extrair a distância vetorial calculada atribuindo um nome de propriedade de saída distance_field no cenário find_nearest, conforme mostrado no exemplo a seguir:

Por exemplo, para a seguinte coleção:

Node.js

await db.collection('cities').doc('SF').set({name: 'San Francisco', embedding: vector([1.0, -1.0])});
await db.collection('cities').doc('TO').set({name: 'Toronto', embedding: vector([5.0, -10.0])});
await db.collection('cities').doc('AT').set({name: 'Atlantis', embedding: vector([2.0, -4.0])});

Fazer uma pesquisa vetorial com uma saída solicitada distance_field:

Node.js

const results = await db.pipeline()
  .collection("cities")
  .findNearest({
      field: 'embedding',
      vectorValue: vector([1.3, 2.345]),
      distanceMeasure: 'euclidean',
      distanceField: 'computedDistance',
  })
  .execute();

O que produz os seguintes documentos:

{name: 'San Francisco', embedding: vector([1.0, -1.0]), computedDistance: 3.3584259705999178},
{name: 'Atlantis', embedding: vector([2.0, -4.0]), computedDistance: 6.383496299051172},
{name: 'Toronto', embedding: vector([5.0, -10.0]), computedDistance: 12.887553103673328}

Limitações

Ao trabalhar com embeddings de vetor, observe a seguinte limitação: