AppSearch とは
テキストをオンデバイスで検索する機能の1つで、オフラインでも利用可能なライブラリです。
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.
かなり具体的でイメージしやすいかと思います。
また、LocalStorage
とPlatformStorage
の2種類が用意されていて違いとしては以下のような機能差があります。
利用用途にもよりますが、今回は主に使用されるであろうLocalStorage
に焦点を当ててご紹介します。
導入方法
下準備
利用するgradle(module)にAppSearchを追加します。
[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" }
...
dependencies {
...
implementation(libs.androidx.appsrarch)
kapt(libs.androidx.appsrarch.compiler)
implementation(libs.androidx.appsrarch.local.storage)
implementation(libs.androidx.appsrarch.platform.storage)
...
}
利用方法
AppSearchのデータ単位であるドキュメントクラスを作成します。
@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の設定を行います
@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データは複数件用意すると検索速度を感じやすいかと思います。
// 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...
}
}
検索も試してみます。
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_BY
やRANKING_STRATEGY
、PREFIXのTERM
など様々な機能があります。
最後に
いかがだったでしょうか。比較的シンプルな実装で、規模に関わらず利用しやすいライブラリだったかと思います。
また、Sample数は少ないですが1,000件
の場合でも取得にかかる時間が約30ms
という結果でした。速度の観点でも悪くない数字だと思います。
ぜひ、みなさんもオンデバイス検索を検討される際には AppSearch
をお試しいただければと思います。
※現時点(2024/12/5)でappsearch-compiler
はksp
に対応していなさそうなので、その点だけご注意ください。
TVer Advent Calender
← @yabk さんによる 「CharlesのAndroid設定について」
→ @k0bya4 さんによる 「DBスキーママイグレーションの自動化について書きます」
になります。