AppSearch

AppSearch یک راه‌حل جستجوی درون‌دستگاهی با عملکرد بالا برای مدیریت داده‌های ساختاریافته ذخیره‌شده به‌صورت محلی است. این بایگانی حاوی میاناهای برنامه‌سازی کاربردی برای نمایه‌سازی داده‌ها و بازیابی داده‌ها بااستفاده از جستجوی کل نوشتار است. برنامه‌ها می‌توانند از AppSearch برای ارائه قابلیت‌های جستجوی درون‌برنامه سفارشی استفاده کنند، که به کاربران امکان می‌دهد حتی در حالت آفلاین نیز محتوا را جستجو کنند.

نموداری که نمایه‌سازی و جستجو را در AppSearch نشان می‌دهد

AppSearch ویژگی‌های زیر را ارائه می‌دهد:

  • پیاده‌سازی سریع و اولویت‌دار فضای ذخیره‌سازی تلفن همراه با مصرف کم ورودی/خروجی
  • نمایه‌سازی و پُرسمان بسیار کارآمد در مجموعه‌های بزرگ داده
  • پشتیبانی چندزبانه، مثل انگلیسی و اسپانیایی
  • رتبه‌بندی مربوط بودن و امتیازدهی استفاده

به‌دلیل استفاده کمتر از ورودی/خروجی، AppSearch درمقایسه با SQLite، تأخیر کمتری برای نمایه‌سازی و جستجو در مجموعه‌های داده بزرگ ارائه می‌دهد. AppSearch پُرسمان‌های بین‌نوعی را با پشتیبانی از پُرسمان‌های تکی ساده می‌کند، درحالی‌که SQLite نتایج را از چندین جدول ادغام می‌کند.

برای نشان دادن ویژگی‌های AppSearch، بیایید مثال یک برنامه موسیقی را درنظر بگیریم که آهنگ‌های موردعلاقه کاربران را مدیریت می‌کند و به کاربران اجازه می‌دهد به‌راحتی آن‌ها را جستجو کنند. کاربران از موسیقی‌های سراسر جهان با عنوان‌های آهنگ به زبان‌های مختلف لذت می‌برند، که AppSearch به‌طور بومی از نمایه‌سازی و پُرسمان برای آن‌ها پشتیبانی می‌کند. وقتی کاربر آهنگی را براساس عنوان یا نام هنرمند جستجو می‌کند، برنامه به‌سادگی درخواست را به AppSearch ارسال می‌کند تا آهنگ‌های منطبق را به‌سرعت و به‌طور کارآمد بازیابی کند. برنامه نتایج را نشان می‌دهد و به کاربرانش امکان می‌دهد به‌سرعت پخش آهنگ‌های دلخواهشان را شروع کنند.

راه‌اندازی

برای استفاده از AppSearch در برنامه‌تان، وابستگی‌های زیر را به فایل build.gradle برنامه‌تان اضافه کنید:

شیک

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

کاتلین

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، طرح‌واره، انواع طرح‌واره، اسناد،
جلسه، و جستجو. شکل ۱. نمودار مفاهیم AppSearch: پایگاه داده AppSearch، طرح‌واره، انواع طرح‌واره، اسناد، جلسه، و جستجو.

پایگاه داده و جلسه

پایگاه داده AppSearch مجموعه‌ای از اسناد است که با طرح‌واره پایگاه داده مطابقت دارد. برنامه‌های کارخواه با ارائه بافت برنامه و نام پایگاه داده، پایگاه داده ایجاد می‌کنند. پایگاه‌های داده فقط توسط برنامه‌ای که آن‌ها را ایجاد کرده است می‌توانند باز شوند. وقتی پایگاه داده‌ای باز می‌شود، جلسه‌ای برای تعامل با پایگاه داده برگردانده می‌شود. جلسه نقطه ورودی برای فراخوانی AppSearch API است و تا زمانی که توسط برنامه کارخواه بسته نشود، باز می‌ماند.

طرح و انواع طرح

طرح‌واره نشان‌دهنده ساختار سازمانی داده‌ها در پایگاه داده AppSearch است.

