البحث باستخدام تضمينات المتّجهات

توضّح لك الصفحة كيفية استخدام Cloud Firestore لإجراء عمليات بحث متجهة عن أقرب K جيران (KNN) باستخدام التقنيات التالية:

  • قيم المتّجه للمتجر
  • إنشاء فهارس متجهات KNN وإدارتها
  • إجراء طلب بحث عن الجار الأقرب (KNN) باستخدام أحد مقاييس مسافة المتجهات المتوافقة

تخزين تضمينات المتجهات

يمكنك إنشاء قيم متّجهة، مثل عمليات تضمين النص، من بيانات Cloud Firestore وتخزينها في مستندات Cloud Firestore.

عملية الكتابة باستخدام تضمين متّجه

يوضّح المثال التالي كيفية تخزين تضمين متّجهي في مستند Cloud 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();

حساب تضمينات المتجهات باستخدام Cloud Function

لحساب وتخزين تضمينات المتجهات كلما تم تعديل مستند أو إنشاؤه، يمكنك إعداد دالة Cloud:

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

إنشاء فهارس المتجهات وإدارتها

قبل أن تتمكّن من إجراء بحث عن أقرب جار باستخدام تضمينات المتجهات، عليك إنشاء فهرس مطابق. توضّح الأمثلة التالية كيفية إنشاء فهارس متّجهة وإدارتها باستخدام Google Cloud CLI. يمكن أيضًا إدارة فهارس المتجهات باستخدام Firebase CLI وTerraform.

إنشاء فهرس متجهات

قبل إنشاء فهرس متّجه، عليك الترقية إلى أحدث إصدار من Google Cloud CLI:

gcloud components update

لإنشاء فهرس متّجه، استخدِم 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

where:

  • collection-group هو رقم تعريف مجموعة المجموعات.
  • vector-field هو اسم الحقل الذي يحتوي على تضمين المتّجه.
  • database-id هو رقم تعريف قاعدة البيانات.
  • يتضمّن vector-configuration المتّجه dimension ونوع الفهرس. dimension هو عدد صحيح يصل إلى 2048. يجب أن يكون نوع الفهرس flat. نسِّق إعدادات الفهرس على النحو التالي: {"dimension":"DIMENSION", "flat": "{}"}.

ينشئ المثال التالي فهرسًا مركّبًا يتضمّن فهرسًا متّجهًا للحقل vector-field وفهرسًا تصاعديًا للحقل color. يمكنك استخدام هذا النوع من الفهرس للفلترة المسبقة للبيانات قبل إجراء عملية بحث عن أقرب جار.

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

عرض جميع فهارس المتجهات

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

استبدِل database-id بمعرّف قاعدة البيانات.

حذف فهرس متّجه

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

where:

  • index-id هو رقم تعريف الفهرس المطلوب حذفه. استخدِم indexes composite list لاسترداد رقم تعريف الفهرس.
  • database-id هو رقم تعريف قاعدة البيانات.

وصف فهرس المتّجهات

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

where:

  • index-id هو معرّف الفهرس المطلوب وصفه. استخدِم indexes composite list لاسترداد رقم تعريف الفهرس.
  • database-id هو رقم تعريف قاعدة البيانات.

إجراء طلب بحث عن أقرب جار

يمكنك إجراء بحث عن التشابه للعثور على أقرب النقاط المجاورة لتضمين متّجه. تتطلّب عمليات البحث المشابهة فهارس متّجهة. إذا لم يكن هناك فهرس، تقترح Cloud Firestore إنشاء فهرس باستخدام gcloud CLI.

يعثر المثال التالي على 10 نقاط مجاورة لأقرب متّجه طلب بحث.

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

مسافات المتجهات

تتيح طلبات البحث عن الجيران الأقرب الخيارات التالية لمسافة المتجهات:

  • EUCLIDEAN: تقيس المسافة الإقليدية بين المتجهات. لمزيد من المعلومات، يُرجى الاطّلاع على المسافة الإقليدية.
  • COSINE: تقارن هذه الطريقة المتّجهات استنادًا إلى الزاوية بينها، ما يتيح لك قياس التشابه الذي لا يستند إلى مقدار المتّجهات. ننصحك باستخدام DOT_PRODUCT مع الخطوط المتجهة الموحّدة بدلاً من مسافة COSINE، لأنّها مكافئة رياضيًا وتوفّر أداءً أفضل. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة تشابه الجيب التمامي.
  • DOT_PRODUCT: مشابهة لـ COSINE ولكنها تتأثر بحجم المتجهات. لمزيد من المعلومات، اطّلِع على مقالة الضرب النقطي.

اختيار مقياس المسافة

استنادًا إلى ما إذا كانت جميع تضمينات المتجهات موحّدة أم لا، يمكنك تحديد مقياس المسافة الذي تريد استخدامه للعثور على مقياس المسافة. يبلغ مقدار (طول) تضمين المتّجه العادي 1.0 بالضبط.

