AppSearch

‫AppSearch هو حلّ بحث عالي الأداء على الجهاز فقط لإدارة البيانات المنظَّمة المخزَّنة محليًا. وتحتوي على واجهات برمجة تطبيقات لفهرسة البيانات واستردادها باستخدام البحث في النص الكامل. يمكن للتطبيقات استخدام AppSearch لتوفير إمكانات بحث مخصّصة داخل التطبيق، ما يتيح للمستخدمين البحث عن المحتوى حتى في حال عدم الاتصال بالإنترنت.

مخطّط بياني يوضّح الفهرسة والبحث داخل AppSearch

توفّر AppSearch الميزات التالية:

  • تخزين سريع ومخصّص للأجهزة الجوّالة مع استخدام منخفض لعمليات الإدخال والإخراج
  • فهرسة وطلبات بحث عالية الكفاءة على مجموعات البيانات الكبيرة
  • دعم لغات متعددة، مثل الإنجليزية والإسبانية
  • ترتيب مدى الصلة بالموضوع وتسجيل الاستخدام

بسبب انخفاض استخدام الإدخال/الإخراج، يوفّر AppSearch وقت استجابة أقل للفهرسة والبحث في مجموعات البيانات الكبيرة مقارنةً بـ SQLite. تسهّل AppSearch طلبات البحث من أنواع مختلفة من خلال إتاحة طلبات البحث الفردية، بينما تدمج SQLite النتائج من جداول متعددة.

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

الإعداد

لاستخدام AppSearch في تطبيقك، أضِف التبعيات التالية إلى ملف build.gradle في تطبيقك:

Groovy

dependencies {
    def appsearch_version = "1.2.0-alpha02"

    implementation "androidx.appsearch:appsearch:$appsearch_version"
    // Use kapt instead of annotationProcessor if writing Kotlin classes
    annotationProcessor "androidx.appsearch:appsearch-compiler:$appsearch_version"

    implementation "androidx.appsearch:appsearch-local-storage:$appsearch_version"
    // PlatformStorage is compatible with Android 12+ devices and supports sharing data
    // with other apps. Feature support varies by device. Before calling an API that
    // requires a feature, check Features.isFeatureSupported().
    implementation "androidx.appsearch:appsearch-platform-storage:$appsearch_version"

    // PlayServicesStorage is compatible with all devices that support Google Play Services on
    // all API levels. It offers similar capabilities to PlatformStorage and is the
    // recommended solution for lower API levels on which PlatformStorage is not supported.
    implementation "androidx.appsearch:appsearch-play-services-storage:$appsearch_version"
}

Kotlin

dependencies {
    val appsearch_version = "1.2.0-alpha02"

    implementation("androidx.appsearch:appsearch:$appsearch_version")
    // Use annotationProcessor instead of kapt if writing Java classes
    kapt("androidx.appsearch:appsearch-compiler:$appsearch_version")

    implementation("androidx.appsearch:appsearch-local-storage:$appsearch_version")
    // PlatformStorage is compatible with Android 12+ devices and supports sharing data
    // with other apps. Feature support varies by device. Before calling an API that
    // requires a feature, check Features.isFeatureSupported().
    implementation("androidx.appsearch:appsearch-platform-storage:$appsearch_version")

    // PlayServicesStorage is compatible with all devices that support Google Play Services on
    // all API levels. It offers similar capabilities to PlatformStorage and is the
    // recommended solution for lower API levels on which PlatformStorage is not supported.
    implementation("androidx.appsearch:appsearch-play-services-storage:$appsearch_version")

}

مفاهيم AppSearch

يوضّح المخطّط البياني التالي مفاهيم AppSearch وتفاعلاتها.

مخطّط بياني
يوضّح تطبيق عميل وتفاعلاته مع مفاهيم AppSearch التالية: قاعدة بيانات AppSearch والمخطط وأنواع المخططات والمستندات والجلسة والبحث. الشكل 1: مخطّط بياني لمفاهيم AppSearch: قاعدة بيانات AppSearch والمخطط وأنواع المخططات والمستندات والجلسة والبحث