طرحواره از انواع طرحواره تشکیل شده است که انواع یکتای داده‌ها را نشان می‌دهد. انواع طرحواره شامل ویژگی‌هایی است که حاوی نام، نوع داده، و کاردینالیتی است. وقتی نوع طرح‌واره به طرح‌واره پایگاه داده اضافه شد، اسناد آن نوع طرح‌واره را می‌توان ایجاد کرد و به پایگاه داده اضافه کرد.

اسناد

در AppSearch، واحد داده به‌صورت سند نشان داده می‌شود. هر سند در پایگاه داده AppSearch به‌طور منحصربه‌فرد با فضای نام و شناسه آن شناسایی می‌شود. از فضاهای نام برای جدا کردن داده‌ها از منابع مختلف استفاده می‌شود، زمانی که فقط یک منبع نیاز به پرس‌وجو دارد، مانند حساب‌های کاربری.

اسناد حاوی مُهر زمان ایجاد، زمان زندگی (TTL)، و امتیازی هستند که می‌تواند برای رتبه‌بندی درطول بازیابی استفاده شود. همچنین نوع طرح‌واره‌ای به سند اختصاص داده می‌شود که ویژگی‌های داده‌های اضافی را که سند باید داشته باشد توصیف می‌کند.

کلاس سند انتزاعی از سند است. این سند حاوی فیلدهای حاشیه‌نویسی‌شده‌ای است که محتوای سند را نشان می‌دهد. به‌طور پیش‌فرض، نام کلاس سند نام نوع طرح‌واره را تنظیم می‌کند.

اسناد نمایه می‌شوند و با ارائه پُرسمان می‌توان آن‌ها را جستجو کرد. اگر سندی حاوی عبارت‌های موجود در پُرسمان باشد یا با مشخصات جستجوی دیگری مطابقت داشته باشد، مطابقت داده می‌شود و در نتایج جستجو گنجانده می‌شود. نتایج براساس امتیاز و راهبرد رتبه‌بندی‌شان مرتب می‌شوند. نتایج جستجو با صفحه‌هایی نشان داده می‌شود که می‌توانید به‌صورت متوالی بازیابی کنید.

AppSearch سفارشی‌سازی‌هایی برای جستجو ارائه می‌دهد، ازجمله فیلترها، پیکربندی اندازه صفحه، و قطعه‌سازی.

فضای ذخیره‌سازی پلاتفرم، فضای ذخیره‌سازی محلی، یا فضای ذخیره‌سازی خدمات Play

‫AppSearch سه راهکار ذخیره‌سازی ارائه می‌دهد: LocalStorage،‏ PlatformStorage، و PlayServicesStorage. با LocalStorage، برنامه شما نمایه‌ای مختص برنامه را مدیریت می‌کند که در فهرست راهنمای داده‌های برنامه شما قرار دارد. با هر دو PlatformStorage و PlayServicesStorage، برنامه شما به نمایه مرکزی سراسر سیستم کمک می‌کند. نمایه PlatformStorage در سرور سیستم میزبانی می‌شود و نمایه PlayServicesStorage در فضای ذخیره‌سازی «خدمات Google Play» میزبانی می‌شود. دسترسی به داده‌ها در این نمایه‌های مرکزی به داده‌هایی محدود می‌شود که برنامه شما ارائه کرده است و داده‌هایی که صریحاً توسط برنامه دیگری با شما هم‌رسانی شده است. همه این گزینه‌های فضای ذخیره‌سازی از میانای برنامه‌سازی کاربردی یکسانی استفاده می‌کنند و می‌توانند براساس نسخه دستگاه با یکدیگر جابه‌جا شوند.

به‌خاطر داشته باشید که پشتیبانی از ویژگی‌ها براساس گزینه فضای ذخیره‌سازی و دستگاه متفاوت است. برای اطلاعات بیشتر، بررسی دردسترس بودن ویژگی را ببینید.

کد زیر یک جلسه PlatformStorage در Android 12 (سطح میانای برنامه‌سازی کاربردی ۳۱) و بالاتر، و یک جلسه PlayServicesStorage یا LocalStorage در نسخه‌های قدیمی‌تر ایجاد می‌کند:

کاتلین

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

