AppSearch

AppSearch হল একটি উচ্চ-পারফরম্যান্স অন-ডিভাইস সার্চ সমাধান যা স্থানীয়ভাবে সংরক্ষিত, স্ট্রাকচার্ড ডেটা ম্যানেজ করার জন্য। এতে ডেটা ইন্ডেক্সিং ও সম্পূর্ণ টেক্সট সার্চ ব্যবহার করে ডেটা ফিরিয়ে আনার জন্য API রয়েছে। অ্যাপ্লিকেশনগুলি কাস্টম ইন-অ্যাপ সার্চের সুবিধা অফার করার জন্য AppSearch ব্যবহার করতে পারে, যা ব্যবহারকারীদের অফলাইনে থাকাকালীনও কন্টেন্ট সার্চ করার অনুমতি দেয়।

AppSearch-এর মধ্যে ইন্ডেক্সিং ও সার্চ করার ডায়াগ্রাম ইলাস্ট্রেশন

AppSearch নিম্নলিখিত ফিচার প্রদান করে:

  • কম I/O ব্যবহার সহ দ্রুত, মোবাইল-ফার্স্ট স্টোরেজ ইমপ্লিমেন্টেশন
  • বড় ডেটা সেটের উপর অত্যন্ত দক্ষ ইন্ডেক্সিং এবং কোয়েরি করা
  • একাধিক ভাষার জন্য সহায়তা, যেমন ইংরেজি এবং স্প্যানিশ
  • প্রাসঙ্গিকতা র‍্যাঙ্কিং ও ব্যবহার স্কোরিং

I/O-এর কম ব্যবহারের কারণে, SQLite-এর তুলনায় বড় ডেটাসেটে ইন্ডেক্সিং ও সার্চ করার জন্য AppSearch কম লেটেন্সি অফার করে। 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"
}

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 ডেটাবেস, স্কিমা, স্কিমার ধরন, ডকুমেন্ট, সেশন ও সার্চ। ছবি ১. AppSearch ধারণার ডায়াগ্রাম: AppSearch ডেটাবেস, স্কিমা, স্কিমার ধরন, ডকুমেন্ট, সেশন ও সার্চ।

ডেটাবেস ও সেশন

AppSearch ডেটাবেস হল ডকুমেন্টের একটি সংগ্রহ যা ডেটাবেস স্কিমার সাথে মানানসই। ক্লায়েন্ট অ্যাপ্লিকেশন, তাদের অ্যাপ্লিকেশনের প্রসঙ্গ ও ডেটাবেসের নাম প্রদান করে ডেটাবেস তৈরি করে। যে অ্যাপ্লিকেশন ডেটাবেস তৈরি করেছে, শুধুমাত্র সেটিই ডেটাবেস খুলতে পারবে। ডেটাবেস খোলা হলে, ডেটাবেসের সাথে ইন্টার‍্যাক্ট করার জন্য একটি সেশন রিটার্ন করা হয়। সেশন হল AppSearch API কল করার এন্ট্রি পয়েন্ট এবং ক্লায়েন্ট অ্যাপ্লিকেশন বন্ধ না করা পর্যন্ত এটি খোলা থাকে।

স্কিমা ও স্কিমার ধরন

স্কিমা AppSearch ডেটাবেসের মধ্যে ডেটার সাংগঠনিক কাঠামোকে উপস্থাপন করে।

স্কিমাটি স্কিমার ধরন দিয়ে তৈরি যা ডেটার অনন্য ধরনকে উপস্থাপন করে। স্কিমার ধরন প্রপার্টি নিয়ে গঠিত হয়, যার মধ্যে নাম, ডেটার ধরন ও কার্ডিনালিটি থাকে। ডেটাবেস স্কিমায় কোনও স্কিমা টাইপ যোগ করা হলে, সেই স্কিমা টাইপের ডকুমেন্ট তৈরি করে ডেটাবেসে যোগ করা যেতে পারে।

ডকুমেন্ট

AppSearch-এ, ডেটার একটি ইউনিটকে ডকুমেন্ট হিসেবে দেখানো হয়। AppSearch ডেটাবেসের প্রতিটি ডকুমেন্ট এর নেমস্পেস এবং আইডি দ্বারা অনন্যভাবে শনাক্ত করা হয়। নেমস্পেস ব্যবহার করা হয় বিভিন্ন সোর্স থেকে ডেটা আলাদা করার জন্য, যখন শুধুমাত্র একটি সোর্স কোয়েরি করতে হয়, যেমন ব্যবহারকারীর অ্যাকাউন্ট।

