Firestoreが全文検索非対応なので、Swiftの力を使って全文検索できるようにしてみた

<h1>はじめに</h1>
皆さん、明けましておめでとうございます！
IPFactoryの筋肉大好きごみちゃんです:muscle:<br>
今回は<strong>全文検索非対応のFirestoreをSwiftのライブラリの力を使って全文検索できるようにしてしまおう</strong>と言う記事です!<br>
それでは早速いってみましょう！


<h1>レイアウト設置</h1>
今回は検索ワードを打ち込む用のTextFieldと検索ボタンだけ設置します！
<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3130765/255eb400-932f-1815-a69e-75932baa87bc.png">

<h1>コーディング</h1>
今回はFirestoreに登録してある本のタイトルを全文検索で取得する想定でコードを書いていきます。<br>
Firestoreには事前に"Book"と言うコレクションの中に「ITパスポート」と言うワードが含まれている本を2冊登録しています。

それでは書いていきましょう！

まずはFirestoreをインポートして、インスタンスを定義しましょう。
```swift
import FirebaseFirestore
```
```swift
let db = Firestore.firestore()
```


次に各レイアウトの紐付けを行います。
```swift
    @IBOutlet weak var textField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        
    }
    
    @IBAction func searchButton(_ sender: Any) {
        
    }
```

紐付けができたら、検索文字と該当した本のタイトルを格納する用の変数を定義します。
```swift
var bookNames = [""]
```

ここからは関数を書いていきます！
```swift
    //登録してあるすべての本の情報を受け取る
    func getAllBook(){
        db.collection("Book").getDocuments { querySnapshot, error in
            if let error = error {
                print("Error getting documents: \(error)")
                return
            }

            guard let querySnapshot = querySnapshot else {
                print("Error: querySnapshot is nil")
                return
            }
            
            for document in querySnapshot!.documents{
                var Title = document["title"] as! String
                self.searchBookTitle(Title: Title)
            }
        }
    }
    
    //全文検索を行なって検索文字が含まれている本のタイトルを配列に格納する
    func searchBookTitle(Title:String){
        var flg :Bool = Title.contains(textField.text!)
        if flg == true {
            bookNames.append(Title)
        }
    }
```
これで該当する本のタイトルを取得できました！

ここからはwhereField文を使って、先ほど取得した本のタイトルから本の情報を取得したいと思います。
本のタイトルと念の為、事前に登録してあった本の著者名も出力されるか試してみます。
```swift
//本の情報を出力する
    func printBookInfo(){
        db.collection("Book").whereField("title", in: bookNames).getDocuments { querySnapshot, error in
            if let error = error {
                print("Error getting documents: \(error)")
                return
            }

            guard let querySnapshot = querySnapshot else {
                print("Error: querySnapshot is nil")
                return
            }
            
            for data in querySnapshot!.documents {
                var title = data["title"] as! String
                var author  = data["author"] as! String
                print(title)
                print(author)
            }
        }
    }
```

先ほど書いた関数の中で今作ったprintBookInfo()が動作するようにgetAllBook()内に「printBookInfo()」と書き加えます。
```swift
    //登録してあるすべての本の情報を受け取る
    func getAllBook(){
        db.collection("Book").getDocuments { querySnapshot, error in
            if let error = error {
                print("Error getting documents: \(error)")
                return
            }

            guard let querySnapshot = querySnapshot else {
                print("Error: querySnapshot is nil")
                return
            }
            
            for document in querySnapshot!.documents{
                var Title = document["title"] as! String
                self.searchBookTitle(Title: Title)
            }
        }
        printBookInfo()
    }
```

ここまでできたらいよいよ関数を動かしてみます！
searchButtonが押されたらgetAllBook()が動くように「getAllBook()」と書き加えてください！
```swift
    @IBAction func searchButton(_ sender: Any) {
        getAllBook()
    }
```

これでコーディング終了です！
お疲れ様でした:bow_tone1:
ちゃんと動くかどうか試しにビルドしてみてください。
<img width="650" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3130765/4fe39242-e483-a8f1-495c-dae271065936.png">
試しにビルドしてみたところうまくいきました！

<h1>コード全体</h1>

```swift
import UIKit
import FirebaseFirestore

class SearchWordViewController: UIViewController {
    
    let db = Firestore.firestore()
    var bookNames = [""]
    
    
    @IBOutlet weak var textField: UITextField!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

        
    }
    
    @IBAction func searchButton(_ sender: Any) {
        getAllBook()
    }
    
    //登録してあるすべての本の情報を受け取る
    func getAllBook(){
        db.collection("Book").getDocuments { querySnapshot, error in
            if let error = error {
                print("Error getting documents: \(error)")
                return
            }

            guard let querySnapshot = querySnapshot else {
                print("Error: querySnapshot is nil")
                return
            }
            
            for document in querySnapshot!.documents{
                var Title = document["title"] as! String
                self.searchBookTitle(Title: Title)
            }
        }
        printBookInfo()
    }
    
    //全文検索を行なって検索文字が含まれている本のタイトルを配列に格納する
    func searchBookTitle(Title:String){
        var flg :Bool = Title.contains(textField.text!)
        if flg == true {
            bookNames.append(Title)
        }
    }
    
    //本の情報を出力する
    func printBookInfo(){
        db.collection("Book").whereField("title", in: bookNames).getDocuments { querySnapshot, error in
            if let error = error {
                print("Error getting documents: \(error)")
                return
            }

            guard let querySnapshot = querySnapshot else {
                print("Error: querySnapshot is nil")
                return
            }
            
            for data in querySnapshot!.documents {
                var title = data["title"] as! String
                var author  = data["author"] as! String
                print(title)
                print(author)
            }
        }
    }
    
}
```

<h1>さいごに</h1>
今回はSwiftの力を使ってFirestoreに格納したデータを全文検索できるようにしてみました！
少しでも参考になれたなら嬉しいです
:muscle:<br>
まだまだプログラミング初心者なので至らない点も多かったかと思いますが、最後までご覧いただきありがとうございました:bow_tone1:<br>