قاعدة البيانات والجلسة

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

المخطّطات وأنواعها

يمثّل المخطّط البنية التنظيمية للبيانات ضمن قاعدة بيانات AppSearch.

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

المستندات

في AppSearch، يتم تمثيل وحدة البيانات كمستند. يتم تحديد كل مستند في قاعدة بيانات AppSearch بشكل فريد من خلال مساحة الاسم والمعرّف الخاصين به. تُستخدم مساحات الأسماء لفصل البيانات من مصادر مختلفة عندما يحتاج مصدر واحد فقط إلى الاستعلام، مثل حسابات المستخدمين.

تحتوي المستندات على طابع زمني للإنشاء ومدة صلاحية (TTL) ونتيجة يمكن استخدامها للترتيب أثناء الاسترداد. يتم أيضًا تعيين نوع مخطط للمستند يصف خصائص البيانات الإضافية التي يجب أن يحتوي عليها المستند.

فئة المستند هي تجريد للمستند. ويحتوي على حقول مشروحة تمثّل محتوى المستند. يحدّد اسم فئة المستند تلقائيًا اسم نوع المخطط.

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

توفّر AppSearch تخصيصات للبحث، مثل الفلاتر وضبط حجم الصفحة والمقتطفات.

مساحة تخزين المنصة أو مساحة التخزين المحلية أو مساحة تخزين خدمات Play

توفّر AppSearch ثلاثة حلول للتخزين: LocalStorage وPlatformStorage وPlayServicesStorage. باستخدام LocalStorage، يدير تطبيقك فهرسًا خاصًا بالتطبيق يتوفّر في دليل بيانات التطبيق. باستخدام كل من PlatformStorage وPlayServicesStorage، يساهم تطبيقك في فهرس مركزي على مستوى النظام. تتم استضافة فهرس "PlatformStorage" في خادم النظام، بينما تتم استضافة فهرس "PlayServicesStorage" في مساحة التخزين الخاصة بـ "خدمات Google Play". يقتصر الوصول إلى البيانات ضمن هذه الفهارس المركزية على البيانات التي ساهم بها تطبيقك والبيانات التي تمت مشاركتها معك صراحةً من خلال تطبيق آخر. تتشارك جميع خيارات التخزين هذه واجهة برمجة التطبيقات نفسها ويمكن تبادلها بناءً على إصدار الجهاز.

يُرجى العِلم أنّ توفّر الميزات يختلف حسب خيار مساحة التخزين والجهاز. لمزيد من المعلومات، يُرجى الاطّلاع على التحقّق من توفّر الميزة.

تنشئ التعليمة البرمجية التالية جلسة PlatformStorage على نظام التشغيل Android 12 (مستوى واجهة برمجة التطبيقات 31) والإصدارات الأحدث، وجلسة PlayServicesStorage أو LocalStorage على الإصدارات الأقدم:

Kotlin

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    appSearchSessionFuture.setFuture(
        PlatformStorage.createSearchSession(
            PlatformStorage.SearchContext.Builder(mContext, DATABASE_NAME)
               .build()
        )
    )
} else {
    if (usePlayServicesStorageBelowS) {
        appSearchSessionFuture.setFuture(
            PlayServicesStorage.createSearchSession(
                PlayServicesStorage.SearchContext.Builder(mContext, DATABASE_NAME)
                    .build()
            )
        )
    } else {
        appSearchSessionFuture.setFuture(
            LocalStorage.createSearchSession(
                LocalStorage.SearchContext.Builder(mContext, DATABASE_NAME)
                    .build()
            )
        )
    }
}

