匹配 Swift 中全文搜索的所有标记

Matching ALL tokens for full-text search in Swift

很抱歉有人问我这个问题,但我没有找到答案,但我正在尝试对 CloudKit 数据库进行全文搜索,其中 all 的搜索词匹配。我的例子如下:

var searchString = "almond salad"
let predicate = NSPredicate(format: "self CONTAINS %@", searchString)
let query = CKQuery(recordType: "Recipe", predicate: predicate)

我将省略所有其他代码来设置默认云数据库、执行查询等。它们都可以正确编译,但我想要它做的是给我任何包含 "almond" 和在同一条记录中包含 "salad" - 理想情况下我会得到杏仁沙拉食谱。照原样,它会给出诸如 "almond cake" 和 "tomato salad" 之类的记录,其中只有一个单词匹配(它还会给出 Almond Salad,但我想去掉其他的)。我想我没有正确阅读 CKQuery 文档,因为它似乎说所有标记都应该在一条记录中匹配,但它似乎并没有这样做。帮忙?

编辑:这是我根据 Dave 的回答得出的最终解决方案。

var searchString = "almond salad"
var formatString = ""

let searchStringArray = searchString.componentsSeparatedByString(" ")

if searchString != "" {
formatString = "self CONTAINS '\(searchStringArray[0])'"

if searchStringArray.count > 1 {
for var index = 1; index < searchStringArray.count; ++index {
formatString = formatString + " AND self CONTAINS '\(searchStringArray[index])'"
}
}

let predicate = NSPredicate(format: formatString)

编辑 2:我对撇号的格式化方式有疑问,所以我改变了(双关语)我的方法。这是我实际的最终解决方案。

var searchString = "momma's apple pie"
let searchStringArray = searchString.componentsSeparatedByString(" ")

if searchString.isEmpty { let predicate = NSPredicate(value: true) }

else {
switch (searchStringArray.count) {

case 1:
predicate = NSPredicate(format: "self CONTAINS %@", searchStringArray[0])

case 2:
predicate = NSPredicate(format: "self CONTAINS %@ AND self CONTAINS %@", searchStringArray[0], searchStringArray[1])

.
.
.

default:
print("Limiting search to 5 terms")
*copied and pasted case 5 predicate*

也许有点蛮力,但如果有人有更优雅的解决方案,我愿意听听。再次感谢您的帮助!

看起来像 CKQuery documentation is currently incorrect. I will file a bug 关于这个。

我通过执行以下操作获得了您想要的结果:

NSPredicate(format: "self CONTAINS 'almond' AND self CONTAINS 'salad'")

这意味着您需要一些额外的代码来用空格分隔字符串中的标记,然后构建此 AND 谓词以将它们放在一起(如果有两个或更多)。

为了用不限数量的单词分隔标记,我使用了这个通用解决方案:

    if searchString == "" {
        predicate = NSPredicate(value: true)

    } else {
       let searchArray: [String] = searchString.componentsSeparatedByString(" ")
        var exp = ""
        for key in searchArray {
            if searchArray.indexOf(key) == 0 {
                exp = "self CONTAINS '\(key)'"
            } else {
                exp += " and self CONTAINS '\(key)'"
            }
        }
        predicate = NSPredicate(format: exp)
    }

适用于 xCode 7.2.1 和 swift 2.1

HTH 罗伯托·塔加