Parse(Parse.com)のQueryまとめ


iosの開発に非常に重宝するparse。
そのparseでもかなり使われてるquery周りをまとめてみました。

Relation周りの検索が思いの他documentになく、ちょっと最初苦戦したので、皆さんの参考になれば。
ドキュメントは[こちら](https://www.parse.com/docs/ios_guide#queries/iOS)

##今回の想定

よくあるUserと、ユーザの友達を管理したFriendのテーブルを用いて使い方を説明していきます。

データは下記の通りです。皆さんのデータ構造に合わせて理解してもらえれば。
※objectIdは全て適当に作った乱数を今回は入れてます

####User

| objectId   | name        |  age         |  createAt     |    updatedAt  |
|:-----------|------------:|:------------:| :------------:| :------------:|
| avnhsJwvDB |        John |     23       |      2014-09-07T09:30:52.167Z         |      2014-09-07T09:30:52.167Z         |
| o6Ny5quOvf |    Moriyaman|    24        |       2014-09-07T09:32:52.167Z        |       2014-09-07T09:32:52.167Z        |
| XlUir6hVPr |        Mike |     25       |       2014-09-07T09:34:52.167Z        |        2014-09-07T09:34:52.167Z       |
| UxoYk7hEjT |      Sakiko |      20      |       2014-09-07T09:36:52.167Z        |        2014-09-07T09:36:52.167Z       |
| thUC9aAKNm |     Takashi |    32        |        2014-09-07T09:38:52.167Z       |        2014-09-07T09:38:52.167Z       |
| wXxDHbI6e7 |     Takahiro|    34        |        2014-09-07T09:40:52.167Z       |        2014-09-07T09:40:52.167Z       |

####Friend

| objectId    | user                  |  friendUser              |  createAt     |    updatedAt  | userObjectId | friendUserObjectId|
|:-----------:| :------------:        |:------------:            | :------------:| :------------:|:------------:| :------------:    |
| BzuX9rcOl3  |        view Relations |     view Relations       |       2014-09-07T09:38:52.167Z        |  2014-09-07T09:38:52.167Z             |    avnhsJwvDB (John)        |      o6Ny5quOvf (Moriyaman)            |
| 76t3VnL1Vf  |    view Relations     |    view Relations        |       2014-09-07T09:38:52.167Z        |        2014-09-07T09:38:52.167Z       |         XlUir6hVPr(Mike)     |  UxoYk7hEjT(Sakiko)                 |


##初級編

まずは、ユーザのテーブルから希望のデータを検索していきます。
個人的には、relationを使わず単純に出す場合はNSPredicate ver.の方がオススメです。
※日頃sql文を書く事が多いので、慣れているという理由ですが...w

####(i) age の比較

PFQuey ver.

```
//common
PFQuery *userQuery = [PFUser query];

// age = 18
[userQuery whereKey:@"age" equalTo: @18];

// age > 18
[userQuery whereKey:@"age" greaterThan: @18];

// age >= 18
[userQuery whereKey:@"age" greaterThanOrEqualTo: @18];

// age < 18
[userQuery whereKey:@"age" lessThan: @18];

// age <= 18
[userQuery whereKey:@"age" lessThanOrEqualTo: @18];

```

NSPredicate ver.

```
// age = 18
NSPredicate *predicate = [NSPredicate predicateWithFormat:
                          @"age = 18"];

// age > 18
NSPredicate *predicate = [NSPredicate predicateWithFormat:
                          @"age > 18"];

// age >= 18
NSPredicate *predicate = [NSPredicate predicateWithFormat:
                          @"age >= 18"];

// age < 18
NSPredicate *predicate = [NSPredicate predicateWithFormat:
                          @"age < 18"];

// age <= 18
NSPredicate *predicate = [NSPredicate predicateWithFormat:
                          @"age <= 18"];

// common
PFQuery *query = [PFQuery queryWithClassName:@"User" predicate:predicate];
```

####(ii) like 検索

PFQuey ver.

```
// name like 'Taka%'
[userQuery whereKey:@"name" hasPrefix:@"Taka"];

```

NSPredicate ver.

```
// name like 'Taka%'
NSPredicate *pred = [NSPredicate predicateWithFormat:@"name BEGINSWITH 'Taka'"];

```

####(iii) order

```
// order by age ASC
[query orderByAscending:@"age"];

```

```
// order by age Desc
[query orderByDescending:@"age"];

```

####(iv) in or not in 検索

PFQuey ver.

```
// common
NSArray *names = @[@"Moriyaman",
                   @"John"];

// name in (Moriyaman, John)
[userQuery whereKey:@"name" containedIn:names];

// name not in (Moriyaman, John)
[userQuery whereKey:@"name" notContainedIn:names];

```

NSPredicate ver.

```
// common
NSArray *names = @[@"Moriyaman",
                   @"John"];

// name in (Moriyaman, John)
NSPredicate *pred = [NSPredicate predicateWithFormat:
                     @"name IN %@", names];

// name not in (Moriyaman, John)
NSPredicate *pred = [NSPredicate predicateWithFormat:
                     @"NOT (name IN %@)", names];

```

##中級編 Part1

リレーション周りです。
※こっちはPFQueryのみ

(i)ログインしているユーザの友達一覧をFriendテーブルから引っ張ってくる

```
 // 友達ユーザ一覧を獲得
    PFUser * loginUser = [PFUser currentUser];
    PFQuery *friendQuery = [PFQuery queryWithClassName:@"Friend"];
    [friendQuery whereKey:@"user" equalTo: loginUser];
```


(ii)age>23のユーザの友達をFriendテーブルから引っ張ってくる

```
 // 友達ユーザ一覧を獲得
　　PFQuery *userQuery = [PFUser query];
   [userQuery whereKey:@"age" greaterThan: @23];
   PFQuery *friendQuery = [PFQuery queryWithClassName:@"Friend"];
   [friendQuery whereKey:@"user" matchesQuery: userQuery];

```

##中級編 Part2

リレーション周りですが先程とは結果のデータが違います。

(i)ログインしている友達一覧をUserテーブルから引っ張ってくる

```
 // 友達ユーザ一覧を獲得
    PFUser * loginUser = [PFUser currentUser];
    PFQuery *friendQuery = [PFQuery queryWithClassName:@"Friend"];
    [friendQuery whereKey:@"user" equalTo: loginUser];
    PFQuery *userQuery = [PFUser query];
    [userQuery whereKey:@"objectId" matchesKey:@"friendUserObjectId" inQuery:friendQuery];

```

(iii)ログインして友達じゃないユーザ一覧をUserテーブルから引っ張ってくる

```

 // 友達じゃないユーザ一覧を獲得
    PFUser * loginUser = [PFUser currentUser];
    PFQuery *friendQuery = [PFQuery queryWithClassName:@"Friend"];
    [friendQuery whereKey:@"user" equalTo: loginUser];
    PFQuery *userQuery = [PFUser query];
　　[userQuery whereKey:@"objectId" doesNotMatchKey:@"friendUserObjectId" inQuery:friendQuery];

```

これで一覧を取れます。
最初データ構造に"userObjectId" と "friendUserObjectId" を入れておらず、
どうにかして出来ないかとググりながらチャレンジしましたができず。。。。

同じような質問を[stackoverflow](http://stackoverflow.com/questions/25268023/parse-pfquery-across-a-relationship)でみつけましたが、objectIdをカラムに追加して比較しないと出来ないよと・・・。
って事で、やむなく追加したらできました。

正規化できてねぇ...という感情は一旦捨てましょうw


##最後に...

中級編Part2でかなり詰まりました。。。
その他はドキュメントを見れば大概書いていたので、そこまで問題なくできました。

普段rubyで書いているので、[parse-ruby-client](https://github.com/adelevie/parse-ruby-client)のgemを使ってみてもいいかなーと思ってます。
Parse.com超絶便利ですね！w