Java

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    mAppSearchSessionFuture.setFuture(PlatformStorage.createSearchSession(
            new PlatformStorage.SearchContext.Builder(mContext, DATABASE_NAME)
                    .build()));
} else {
    if (usePlayServicesStorageBelowS) {
        mAppSearchSessionFuture.setFuture(PlayServicesStorage.createSearchSession(
                new PlayServicesStorage.SearchContext.Builder(mContext, DATABASE_NAME)
                        .build()));
    } else {
        mAppSearchSessionFuture.setFuture(LocalStorage.createSearchSession(
                new LocalStorage.SearchContext.Builder(mContext, DATABASE_NAME)
                        .build()));
    }
}

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

بالإضافة إلى ذلك، يمكن عرض البيانات التي تتم فهرستها باستخدام PlatformStorage على مساحات واجهة مستخدم النظام. يمكن للتطبيقات إيقاف عرض بعض بياناتها أو كلّها على مساحات واجهة مستخدم النظام. يمكنك الاطّلاع على مزيد من المعلومات حول واجهة برمجة التطبيقات هذه في مستندات setSchemaTypeDisplayedBySystem().

الميزات LocalStorage (متوافق مع الإصدار 5.0 من Android والإصدارات الأحدث) PlatformStorage (متوافق مع الإصدار 12 من Android والإصدارات الأحدث) PlayServicesStorage (متوافق مع الإصدار 5.0 من Android والإصدارات الأحدث)
البحث الفعّال في النص الكامل
إتاحة لغات متعددة
حجم ثنائي مخفَّض
مشاركة البيانات بين التطبيقات
إمكانية عرض البيانات على مساحات عرض واجهة مستخدم النظام
يمكن فهرسة عدد غير محدود من المستندات وبأحجام غير محدودة
عمليات أسرع بدون وقت استجابة إضافي لـ Binder

هناك حلول وسط إضافية يجب مراعاتها عند الاختيار بين LocalStorage وPlatformStorage. بما أنّ PlatformStorage يدمج واجهات برمجة تطبيقات Jetpack في خدمة نظام AppSearch، فإنّ تأثير حجم حزمة APK يكون ضئيلاً مقارنةً باستخدام LocalStorage. ومع ذلك، يعني هذا أيضًا أنّ عمليات AppSearch تتكبّد وقت استجابة إضافيًا عند طلب خدمة نظام AppSearch. باستخدام PlatformStorage، يحدّ AppSearch من عدد المستندات وحجمها التي يمكن للتطبيق فهرستها لضمان فهرسة مركزية فعّالة. يحتوي PlayServicesStorage أيضًا على نفس القيود مثل PlatformStorage وهو مدعوم فقط على الأجهزة التي تحتوي على خدمات Google Play.

التحقّق من توفُّر الميزات

على الرغم من أنّ جميع خيارات التخزين تشترك في واجهة برمجة التطبيقات نفسها، فإنّ بعض الميزات لا تتوفّر مع كل خيار تخزين أو على كل جهاز. في مرجع واجهة برمجة التطبيقات، يحدّد التعليق التوضيحي @RequiresFeature واجهات برمجة التطبيقات التي تتطلّب إحدى هذه الميزات، وتحدّد الفئة Features قيمة ثابتة لكل ميزة. على سبيل المثال، INDEXING_TYPE_RANGE يتطلّب Features.NUMERIC_SEARCH.

بالنسبة إلى PlatformStorage، يعتمد توفّر الميزات على إصدار Android على الجهاز. بدءًا من الإصدار 13 من نظام التشغيل Android (المستوى 33 لواجهة برمجة التطبيقات)، يعتمد توفّر الميزات أيضًا على تحديثات نظام Google Play التي تلقّاها الجهاز. على سبيل المثال، يتيح PlatformStorage البحث الرقمي (Features.NUMERIC_SEARCH) والبحث الحرفي (Features.VERBATIM_SEARCH) وعمليات الربط (Features.JOIN_SPEC_AND_QUALIFIED_ID) على الأجهزة التالية فقط:

  • الأجهزة التي تعمل بالإصدار 14 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 34) أو الإصدارات الأحدث
  • الأجهزة التي تعمل بالإصدار 13 من نظام التشغيل Android (المستوى 33 لواجهة برمجة التطبيقات) والتي تم تثبيت تحديث نظام Google Play المطلوب عليها

