|
|
@ -129,26 +129,20 @@ public class FullTextSearchFinder: NSObject {
|
|
|
|
return charactersToFilter
|
|
|
|
return charactersToFilter
|
|
|
|
}()
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This is a hot method, especially while running large migrations.
|
|
|
|
|
|
|
|
// Changes to it should go through a profiler to make sure large migrations
|
|
|
|
|
|
|
|
// aren't adversely affected.
|
|
|
|
public class func normalize(text: String) -> String {
|
|
|
|
public class func normalize(text: String) -> String {
|
|
|
|
// 1. Filter out invalid characters.
|
|
|
|
// 1. Filter out invalid characters.
|
|
|
|
let filtered = text.unicodeScalars.lazy.filter({
|
|
|
|
let filtered = text.removeCharacters(characterSet: charactersToRemove)
|
|
|
|
!charactersToRemove.contains($0)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Simplify whitespace.
|
|
|
|
// 2. Simplify whitespace.
|
|
|
|
let simplifyingFunction: (UnicodeScalar) -> UnicodeScalar = {
|
|
|
|
let simplified = filtered.replaceCharacters(characterSet: .whitespacesAndNewlines,
|
|
|
|
if CharacterSet.whitespacesAndNewlines.contains($0) {
|
|
|
|
replacement: " ")
|
|
|
|
return UnicodeScalar(" ")
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
return $0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let simplified = filtered.map(simplifyingFunction)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 3. Strip leading & trailing whitespace last, since we may replace
|
|
|
|
// 3. Strip leading & trailing whitespace last, since we may replace
|
|
|
|
// filtered characters with whitespace.
|
|
|
|
// filtered characters with whitespace.
|
|
|
|
let result = String(String.UnicodeScalarView(simplified))
|
|
|
|
return simplified.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
|
return result.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: - Index Building
|
|
|
|
// MARK: - Index Building
|
|
|
@ -248,9 +242,7 @@ public class FullTextSearchFinder: NSObject {
|
|
|
|
let contentColumnName = "content"
|
|
|
|
let contentColumnName = "content"
|
|
|
|
|
|
|
|
|
|
|
|
let handler = YapDatabaseFullTextSearchHandler.withObjectBlock { (transaction: YapDatabaseReadTransaction, dict: NSMutableDictionary, _: String, _: String, object: Any) in
|
|
|
|
let handler = YapDatabaseFullTextSearchHandler.withObjectBlock { (transaction: YapDatabaseReadTransaction, dict: NSMutableDictionary, _: String, _: String, object: Any) in
|
|
|
|
if let content: String = indexContent(object: object, transaction: transaction) {
|
|
|
|
dict[contentColumnName] = indexContent(object: object, transaction: transaction)
|
|
|
|
dict[contentColumnName] = content
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// update search index on contact name changes?
|
|
|
|
// update search index on contact name changes?
|
|
|
@ -262,3 +254,15 @@ public class FullTextSearchFinder: NSObject {
|
|
|
|
versionTag: "1")
|
|
|
|
versionTag: "1")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extension String {
|
|
|
|
|
|
|
|
func replaceCharacters(characterSet: CharacterSet, replacement: String) -> String {
|
|
|
|
|
|
|
|
let components = self.components(separatedBy: characterSet)
|
|
|
|
|
|
|
|
return components.joined(separator: replacement)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func removeCharacters(characterSet: CharacterSet) -> String {
|
|
|
|
|
|
|
|
let components = self.components(separatedBy: characterSet)
|
|
|
|
|
|
|
|
return components.joined()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|