جاوا

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 (سازگار با Android نسخه ۵.۰ و بالاتر) PlatformStorage (سازگار با Android نسخه ۱۲ و بالاتر) PlayServicesStorage (سازگار با Android نسخه ۵.۰ و بالاتر)
جستجوی کل نوشتار کارآمد
پشتیبانی چندزبانه
اندازه دودویی کاهش‌یافته
هم‌رسانی داده بین برنامه‌ها
قابلیت نمایش داده‌ها در سطوح واسط کاربر سیستم
تعداد و اندازه سند نامحدود می‌تواند نمایه‌سازی شود
عملیات سریع‌تر بدون تأخیر اضافی در اتصال‌دهنده

هنگام انتخاب بین LocalStorage و PlatformStorage، باید به مزایا و معایب دیگری نیز توجه کرد. چون PlatformStorage میاناهای برنامه‌سازی کاربردی Jetpack را روی سرویس سیستم AppSearch می‌پیچد، تأثیر اندازه APK درمقایسه با استفاده از LocalStorage حداقل است. بااین‌حال، این امر همچنین به این معنی است که عملیات AppSearch هنگام فراخوانی سرویس سیستم AppSearch، تأخیر اتصال‌دهنده اضافی ایجاد می‌کند. با PlatformStorage ، AppSearch تعداد اسناد و اندازه اسنادی را که برنامه می‌تواند نمایه کند محدود می‌کند تا از کارآمد بودن نمایه مرکزی اطمینان حاصل شود. PlayServicesStorage نیز همان محدودیت‌های PlatformStorage را دارد و فقط در دستگاه‌های دارای «خدمات Google Play» پشتیبانی می‌شود.

بررسی امکان دسترسی به ویژگی

اگرچه همه گزینه‌های فضای ذخیره‌سازی از API یکسانی استفاده می‌کنند، برخی‌از ویژگی‌ها با همه گزینه‌های فضای ذخیره‌سازی یا در همه دستگاه‌ها دردسترس نیستند. در مرجع میانای برنامه‌سازی کاربردی، حاشیه‌نویسی @RequiresFeature میاناهای برنامه‌سازی کاربردی‌ای را که به یکی از این ویژگی‌ها نیاز دارند شناسایی می‌کند و کلاس Features ثابتی را برای هر ویژگی تعریف می‌کند. برای مثال، INDEXING_TYPE_RANGE به Features.NUMERIC_SEARCH نیاز دارد.

برای PlatformStorage، پشتیبانی از ویژگی به نسخه Android دستگاه بستگی دارد. از Android 13 (سطح میانای برنامه‌سازی کاربردی ۳۳)، پشتیبانی از ویژگی‌ها به به‌روزرسانی‌های سیستم Google Play که دستگاه دریافت کرده است نیز بستگی دارد. برای مثال، PlatformStorage از جستجوی عددی (Features.NUMERIC_SEARCH)، جستجوی عینی (Features.VERBATIM_SEARCH)، و پیوستن (Features.JOIN_SPEC_AND_QUALIFIED_ID) فقط در دستگاه‌های زیر پشتیبانی می‌کند:

  • دستگاه‌هایی که Android 14 (سطح API‏ ۳۴) یا بالاتر دارند.
  • دستگاه‌هایی که Android نسخه ۱۳ (میانای برنامه‌سازی کاربردی سطح ۳۳) را اجرا می‌کنند و به‌روزرسانی سیستم Google Play لازم را دریافت کرده‌اند.

این ویژگی‌ها در دستگاه‌هایی که Android 12 یا Android 12L (سطح میانای برنامه‌سازی کاربردی ۳۱ و ۳۲) را اجرا می‌کنند پشتیبانی نمی‌شود.

حداکثر تعداد ویژگی‌های نمایه‌شده در سند نیز براساس دستگاه و گزینه فضای ذخیره‌سازی متفاوت است. برای دریافت حد در زمان اجرا، getMaxIndexedProperties() را فراخوانی کنید.

برای تعیین پشتیبانی از ویژگی، فقط به نسخه Android تکیه نکنید. قبل‌از فراخوانی میانای برنامه‌سازی کاربردی که به ویژگی نیاز دارد، با فراخوانی isFeatureSupported() در شیء Features که AppSearchSession.getFeatures() برمی‌گرداند، بررسی کنید که ویژگی پشتیبانی می‌شود. اگر ویژگی موردنیاز پشتیبانی نشود، عملیات با استثنایی ناموفق می‌شود. یک نمونه از موارد ناموفق، تنظیم طرح‌واره‌ای است که شامل ویژگی INDEXING_TYPE_RANGE است و در دستگاه‌هایی که از Features.NUMERIC_SEARCH پشتیبانی نمی‌کنند ناموفق می‌شود.

