2016-08-13 26 views
3

我想使用SQLite.swift查詢FTS表。 Previously I have done it in Android。什麼我試圖做的實質是this如何使用IN條件訪問SQLite.swift中的FTS表

SELECT * 
FROM t2 
WHERE id IN (SELECT docid 
      FROM fts_table 
      WHERE col_text MATCH 'something') 

SQLite.swift documentation我看到IN condition可以這樣寫this

users.filter([1, 2, 3, 4, 5].contains(id)) 
// SELECT * FROM "users" WHERE ("id" IN (1, 2, 3, 4, 5)) 

和虛擬表可以查詢像this

let wonderfulEmails = emails.match("wonder*") 
// SELECT * FROM "emails" WHERE "emails" MATCH 'wonder*' 

let replies = emails.filter(subject.match("Re:*")) 
// SELECT * FROM "emails" WHERE "subject" MATCH 'Re:*' 

但是,我不知道如何結合這些。我真的不想要execute arbitrary SQL(儘管這現在工作得益於this answer的幫助)。

更新

這是我最新的嘗試是不工作:

let tableText = Table("t2") 
let id = Expression<Int64>("id") 
let someColumn = Expression<String>("someColumn") 

let tableFts = VirtualTable("fts_table") 
let columnDocId = Expression<Int64>("docId") 


let ftsQuery = tableFts 
    .select(columnDocId) 
    .filter(tableFts.match("something")) 
let tableQuery = tableText 
    .filter((try db.prepare(ftsQuery)) 
     .contains(id))      // <-- error 

for row in try db.prepare(tableQuery) { 
    print(row[someColumn]) 
} 

其中具有contains(id)行引發錯誤:

Cannot convert value of type 'Expression' to expected argument type '@noescape (Row) throws -> Bool'

+0

您是否有示例代碼片段和失敗?你想做什麼不起作用? – stephencelis

+0

@stephencelis,我已添加更新。在這次最新的嘗試中,我嘗試將它分解爲兩個查詢,因爲我不知道有任何方法可以在單個查詢中執行。 – Suragch

+0

我不相信你能夠在FTS表的查詢中使用表達式。如果您查看fts表的db模式,您會注意到type列是空的,而不是顯示預期的類型(如常規表中所述)。不確定爲什麼sqlite會像這樣工作,但我已經能夠工作的唯一一件事是循環遍歷返回的語句行。想知道你是否能夠進一步提高這一點。 –

回答

1

我最終只是運行原始的SQL命令。這並不完全回答我在問題中提出的問題(因爲它不使用純SQLite.swift API),但對於那些只需要得到某些工作的人來說......可以工作。

這裏是我從我的一些源代碼中提取的一個修改後的示例。

static func findLinesContaining(_ searchTerms: String, forSearchScope scope: SearchScope) throws -> [TextLines] { 

    guard let db = SQLiteDataStore.sharedInstance.TextDB else { 
     throw DataAccessError.datastore_Connection_Error 
    } 

    // TODO: convert to SQLite.swift syntax rather than using a SQL string 
    var statement: Statement? = nil 
    switch scope { 
    case .wholeCollection: 
     statement = try db.run("SELECT bookId, chapterId, lineId, lineText" + 
      " FROM lines" + 
      " WHERE rowid IN (SELECT docid FROM fts_table" + 
      " WHERE fts_table MATCH ?);", searchTerms) 

    case .singleBook(let chosenBookId): 
     statement = try db.run("SELECT bookId, chapterId, lineId, lineText" + 
      " FROM lines" + 
      " WHERE rowid IN (SELECT docid FROM fts_table" + 
      " WHERE fts_table MATCH ?) AND bookId = ?;", [searchTerms, chosenBookId]) 
    } 


    var returnList: [TextLine] = [] 
    for row in statement! { 

     let line = TextLine() 
     if let bookId = row[0] as? Int64, 
      let chapterId = row[1] as? Int64, 
      let lineId = row[2] as? Int64, 
      let text = row[3] as? String { 

      line.bookId = Int(bookId) 
      line.chapterId = Int(chapterId) 
      line.lineId = Int(lineId) 
      line.lineText = text 
     } 

     returnList.append(line) 
    } 

    return returnList 
} 

上面的代碼在重命名用於SO的變量和類之後未經測試。如果您發現錯誤,您有權限編輯代碼。

+0

謝謝!我嘗試了類似的東西,但沒有使用參數佔位符(?);我將繼續前進。 +1的有用份額。 –