2015-09-29 2 views
2

Приносим извинения, если это было задано, и я пропустил поиск ответа, но я пытаюсь выполнить полный текстовый поиск базы данных CloudKit, где все поиска слов. Мой пример ниже:Согласование всех токенов для полнотекстового поиска в Swift

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) 

Edit 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

Похоже, что CKQuery documentation в настоящее время некорректен. Я буду file a bug об этом.

Я был в состоянии получить результат, который вы хотели, выполнив следующие действия:

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

Это означает, что вам нужно немного дополнительного кода для разделения лексем в вашей строке через пробел, а затем построить это и предикат собрать их вместе (если их два или более).

+0

Спасибо, что проверил, я собирался с ума сойти, думая, что я не понимаю документацию. Я довольно новичок в Swift, но думаю, что я проложил канал с помощью решения. Поскольку я не знаю, сколько слов пользователь будет искать, я разбил searchString на массив и использовал цикл for, просто добавляя каждый элемент массива в формат предиката stringString. У меня проблемы с получением кода для работы в комментариях (я новичок в этом), я думаю, что это работает ... Спасибо за помощь! –

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 и быстры 2,1

НТН Роберто Targa