لا تتوفّر هذه الميزات على الأجهزة التي تعمل بالإصدار Android 12 أو Android 12L (المستويان 31 و32 من واجهة برمجة التطبيقات).

يختلف أيضًا الحد الأقصى لعدد السمات المفهرَسة في المستند حسب الجهاز وخيار التخزين. للحصول على الحدّ الأقصى في وقت التشغيل، يمكنك استدعاء getMaxIndexedProperties().

لا تعتمد على إصدار Android وحده لتحديد مدى توفّر الميزة. قبل طلب بيانات من واجهة برمجة تطبيقات تتطلّب ميزة معيّنة، تأكَّد من أنّ الميزة متاحة من خلال طلب isFeatureSupported() على عنصر Features الذي يتم عرضه من خلال AppSearchSession.getFeatures(). إذا كانت إحدى الميزات المطلوبة غير متاحة، ستتعذّر العملية مع ظهور استثناء. على سبيل المثال، يتعذّر ضبط مخطط يتضمّن سمة INDEXING_TYPE_RANGE على الأجهزة التي لا تتيح استخدام Features.NUMERIC_SEARCH.

يتحقّق الرمز التالي مما إذا كان AppSearchSession المفتوح يتيح البحث الرقمي:

Kotlin

val features = session.features
if (features.isFeatureSupported(Features.NUMERIC_SEARCH)) {
    // Numeric search is supported. You can index properties with
    // LongPropertyConfig.INDEXING_TYPE_RANGE and enable numeric search with
    // SearchSpec.Builder.setNumericSearchEnabled(true).
} else {
    // Numeric search isn't supported. Set a schema without range-indexed
    // properties, or switch to a different storage option.
}

Java

Features features = session.getFeatures();
if (features.isFeatureSupported(Features.NUMERIC_SEARCH)) {
    // Numeric search is supported. You can index properties with
    // LongPropertyConfig.INDEXING_TYPE_RANGE and enable numeric search with
    // SearchSpec.Builder.setNumericSearchEnabled(true).
} else {
    // Numeric search isn't supported. Set a schema without range-indexed
    // properties, or switch to a different storage option.
}

بدء استخدام AppSearch

يوضّح المثال في هذا القسم كيفية استخدام واجهات برمجة تطبيقات AppSearch للدمج مع تطبيق افتراضي لتدوين الملاحظات.

كتابة فئة مستند

الخطوة الأولى للدمج مع AppSearch هي كتابة فئة مستند لوصف البيانات التي سيتم إدراجها في قاعدة البيانات. يمكنك وضع علامة على فئة كفئة مستندات باستخدام التعليق التوضيحي @Document.يمكنك استخدام مثيلات فئة المستندات لوضع المستندات في قاعدة البيانات واسترداد المستندات منها.

يحدّد الرمز التالي فئة مستند Note مع حقل يحمل التعليق التوضيحي @Document.StringProperty لفهرسة نص عنصر Note.

Kotlin

@Document
public data class Note(

    // Required field for a document class. All documents MUST have a namespace.
    @Document.Namespace
    val namespace: String,

    // Required field for a document class. All documents MUST have an Id.
    @Document.Id
    val id: String,

    // Optional field for a document class, used to set the score of the
    // document. If this is not included in a document class, the score is set
    // to a default of 0.
    @Document.Score
    val score: Int,

    // Optional field for a document class, used to index a note's text for this
    // document class.
    @Document.StringProperty(indexingType = AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)
    val text: String
)

Java

@Document
public class Note {