ডকুমেন্টে একটি ক্রিয়েশন টাইমস্ট্যাম্প, একটি টাইম-টু-লাইভ (TTL) এবং একটি স্কোর থাকে যা পুনরুদ্ধারের সময় র‍্যাঙ্কিংয়ের জন্য ব্যবহার করা যেতে পারে। এছাড়াও, একটি ডকুমেন্টকে একটি স্কিমা টাইপ অ্যাসাইন করা হয় যা ডকুমেন্টের অতিরিক্ত ডেটা প্রপার্টি বর্ণনা করে।

ডকুমেন্ট ক্লাস হল ডকুমেন্টের অ্যাবস্ট্রাকশন। এতে অ্যানোটেট করা ফিল্ড আছে যা কোনও ডকুমেন্টের কন্টেন্টকে তুলে ধরে। ডিফল্ট হিসেবে, ডকুমেন্ট ক্লাসের নাম স্কিমার ধরনের নাম সেট করে।

ডকুমেন্ট ইন্ডেক্স করা হয় এবং কোয়েরি লিখে সার্চ করা যায়। কোনও ডকুমেন্টে কোয়েরির শব্দ থাকলে বা অন্য কোনও সার্চ স্পেসিফিকেশনের সাথে মিলে গেলে, সেটি সার্চ ফলাফলে অন্তর্ভুক্ত করা হয়। ফলাফলগুলি তাদের স্কোর এবং র‌্যাঙ্কিং কৌশলের উপর ভিত্তি করে সাজানো হয়। সার্চ ফলাফল পৃষ্ঠা হিসেবে দেখানো হয় যা আপনি ক্রমিক অনুসারে দেখতে পারেন।

AppSearch সার্চের জন্য কাস্টমাইজেশন অফার করে, যেমন ফিল্টার, পৃষ্ঠা সাইজ কনফিগারেশন এবং স্নিপেটিং।

প্ল্যাটফর্ম স্টোরেজ, লোকাল স্টোরেজ বা Play পরিষেবা স্টোরেজ

AppSearch তিনটি স্টোরেজ সমাধান অফার করে: LocalStorage, PlatformStorage এবং PlayServicesStorage। LocalStorage-এর মাধ্যমে, আপনার অ্যাপ্লিকেশন একটি অ্যাপ-নির্দিষ্ট ইন্ডেক্স ম্যানেজ করে যা আপনার অ্যাপ্লিকেশন ডেটা ডিরেক্টরিতে থাকে। PlatformStorage এবং PlayServicesStorage, দুটির মাধ্যমেই আপনার অ্যাপ্লিকেশন সিস্টেম-ব্যাপী সেন্ট্রাল ইনডেক্সে কন্ট্রিবিউট করে। PlatformStorage-এর ইন্ডেক্স সিস্টেম সার্ভারে হোস্ট করা হয় এবং PlayServicesStorage-এর ইন্ডেক্স Google Play পরিষেবার স্টোরেজে হোস্ট করা হয়। এইসব সেন্ট্রাল ইন্ডেক্সের মধ্যে ডেটা অ্যাক্সেস আপনার অ্যাপ্লিকেশনের কন্ট্রিবিউট করা ডেটা এবং অন্য অ্যাপ্লিকেশনের মাধ্যমে আপনার সাথে স্পষ্টভাবে শেয়ার করা ডেটার মধ্যে সীমাবদ্ধ। এইসব স্টোরেজ বিকল্প একই API শেয়ার করে এবং ডিভাইসের ভার্সনের উপর ভিত্তি করে একে অপরের সাথে পরিবর্তন করা যেতে পারে।

মনে রাখবেন, স্টোরেজ বিকল্প ও ডিভাইস অনুযায়ী ফিচারের সহায়তা আলাদা আলাদা হয়। আরও তথ্যের জন্য, ফিচার উপলভ্য কিনা চেক করে দেখুন।

নিম্নলিখিত কোড Android 12 (API লেভেল 31) এবং তার পরবর্তী যেকোনও ভার্সনে PlatformStorage সেশন এবং আগের যেকোনও ভার্সনে 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()
            )
        )
    }
}

জাভা

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()-এর জন্য ডকুমেন্টেশনে এই API সম্পর্কে আরও পড়ুন।

