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

توضّح لك الصفحة كيفية استخدام Cloud Firestore لإجراء عمليات بحث متّجهة باستخدام تقنية "أقرب جيران" (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])
});
انتقال
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
}
جافا
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

لاحتساب عمليات تضمين المتجهات وتخزينها عند تعديل مستند أو إنشائه، يمكنك إعداد وظيفة 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,
  });
}
انتقال
  // Not yet supported in the Go client library
جافا
  // Not yet supported in the Java client library

إنشاء وإدارة مؤشرات المتجهات

قبل أن تتمكّن من إجراء بحث عن أقرب العناصر باستخدام عمليات إدراج المتجهات، يجب إنشاء فهرس ملائم. توضِّح الأمثلة التالية كيفية إنشاء وإدارة الفهارس المتّجهة باستخدام Google Cloud CLI. يمكن أيضًا إدارة فهارس Vector باستخدام واجهة 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

حيث:

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

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

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

حيث:

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

وصف فهرس متجه

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

حيث:

  • 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();
انتقال
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
}
جافا
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: لقياس المسافة الإقليدية بين المتّجهات لمزيد من المعلومات، يُرجى الاطّلاع على مقالة Euclidean.
  • COSINE: تقارن المتجهات استنادًا إلى الزاوية بينها، ما يتيح لكقياس التشابه الذي لا يستند إلى شدة المتجهات. ننصحك باستخدام DOT_PRODUCT مع خطوط متجهة معدَّلة على أساس الوحدة بدلاً من مسافة COSINE، وهي معادلة رياضيًا مع أداء أفضل. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة التشابه القائم على دالة الجيب الزائدي.
  • DOT_PRODUCT: يشبه COSINE، ولكنه يتأثر بحجم المتجهات. لمزيد من المعلومات، اطّلِع على حاصل ضرب نقطي.

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

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

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

البيانات المنسَّقة

إذا كانت لديك مجموعة بيانات تم فيها تطبيع جميع عمليات إدراج المتجهات، تقدّم جميع مقاييس البعد الثلاثة نتائج البحث الدلالية نفسها. في الأساس، على الرغم من أنّ كل قياس مسافة يعرِض قيمة مختلفة، يتم ترتيب هذه القيم بالطريقة نفسها. عند توحيد المستودعات، يكون 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();
انتقال
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
}
جافا
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'));
});
انتقال
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
}
جافا
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'
    });
انتقال
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
}
جافا
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);
});
انتقال
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
}
جافا
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 استخدام ميزة البحث بالاستناد إلى المتجهات.

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