  // Required field for a document class. All documents MUST have a namespace.
  @Document.Namespace
  private final String namespace;

  // Required field for a document class. All documents MUST have an Id.
  @Document.Id
  private final String id;

  // Optional field for a document class, used to set the score of the
  // document. If this is not included in a document class, the score is set
  // to a default of 0.
  @Document.Score
  private final int score;

  // Optional field for a document class, used to index a note's text for this
  // document class.
  @Document.StringProperty(indexingType = StringPropertyConfig.INDEXING_TYPE_PREFIXES)
  private final String text;

  Note(@NonNull String id, @NonNull String namespace, int score, @NonNull String text) {
    this.id = Objects.requireNonNull(id);
    this.namespace = Objects.requireNonNull(namespace);
    this.score = score;
    this.text = Objects.requireNonNull(text);
  }

  @NonNull
  public String getNamespace() {
    return namespace;
  }

  @NonNull
  public String getId() {
    return id;
  }

  public int getScore() {
    return score;
  }

  @NonNull
  public String getText() {
     return text;
  }
}

فتح قاعدة بيانات

يجب إنشاء قاعدة بيانات قبل العمل على المستندات. ينشئ الرمز التالي قاعدة بيانات جديدة باسم notes_app ويحصل على ListenableFuture لـ AppSearchSession، والذي يمثل الاتصال بقاعدة البيانات ويوفر واجهات برمجة التطبيقات لعمليات قاعدة البيانات.

Kotlin

val context: Context = getApplicationContext()
val sessionFuture = LocalStorage.createSearchSession(
    LocalStorage.SearchContext.Builder(context, /*databaseName=*/"notes_app")
    .build()
)

Java

Context context = getApplicationContext();
ListenableFuture<AppSearchSession> sessionFuture = LocalStorage.createSearchSession(
       new LocalStorage.SearchContext.Builder(context, /*databaseName=*/ "notes_app")
               .build()
);

ضبط مخطط

يجب ضبط مخطط قبل أن تتمكّن من وضع المستندات في قاعدة البيانات واستردادها منها. يتكوّن مخطّط قاعدة البيانات من أنواع مختلفة من البيانات المنظَّمة، يُشار إليها باسم "أنواع المخطّطات". يضبط الرمز التالي المخطط من خلال توفير فئة المستند كنوع مخطط.

Kotlin

val setSchemaRequest = SetSchemaRequest.Builder().addDocumentClasses(Note::class.java)
    .build()
val setSchemaFuture = Futures.transformAsync(
    sessionFuture,
    { session ->
        session?.setSchema(setSchemaRequest)
    }, mExecutor
)

Java

SetSchemaRequest setSchemaRequest = new SetSchemaRequest.Builder().addDocumentClasses(Note.class)
       .build();
ListenableFuture<SetSchemaResponse> setSchemaFuture =
       Futures.transformAsync(sessionFuture, session -> session.setSchema(setSchemaRequest), mExecutor);

وضع مستند في قاعدة البيانات

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

Kotlin

val note = Note(
    namespace="user1",
    id="noteId",
    score=10,
    text="Buy fresh fruit"
)

val putRequest = PutDocumentsRequest.Builder().addDocuments(note).build()
val putFuture = Futures.transformAsync(
    sessionFuture,
    { session ->
        session?.put(putRequest)
    }, mExecutor
)

Futures.addCallback(
    putFuture,
    object : FutureCallback<AppSearchBatchResult<String, Void>?> {
        override fun onSuccess(result: AppSearchBatchResult<String, Void>?) {

            // Gets map of successful results from Id to Void
            val successfulResults = result?.successes

            // Gets map of failed results from Id to AppSearchResult
            val failedResults = result?.failures
        }

        override fun onFailure(t: Throwable) {
            Log.e(TAG, "Failed to put documents.", t)
        }
    },
    mExecutor
)

Java