এছাড়াও, PlatformStorage-এর সাথে, ইন্ডেক্স করা ডেটা সিস্টেম UI সারফেসে দেখানো যেতে পারে। অ্যাপ্লিকেশনগুলি সিস্টেম UI সারফেসে তাদের কিছু বা সমস্ত ডেটা প্রদর্শন করা থেকে অপ্ট-আউট করতে পারে। setSchemaTypeDisplayedBySystem()-এর জন্য ডকুমেন্টেশনে এই API সম্পর্কে আরও পড়ুন।

ফিচার LocalStorage (Android 5.0+ ভার্সনের সাথে মানানসই) PlatformStorage (Android 12+ ভার্সনের সাথে মানানসই) PlayServicesStorage (Android 5.0+ ভার্সনের সাথে মানানসই)
দক্ষ সম্পূর্ণ টেক্সট সার্চ
একাধিক ভাষা ব্যবহার করা যায়
বাইনারি সাইজ কমানো হয়েছে
অ্যাপ্লিকেশন-টু-অ্যাপ্লিকেশন ডেটা শেয়ারিং
সিস্টেম UI সারফেসে ডেটা দেখানোর ক্ষমতা
আনলিমিটেড ডকুমেন্ট সাইজ ও সংখ্যা ইন্ডেক্স করা যাবে
অতিরিক্ত বাইন্ডার লেটেন্সি ছাড়াই দ্রুত অপারেশন

LocalStorage এবং PlatformStorage-এর মধ্যে বেছে নেওয়ার সময় অতিরিক্ত ট্রেড-অফ বিবেচনা করতে হবে। কারণ PlatformStorage, AppSearch সিস্টেম পরিষেবার উপর Jetpack API-কে র‍্যাপ করে, LocalStorage ব্যবহার করার তুলনায় APK সাইজের উপর প্রভাব খুবই কম হয়। তবে, এর অর্থ হল AppSearch সিস্টেম সার্ভিস কল করার সময় AppSearch অপারেশনে অতিরিক্ত বাইন্ডার লেটেন্সি হয়। PlatformStorage -এর মাধ্যমে, AppSearch একটি অ্যাপ্লিকেশনের ডকুমেন্টের সংখ্যা এবং ডকুমেন্টের সাইজ সীমিত করে যাতে একটি দক্ষ সেন্ট্রাল ইন্ডেক্স নিশ্চিত করা যায়। PlayServicesStorage-এর ক্ষেত্রেও PlatformStorage-এর মতো একই সীমাবদ্ধতা রয়েছে এবং এটি শুধুমাত্র Google Play পরিষেবা আছে এমন ডিভাইসেই কাজ করে।

ফিচার উপলভ্য কিনা দেখে নিন

সব স্টোরেজ বিকল্প একই API শেয়ার করলেও, কিছু ফিচার প্রতিটি স্টোরেজ বিকল্পে বা প্রতিটি ডিভাইসে উপলভ্য নয়। API রেফারেন্সে, @RequiresFeature অ্যানোটেশন সেইসব API শনাক্ত করে যেগুলির জন্য এইসব ফিচারের মধ্যে একটি প্রয়োজন হয় এবং Features ক্লাস প্রতিটি ফিচারের জন্য একটি কনস্ট্যান্ট নির্ধারণ করে। যেমন, INDEXING_TYPE_RANGE -এর জন্য Features.NUMERIC_SEARCH প্রয়োজন।

PlatformStorage-এর জন্য, ফিচার কাজ করবে কিনা তা ডিভাইসের Android ভার্সনের উপর নির্ভর করে। Android 13 (API লেভেল 33) থেকে শুরু করে, ফিচার সংক্রান্ত সহায়তাও ডিভাইসে পাওয়া Google Play সিস্টেম আপডেটের উপর নির্ভর করে। যেমন, PlatformStorage শুধুমাত্র নিম্নলিখিত ডিভাইসে সংখ্যাভিত্তিক সার্চ (Features.NUMERIC_SEARCH), ভারবাটিম সার্চ (Features.VERBATIM_SEARCH) এবং জয়েন (Features.JOIN_SPEC_AND_QUALIFIED_ID) করার সুবিধা দেয়:

  • Android 14 (API লেভেল 34) বা তার পরবর্তী যেকোনও ভার্সনে চলে এমন ডিভাইস।
  • যেসব ডিভাইস Android 13 (API লেভেল 33) ভার্সনে চলে এবং প্রয়োজনীয় Google Play সিস্টেম আপডেট পেয়েছে।

Android 12 বা Android 12L (API লেভেল ৩১ ও ৩২) ভার্সনে চলে এমন ডিভাইসে এইসব ফিচার কাজ করে না।

