17
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ElasticsearchAdvent Calendar 2014

Day 4

ElasticsearchとSwiftで簡単mBaaSサンプルアプリ

Last updated at Posted at 2014-12-04

はじめに

この記事は ElasticsearchSwiftのAdvent Calendarを同時に攻略しようとする一石二鳥な実験的記事です。

Elasticsearch Advent Calendar 2014 4日目Swift Advent Calendar 2014 4日目を兼ねています。

概要

解析用サーバとしての利用が多いElasticsearchの「データストア」としての利用を促すために、最近流行りのmBaaSサーバとして簡単に構築してみました。

全てのロジックはSwift側で実装しており、Elasticsearchへは直接アクセスしています。

なので、本番環境としての利用はセキュリティ的におすすめしません。
実際に使うためには、SwiftとElasticsearchの間にWebアプリケーションを挟んで認証をショートカットされないようにする必要があります。
(ElasticsearchのPlugin作成が可能ならWebアプリケーションを利用せずに完結することも可能です。)

Screen Shot 2014-12-04 at 4.46.39.png

Elasticsearchの認証部分にelasticsearch-authを利用しています。

また、Swift側では、AlamofireSwiftyJSONを利用しています。

この実験に使ったコードはtadyjp/ElasticSwiftにあります。

``
$ version
Elasticsearch 1.4.0
Swift version 1.1 (swift-600.0.56.1)



![Screen Shot 2014-12-04 at 5.04.04.png](https://qiita-image-store.s3.amazonaws.com/0/10272/7c671e60-e04e-c734-dc63-fc45ef806ca2.png)

![Screen Shot 2014-12-04 at 5.03.56.png](https://qiita-image-store.s3.amazonaws.com/0/10272/b836446a-c91a-0c58-9a30-e9ddb1e1552b.png)


# Elasticsearchのコード

ありません!

indexの作成や検索は全てSwiftで実装しています。

# Swiftのコード

SwiftでのElasticsearchへの検索は次のコードがメインコードになります。

```swift
        let res = Alamofire.request(.POST, "http://localhost:9200/twitter/tweet/_search?q=user:\(self.username)", parameters: nil, encoding: .JSON)
            .responseJSON { (_, _, json, _) -> Void in
                let sjson = JSON(json!)
                if let hits = sjson["hits"]["hits"].array {
                    var tweets = [] as [String]
                    for subJson: JSON in hits {
                        println(subJson["_source"]["message"].string!)
                        tweets.append(subJson["_source"]["message"].string!)
                    }
                    block(tweets)
                } else {
                    println("getTweets error")
                }
        }

単純にJSONリクエストを行っているだけなので難しいところはありません。

user:<ユーザー名>

という検索クエリを発行することで、自分の投稿のみを抽出しています。

工夫が必要なのはログイン処理の部分です。


    class func currentUser() -> ElasticUser? {
        let ud = NSUserDefaults.standardUserDefaults()
        if let username = ud.objectForKey("username") as? String {
            let token = ud.objectForKey("token") as String
            let user = ElasticUser(username: username, token: token)
            println("currentUser = \(username)")
            return user
        } else {
            return nil
        }
    }

    class func signUp(username: String, password: String, block: (user: ElasticUser?) -> ()) {
        let params = [
            "authenticator": "index",
            "username": username,
            "password": password,
            "roles": "[\"user\"]"
        ]

        println("signUp...")

        let res = Alamofire.request(.PUT, "http://localhost:9200/_auth/account", parameters: params, encoding: .JSON)
            .responseJSON { (_, _, json, _) -> Void in
                let sjson = JSON(json!)
                println(sjson["status"])
                if sjson["status"] == 200 {
                    self.logIn(username, password: password, { (user2: ElasticUser?) in
                        block(user: user2)
                    })
                }
        }
    }

    class func logIn(username: String, password: String, block: (user: ElasticUser?) -> ()) {
        let params = [
            "username": username,
            "password": password
        ]

        println("logIn...")

        let res = Alamofire.request(.POST, "http://localhost:9200/login", parameters: params, encoding: .JSON)
            .responseJSON { (_, _, json, _) -> Void in
                let sjson = JSON(json!)
                println(sjson["status"])
                if sjson["status"] == 200 {
                    let user: ElasticUser? = ElasticUser(username: username, token: sjson["token"].string!)
                    block(user: user)
                } else {
                    block(user: nil)
                }
        }
    }

初回はログイン情報がないのでelasticsearch-authにユーザー作成を依頼します。
すると次回からはこのユーザー名とパスワードでログイン可能になり、一意のtokenが発行されるので、NSUserDefaultsなどに保存して次回以降のアクセス時に利用します。

まとめ

ちょっとしたクライアントサイドのコードだけでElasticsearchのスキーマレス性を活用したなんちゃってmBaaSが動いてしまいました。

これだけでは趣味の範囲は超えませんが、これをたたき台として、なにか新しいアプリケーションの発想が生まれると幸いです。

17
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?