匹配 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
罗伯托·塔加
很抱歉有人问我这个问题,但我没有找到答案,但我正在尝试对 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 罗伯托·塔加