Core Spotlight:セマンティック検索を試みる – その2 (CSUserQuery)

前回の続き: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件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です