کد زیر بررسی می‌کند که آیا AppSearchSession باز از جستجوی عددی پشتیبانی می‌کند یا نه:

کاتلین

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.
}

جاوا

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 تعریف می‌کند.

کاتلین

@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
)

جاوا

@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 دریافت می‌کند، که نشان‌دهنده اتصال به پایگاه داده است و میاناهای برنامه‌سازی کاربردی را برای عملیات پایگاه داده ارائه می‌دهد.

کاتلین

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

جاوا

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

تنظیم طرح‌واره

قبل‌از اینکه بتوانید اسناد را در پایگاه داده قرار دهید و از آن بازیابی کنید، باید طرح‌واره‌ای تنظیم کنید. طرحواره پایگاه داده از انواع مختلفی از داده‌های ساختاریافته تشکیل شده است که به آن‌ها «انواع طرحواره» می‌گویند. کد زیر با ارائه کلاس سند به‌عنوان نوع طرح‌واره، طرح‌واره را تنظیم می‌کند.

کاتلین

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

جاوا

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

سندی را در پایگاه داده قرار دهید

وقتی نوع طرح‌واره اضافه شد، می‌توانید اسناد آن نوع را به پایگاه داده اضافه کنید. کد زیر سندی از نوع طرح‌واره Note بااستفاده از سازنده کلاس سند Note می‌سازد. این کد جای‌نام سند user1 را برای نشان دادن یک کاربر دلخواه از این نمونه تنظیم می‌کند. سپس سند در پایگاه داده درج می‌شود و شنونده‌ای برای پردازش نتیجه عملیات قرار دادن پیوست می‌شود.

کاتلین

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
)

جاوا

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

می‌توانید اسناد نمایه‌شده را بااستفاده از عملیات جستجوی پوشش‌داده‌شده در این بخش جستجو کنید. کد زیر پُرسمان‌هایی را برای عبارت «fruit» در پایگاه داده برای اسنادی که به فضای نام user1 تعلق دارند انجام می‌دهد.

کاتلین

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
)

جاوا

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

Iterate through SearchResults

جستجوها یک نمونه SearchResults را برمی‌گردانند که دسترسی به صفحه‌های اشیاء SearchResult را فراهم می‌کند. هر SearchResult GenericDocument منطبق خود را نگه می‌دارد، شکل کلی سندی که همه سندها به آن تبدیل می‌شوند. کد زیر اولین صفحه نتایج جستجو را دریافت می‌کند و نتیجه را دوباره به سند Note تبدیل می‌کند.

کاتلین

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
)

جاوا

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 از پایگاه داده براساس شناسه ایجاد می‌کند.

کاتلین

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

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

جاوا

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

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

پایداری در دیسک

به‌روزرسانی‌های پایگاه داده باید به‌طور دوره‌ای با فراخوانی requestFlush() در دیسک ذخیره شود. کد زیر requestFlush() را با شنونده‌ای فراخوانی می‌کند تا مشخص شود آیا فراخوانی موفقیت‌آمیز بوده است یا نه.

کاتلین

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)

جاوا

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 را که قبلاً باز شده بود می‌بندد و همه به‌روزرسانی‌ها را در دیسک حفظ می‌کند.

کاتلین

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

جاوا

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

منابع بیشتر

برای کسب اطلاعات بیشتر درباره AppSearch، منابع اضافی زیر را ببینید:

نمونه‌ها

  • نمونه AppSearch ویژه Android‏ (Kotlin)، برنامه یادداشت‌برداری که از AppSearch برای نمایه‌سازی یادداشت‌های کاربر استفاده می‌کند و به کاربران اجازه می‌دهد در یادداشت‌هایشان جستجو کنند.

ارائه کردن بازخورد

بازخورد و ایده‌هایتان را ازطریق این منابع با ما هم‌رسانی کنید:

ردیاب مشکل

اشکالات را گزارش کنید تا بتوانیم آن‌ها را برطرف کنیم.