Note note = new Note(/*namespace=*/"user1", /*id=*/
                "noteId", /*score=*/ 10, /*text=*/ "Buy fresh fruit!");

PutDocumentsRequest putRequest = new PutDocumentsRequest.Builder().addDocuments(note)
       .build();
ListenableFuture<AppSearchBatchResult<String, Void>> putFuture =
       Futures.transformAsync(sessionFuture, session -> session.put(putRequest), mExecutor);

Futures.addCallback(putFuture, new FutureCallback<AppSearchBatchResult<String, Void>>() {
   @Override
   public void onSuccess(@Nullable AppSearchBatchResult<String, Void> result) {

     // Gets map of successful results from Id to Void
     Map<String, Void> successfulResults = result.getSuccesses();

     // Gets map of failed results from Id to AppSearchResult
     Map<String, AppSearchResult<Void>> failedResults = result.getFailures();
   }

   @Override
   public void onFailure(@NonNull Throwable t) {
      Log.e(TAG, "Failed to put documents.", t);
   }
}, mExecutor);

يمكنك البحث في المستندات التي تمت فهرستها باستخدام عوامل تشغيل البحث الموضّحة في هذا القسم. ينفّذ الرمز التالي طلبات بحث عن عبارة "فاكهة" في قاعدة البيانات للمستندات التي تنتمي إلى مساحة الاسم user1.

Kotlin

val searchSpec = SearchSpec.Builder()
    .addFilterNamespaces("user1")
    .build();

val searchFuture = Futures.transform(
    sessionFuture,
    { session ->
        session?.search("fruit", searchSpec)
    },
    mExecutor
)
Futures.addCallback(
    searchFuture,
    object : FutureCallback<SearchResults> {
        override fun onSuccess(searchResults: SearchResults?) {
            iterateSearchResults(searchResults)
        }

        override fun onFailure(t: Throwable?) {
            Log.e("TAG", "Failed to search notes in AppSearch.", t)
        }
    },
    mExecutor
)

Java

SearchSpec searchSpec = new SearchSpec.Builder()
       .addFilterNamespaces("user1")
       .build();

ListenableFuture<SearchResults> searchFuture =
       Futures.transform(sessionFuture, session -> session.search("fruit", searchSpec),
       mExecutor);

Futures.addCallback(searchFuture,
       new FutureCallback<SearchResults>() {
           @Override
           public void onSuccess(@Nullable SearchResults searchResults) {
               iterateSearchResults(searchResults);
           }

           @Override
           public void onFailure(@NonNull Throwable t) {
               Log.e(TAG, "Failed to search notes in AppSearch.", t);
           }
       }, mExecutor);

التكرار من خلال SearchResults

تعرض عمليات البحث مثيل SearchResults، ما يتيح الوصول إلى صفحات عناصر SearchResult. يحتوي كل SearchResult على GenericDocument المطابق له، وهو الشكل العام للمستند الذي يتم تحويل جميع المستندات إليه. يحصل الرمز التالي على الصفحة الأولى من نتائج البحث ويحوّل النتيجة مرة أخرى إلى مستند Note.

Kotlin

Futures.transform(
    searchResults?.nextPage,
    { page: List<SearchResult>? ->
        // Gets GenericDocument from SearchResult.
        val genericDocument: GenericDocument = page!![0].genericDocument
        val schemaType = genericDocument.schemaType
        val note: Note? = try {
            if (schemaType == "Note") {
                // Converts GenericDocument object to Note object.
                genericDocument.toDocumentClass(Note::class.java)
            } else null
        } catch (e: AppSearchException) {
            Log.e(
                TAG,
                "Failed to convert GenericDocument to Note",
                e
            )
            null
        }
        note
    },
    mExecutor
)

Java