بالإضافة إلى ذلك، إذا كنت تعرف مقياس المسافة الذي تم تدريب النموذج عليه، استخدِم مقياس المسافة هذا لاحتساب المسافة بين تضمينات المتجهات.

البيانات الموحّدة

إذا كانت لديك مجموعة بيانات تم فيها تسوية جميع عمليات تضمين المتجهات، ستوفّر مقاييس المسافة الثلاثة النتائج نفسها للبحث الدلالي. في الأساس، على الرغم من أنّ كل مقياس مسافة يعرض قيمة مختلفة، يتم ترتيب هذه القيم بالطريقة نفسها. عندما يتم تسوية التضمينات، يكون DOT_PRODUCT عادةً الأكثر فعالية من الناحية الحسابية، ولكن يكون الفرق ضئيلاً في معظم الحالات. ومع ذلك، إذا كان تطبيقك يتطلّب أداءً عاليًا، قد تساعدك السمة DOT_PRODUCT في تحسين الأداء.

البيانات غير الموحّدة

إذا كان لديك مجموعة بيانات لم يتم فيها تسوية تضمينات المتجهات، لن يكون من الصحيح رياضيًا استخدام DOT_PRODUCT كمقياس للمسافة لأنّ حاصل الضرب النقطي لا يقيس المسافة. استنادًا إلى طريقة إنشاء التضمينات ونوع البحث المفضّل، يمكن أن يؤدي مقياس المسافة COSINE أو EUCLIDEAN إلى ظهور نتائج بحث أفضل من الناحية الموضوعية مقارنةً بمقاييس المسافة الأخرى. قد يكون من الضروري تجربة COSINE أو EUCLIDEAN لتحديد الخيار الأفضل لحالة الاستخدام.

عدم التأكّد مما إذا كانت البيانات منمّطة أو غير منمّطة

إذا لم تكن متأكدًا مما إذا كانت بياناتك مسوّاة أم لا وكنت تريد استخدام DOT_PRODUCT، ننصحك باستخدام COSINE بدلاً من ذلك. COSINE تشبه DOT_PRODUCT مع تضمين ميزة التسوية. تتراوح المسافة المقاسة باستخدام COSINE من 0 إلى 2. تشير النتيجة القريبة من 0 إلى أنّ الخطوط المتجهة متشابهة جدًا.

فلترة المستندات مسبقًا

لفلترة المستندات مسبقًا قبل العثور على أقرب المستندات المشابهة، يمكنك الجمع بين بحث عن التشابه وعوامل تشغيل طلبات بحث أخرى. تتوفّر الفلاتر المركّبة and وor. لمزيد من المعلومات عن فلاتر الحقول المتوافقة، اطّلِع على عوامل تشغيل طلب البحث.

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

استرداد مسافة المتّجه المحسوبة

يمكنك استرداد مسافة المتّجه المحسوبة من خلال تعيين اسم خاصية إخراج distance_result_field في طلب البحث FindNearest، كما هو موضّح في المثال التالي:

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

إذا كنت تريد استخدام قناع حقل لعرض مجموعة فرعية من حقول المستند مع distanceResultField، عليك أيضًا تضمين قيمة distanceResultField في قناع الحقل، كما هو موضّح في المثال التالي:

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

تحديد حدّ أدنى للمسافة

يمكنك تحديد حدّ تشابه يعرض المستندات التي تقع ضمن هذا الحدّ فقط. يعتمد سلوك حقل الحدّ الأدنى على مقياس المسافة الذي تختاره:

  • تفرض مسافتا EUCLIDEAN وCOSINE حدًا أدنى على الحدّ الأدنى للمسافة، بحيث لا يتم عرض سوى المستندات التي تكون فيها المسافة أقل من الحدّ الأدنى المحدّد أو تساويه. وتنخفض مقاييس المسافة هذه كلما زاد التشابه بين المتجهات.
  • DOT_PRODUCT يقتصر الحد الأدنى للمسافة على المستندات التي تكون فيها المسافة أكبر من أو تساوي الحد الأدنى المحدّد. تزداد مسافات حاصل الضرب النقطي كلما أصبحت المتجهات أكثر تشابهًا.

يوضّح المثال التالي كيفية تحديد حدّ مسافة لعرض ما يصل إلى 10 مستندات الأقرب إلى بعضها البعض، والتي تبعد عن بعضها البعض بمقدار 4.5 وحدة على الأكثر باستخدام مقياس المسافة 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());
}

القيود

أثناء العمل مع تضمينات المتّجهات، يُرجى ملاحظة القيود التالية:

  • الحد الأقصى لأبعاد التضمين المسموح بها هو 2048. لتخزين فهارس أكبر، استخدِم تقنية خفض الأبعاد.
  • الحد الأقصى لعدد المستندات التي يمكن عرضها من طلب بحث عن أقرب تطابق هو 1000 مستند.
  • لا تتيح ميزة "البحث المتّجه" برامج معالجة اللقطات في الوقت الفعلي.
  • تتيح مكتبات برامج Python وNode.js وGo وJava للعملاء البحث المستند إلى المتجهات فقط.

الخطوات التالية