前回の続き:Core Spotlight:セマンティック検索を試みる – その1
Core Spotlight で自前でインデクシングしたコンテンツを検索する場合、CSSearchQuery を使って検索クエリを作成する場合、専用のクエリ文字列を複雑なルールに従って構築する必要がある。
/// Using CSSearchQuery
// Build a query with keywords
func buildQuery(with keywords: [String]) -> String {
// refer to:
// Searching for information in your app | Apple Developer Documentation
// https://developer.apple.com/documentation/corespotlight/searching-for-information-in-your-app
let perWordQueries: [String] = keywords.map { word in
let v = "\"*\(word)*\"c" //大文字小文字を無視
return "(title == \(v)) || (textContent == \(v)))"
}
return perWordQueries.count > 1
? "(" + perWordClauses.joined(separator: ") && (") + ")"
: perWordClauses.first ?? ""
}
let searchQuery = buildQuery(with: keywords)
let context = CSSearchQueryContext()
let query = CSSearchQuery(
queryString: searchQuery,
queryContext: context
)
// Event handling
query.foundItemsHandler = { items in ...
query.completionHandler = { error in ...
// Start searching
query.start() 一方、ユーザーが入力した文字列を元にセマンティックに検索したいばあいは、CSUserQuery が便利。入力された文字列をそのまま、userQueryString としてクエリのイニシャライザに渡すことができる。
/// Using CSUserQuery
let context = CSUserQueryContext()
let query = CSUserQuery(
userQueryString: searchQuery,
userQueryContext: context
)
for try await element in query.responses {
switch(element) {
case .item(let item):
// 検索結果に対する処理
case .suggestion(let suggestion):
//サジェスト候補に対する処理
@unknown default: break
}
}しかし、検索結果はとてもセマンティックとは言い難く、部分一致的な挙動しかしてくれない。
Core Spotlight に関する素晴らしい記事を発見し(しかも投稿が2週間前)、これを参考にしている。
Core Spotlight integration for Spotlight and internal app search
追記(2025/09/09)
Core Spotlight のセマンティック検索が部分一致的な挙動しかしないのは、実装の問題ではなく、Siri の性能限界であると Apple の方が教えてくださった。セマンティック検索のセッション(WWDC24)で実演され、また言及もされているデモアプリのサンプルコードについても、いくら探しても見つからなかったが、これもそもそも公開されていないということだった。一件落着(?)。
「Core Spotlight:セマンティック検索を試みる – その2 (CSUserQuery)」への1件のフィードバック