এছাড়াও, কোনও ডকুমেন্টে ইন্ডেক্স করা প্রপার্টির সর্বাধিক সংখ্যা ডিভাইস ও স্টোরেজ বিকল্পের ভিত্তিতে আলাদা হয়। রানটাইমে সীমা পেতে, getMaxIndexedProperties() কল করুন।

ফিচার কাজ করবে কিনা তা নির্ধারণ করতে শুধুমাত্র Android ভার্সনের উপর নির্ভর করবেন না। কোনও ফিচারের প্রয়োজন হয় এমন API কল করার আগে, AppSearchSession.getFeatures() যে Features অবজেক্ট রিটার্ন করে সেটিতে isFeatureSupported() কল করে ফিচারটি কাজ করে কিনা তা যাচাই করুন। প্রয়োজনীয় ফিচার কাজ না করলে, অপারেশনটি ব্যতিক্রম সহ ব্যর্থ হয়। ব্যর্থতার একটি উদাহরণ হল এমন একটি স্কিমা সেট করা যাতে একটি 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.
}

জাভা

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 API ব্যবহার করে একটি কাল্পনিক নোট-কিপিং অ্যাপ্লিকেশনের সাথে ইন্টিগ্রেট করা যায়।

Write a document class

AppSearch-এর সাথে ইন্টিগ্রেট করার প্রথম ধাপ হল ডেটাবেসে যোগ করার জন্য ডেটা বর্ণনা করতে ডকুমেন্ট ক্লাস লেখা। @Document অ্যানোটেশন ব্যবহার করে কোনও ক্লাসকে ডকুমেন্ট ক্লাস হিসেবে চিহ্নিত করুন। আপনি ডেটাবেসে ডকুমেন্ট রাখতে এবং ডেটাবেস থেকে ডকুমেন্ট ফিরিয়ে আনতে ডকুমেন্ট ক্লাসের ইনস্ট্যান্স ব্যবহার করতে পারেন।

নিম্নলিখিত কোডটি একটি নোট অবজেক্টের টেক্সট ইন্ডেক্স করার জন্য @Document.StringProperty অ্যানোটেটেড ফিল্ড সহ একটি নোট ডকুমেন্ট ক্লাস সংজ্ঞায়িত করে।

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
)

জাভা

@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 নামে একটি নতুন ডেটাবেস তৈরি করে এবং AppSearchSession-এর জন্য ListenableFuture পায়, যা ডেটাবেসের সাথে কানেকশনকে দেখায় এবং ডেটাবেস অপারেশনের জন্য API প্রদান করে।

Kotlin

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

স্কিমা সেট করুন

ডেটাবেসে ডকুমেন্ট রাখা এবং সেখান থেকে ডকুমেন্ট ফিরিয়ে আনার আগে আপনাকে অবশ্যই একটি স্কিমা সেট করতে হবে। ডেটাবেস স্কিমায় বিভিন্ন ধরনের স্ট্রাকচার্ড ডেটা থাকে, যাকে "স্কিমার ধরন" বলা হয়। নিম্নলিখিত কোডটি স্কিমা টাইপ হিসেবে ডকুমেন্ট ক্লাস প্রদান করে স্কিমা সেট করে।

Kotlin

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 সেট করে। তারপর ডকুমেন্টটি ডেটাবেসে যোগ করা হয় এবং পুট অপারেশনের ফলাফল প্রসেস করার জন্য একটি লিসেনার অ্যাটাচ করা হয়।

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
)

জাভা

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
)

জাভা

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
)

জাভা

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
)

জাভা

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)

জাভা

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
)

জাভা

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

অতিরিক্ত রিসোর্স

AppSearch সম্পর্কে আরও জানতে, নিম্নলিখিত অতিরিক্ত রিসোর্স দেখুন:

নমুনা

  • Android AppSearch Sample (Kotlin), একটি নোট নেওয়ার অ্যাপ যা ব্যবহারকারীর নোট ইন্ডেক্স করতে AppSearch ব্যবহার করে এবং ব্যবহারকারীদের তাদের নোট সার্চ করার অনুমতি দেয়।

মতামত জানান

এইসব রিসোর্সের মাধ্যমে আপনার মতামত ও আইডিয়া আমাদের সাথে শেয়ার করুন:

Issue Tracker

সমস্যার বিষয়ে অভিযোগ জানান, যাতে আমরা তা সমাধান করতে পারি।