匹配所有令牌以在Swift中进行全文搜索

时间:2015-09-29 20:10:02

标签: swift full-text-search token predicate cloudkit

如果有人问我并且我错过了答案,我很抱歉,但我正在尝试对CloudKit数据库进行全文搜索,其中所有的搜索字匹配。我的例子如下:

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

我将省略所有其他代码来设置默认云数据库,执行查询等。这一切都正确编译,但我想要它做的是给我任何包含“杏仁”并包含“沙拉”的记录在相同的记录 - 理想情况下我会得到杏仁沙拉食谱。按照它的方式,它将给出诸如“杏仁蛋糕”和“番茄沙拉”之类的记录,其中只有一个词匹配(它也会给出杏仁沙拉,但我想摆脱其他的)。我想我正在错误地阅读CKQuery文档,因为它似乎说所有标记应该在一条记录中匹配,但它似乎并没有这样做。帮助

编辑:这是基于戴夫答案的最终解决方案。

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*

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

2 个答案:

答案 0 :(得分:2)

看起来CKQuery documentation目前不正确。我会file a bug关于此事。

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

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

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

答案 1 :(得分:1)

为了使用无限数量的单词分隔令牌,我正在使用这种通用解决方案:

    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 罗伯托·塔加