Futures.transform(searchResults.getNextPage(), page -> {
  // Gets GenericDocument from SearchResult.
  GenericDocument genericDocument = page.get(0).getGenericDocument();
  String schemaType = genericDocument.getSchemaType();

  Note note = null;

  if (schemaType.equals("Note")) {
    try {
      // Converts GenericDocument object to Note object.
      note = genericDocument.toDocumentClass(Note.class);
    } catch (AppSearchException e) {
      Log.e(TAG, "Failed to convert GenericDocument to Note", e);
    }
  }

  return note;
}, mExecutor);

إزالة مستند

عندما يحذف المستخدم ملاحظة، يحذف التطبيق مستند Note المقابل من قاعدة البيانات. يضمن ذلك عدم ظهور الملاحظة في طلبات البحث. يُرسل الرمز التالي طلبًا صريحًا لإزالة مستند Note من قاعدة البيانات حسب المعرّف.

Kotlin

val removeRequest = RemoveByDocumentIdRequest.Builder("user1")
    .addIds("noteId")
    .build()

val removeFuture = Futures.transformAsync(
    sessionFuture, { session ->
        session?.remove(removeRequest)
    },
    mExecutor
)

Java

RemoveByDocumentIdRequest removeRequest = new RemoveByDocumentIdRequest.Builder("user1")
       .addIds("noteId")
       .build();

ListenableFuture<AppSearchBatchResult<String, Void>> removeFuture =
       Futures.transformAsync(sessionFuture, session -> session.remove(removeRequest), mExecutor);

الاحتفاظ بالبيانات على القرص

يجب حفظ التعديلات على قاعدة البيانات بشكل دوري على القرص من خلال استدعاء requestFlush(). يستدعي الرمز التالي requestFlush() مع مستمع لتحديد ما إذا كان الاستدعاء ناجحًا.

Kotlin

val requestFlushFuture = Futures.transformAsync(
    sessionFuture,
    { session -> session?.requestFlush() }, mExecutor
)

Futures.addCallback(requestFlushFuture, object : FutureCallback<Void?> {
    override fun onSuccess(result: Void?) {
        // Success! Database updates have been persisted to disk.
    }

    override fun onFailure(t: Throwable) {
        Log.e(TAG, "Failed to flush database updates.", t)
    }
}, mExecutor)

Java

ListenableFuture<Void> requestFlushFuture = Futures.transformAsync(sessionFuture,
        session -> session.requestFlush(), mExecutor);

Futures.addCallback(requestFlushFuture, new FutureCallback<Void>() {
    @Override
    public void onSuccess(@Nullable Void result) {
        // Success! Database updates have been persisted to disk.
    }

    @Override
    public void onFailure(@NonNull Throwable t) {
        Log.e(TAG, "Failed to flush database updates.", t);
    }
}, mExecutor);

إغلاق جلسة

يجب إغلاق AppSearchSession عندما لا يستدعي التطبيق أي عمليات في قاعدة البيانات. يؤدي الرمز التالي إلى إغلاق جلسة AppSearch التي تم فتحها سابقًا ويحفظ جميع التعديلات على القرص.

Kotlin

val closeFuture = Futures.transform<AppSearchSession, Unit>(sessionFuture,
    { session ->
        session?.close()
        Unit
    }, mExecutor
)

Java

ListenableFuture<Void> closeFuture = Futures.transform(sessionFuture, session -> {
   session.close();
   return null;
}, mExecutor);

مراجع إضافية

لمزيد من المعلومات حول AppSearch، يمكنك الاطّلاع على المراجع الإضافية التالية:

نماذج

  • نموذج Android AppSearch (لغة Kotlin): هو تطبيق لتدوين الملاحظات يستخدم AppSearch لفهرسة ملاحظات المستخدم والسماح للمستخدمين بالبحث في ملاحظاتهم.

تقديم ملاحظات

يمكنك مشاركة ملاحظاتك وأفكارك معنا من خلال المراجع التالية:

أداة Issue Tracker

أبلِغ عن الأخطاء لنتمكّن من إصلاحها.