0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TVerAdvent Calendar 2024

Day 17

Jetpack Compose で AppSearch に対応する

Last updated at Posted at 2024-12-16

AppSearch とは

テキストをオンデバイスで検索する機能の1つで、オフラインでも利用可能なライブラリです。
appsearch_overview_diagram.png

Low I/Oな為、SQLiteに比べ大規模なデータセットのインデックス作成と検索レイテンシが低くなります。

ユースケース例(以下リファレンスからの引用)

let’s take the example of a music application that manages users’ favorite songs and allows users to easily search for them. Users enjoy music from around the world with song titles in different languages, which AppSearch natively supports indexing and querying for. When the user searches for a song by title or artist name, the application simply passes the request to AppSearch to quickly and efficiently retrieve matching songs. The application surfaces the results, allowing its users to quickly start playing their favorite songs.

かなり具体的でイメージしやすいかと思います。

また、LocalStoragePlatformStorageの2種類が用意されていて違いとしては以下のような機能差があります。

スクリーンショット 2024-12-05 22.28.36.png

利用用途にもよりますが、今回は主に使用されるであろうLocalStorageに焦点を当ててご紹介します。

導入方法

下準備

利用するgradle(module)にAppSearchを追加します。

libs.versions.toml
[versions]
appSearch = "1.1.0-alpha06"
...

[libraries]
androidx-appsrarch = { group = "androidx.appsearch", name = "appsearch", version.ref = "appSearch" }
androidx-appsrarch-compiler = { group = "androidx.appsearch", name = "appsearch-compiler", version.ref = "appSearch" }
androidx-appsrarch-local-storage = { group = "androidx.appsearch", name = "appsearch-local-storage", version.ref = "appSearch" }
androidx-appsrarch-platform-storage = { group = "androidx.appsearch", name = "appsearch-platform-storage", version.ref = "appSearch" }
...
build.gradle.kts(app)
dependencies {
    ...
    implementation(libs.androidx.appsrarch)
    kapt(libs.androidx.appsrarch.compiler)
    implementation(libs.androidx.appsrarch.local.storage)
    implementation(libs.androidx.appsrarch.platform.storage)
    ...
}

利用方法

AppSearchのデータ単位であるドキュメントクラスを作成します。

Video.kt
@Document
public data class Video(
    @Document.Namespace
    val namespace: String,
    @Document.Id
    val id: String,
    @Document.Score
    val score: Int,
    @Document.StringProperty(indexingType = AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)
    val text: String
)

indexingTypeはPREFIXの他にも

  • INDEXING_TYPE_NONE
  • INDEXING_TYPE_EXACT_TERMS
    の3つから選ぶことができます。
    今回は部分一致での検索を行いたいので、PREFIXを指定しています。

次にDBの作成とSchemeの設定を行います

SampleActivity.kt

@Composable
fun MainScreen(applicationContext: Context) {
    val scope = rememberCoroutineScope()
    scope.launch(Dispatchers.IO) {
        // Database の作成(if it's not creared)
        val sessionFuture = LocalStorage.createSearchSessionAsync(
            LocalStorage.SearchContext.Builder(
                applicationContext, DATABASE_NAME
            ).build()
        )
        // Scheme の設定
        val setSchemaRequest = SetSchemaRequest.Builder()
            .addDocumentClasses(Video::class.java)
            .build()
        sessionFuture.get().setSchemaAsync(setSchemaRequest)
    }
}

ここまでできたら、データのインサートを行います。
※Sampleデータは複数件用意すると検索速度を感じやすいかと思います。

SampleActivity.kt
// Dataの追加
val video = Video(
    namespace = "HaSuzuki",
    id = "videoId",
    score = 20,
    text = "Sample Sports Highlights Video."
)
sessionFuture.get().putAsync(PutDocumentsRequest.Builder().addDocuments(
    video
).build()).get().let {
    if (it.isSuccess) {
        // something...
    }
}

検索も試してみます。

SampleActivity.kt
val searchSpec = SearchSpec.Builder()
    .setResultCountPerPage(1)
    .setSnippetCount(10)
    .build()
val result = sessionFuture.get().search("Video", searchSpec)
result.nextPageAsync.get().mapNotNull {
    if (it.genericDocument.schemaType == Video::class.java.simpleName) {
       val doc = it.getDocument(Video::class.java)
       // text = Sample Sports Highlights Video.
       Log.d("Hit Documents", doc.text)
    }
}

setSnippetCountのdefault = 0かつMAX_RANGEは10,000で設定されているのでご注意ください。

補足

SearchSpec は他にもORDER_BYRANKING_STRATEGYPREFIXのTERMなど様々な機能があります。

最後に

いかがだったでしょうか。比較的シンプルな実装で、規模に関わらず利用しやすいライブラリだったかと思います。
また、Sample数は少ないですが1,000件の場合でも取得にかかる時間が約30msという結果でした。速度の観点でも悪くない数字だと思います。

ぜひ、みなさんもオンデバイス検索を検討される際には AppSearch をお試しいただければと思います。

※現時点(2024/12/5)でappsearch-compilerkspに対応していなさそうなので、その点だけご注意ください。

TVer Advent Calender
@yabk さんによる 「CharlesのAndroid設定について」
@k0bya4 さんによる 「DBスキーママイグレーションの自動化について書きます」
になります。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?