14491


日記的なiOSアプリを作っている初心者です。

現在ローカルデータベース（RealmSwift）の設計を行っています。日記データそれぞれにつけることができるタグ機能を実装したいと考え、やり方を検索し、  
<http://colo-ri.jp/develop/2012/02/tag-database-schema-methods.html>  
上記のサイトにあったToxi法を使用しようと考えました。

次に、モデルを以下のように作成しました。

[code]

    class Notedatas: Object {
        dynamic var objectId = ""
        dynamic var userId = ""
        dynamic var noteText = ""
        dynamic var menuName = ""
        dynamic var PhotoPath = ""
        dynamic var goaltime:Double = 0
        dynamic var timer:Double = 0
    
        override static func primaryKey() -> String{
            return "objectId"
        }
    }
    
    class tag:Object {
        dynamic var id = ""
        dynamic var tagname = ""
    
        override static func primaryKey() -> String{
            return "id"
        }
    }
    
    class Notedatas_tag:Object{
        dynamic var id = ""
        dynamic var Notedata_id = ""
        dynamic var tag_id = ""
    
        override static func primaryKey() ->String{
            return "id"
        }
    }
    
[/code]

ここから、おそらく３つのテーブルのリレーションを定義しなくてはならないのだと思うのですが、

どのようにリレーションを繋げばよいのか？

また、実際にデータを追加するときに,3つのテーブルにどのように追加するのか？  
表示するときのタグの付け方、タグから検索するときの実装などがわかりません。

タグ機能実装のデータベースの設計や考え方、やり方を教えてください。


CC BY-SA 3.0
2015-08-16T14:14:35.977
14487
2015-08-16T15:19:15.283
2015-08-16T15:19:15.283
5519
10791
question
ios swift realm database
タグ機能の実装、データベースの設計について


RealmはMySQLのようなリレーショナルデータベースではなく、どちらかというオブジェクトデータベースに近いので、あまりリレーショナルデータベースのような設計を適用しようとするとかえって使いにくくなります。

Realmの場合は、スキーマの定義で関連を表現することができるのと、関連を取得するコストは低く、使い方もプロパティにアクセスするのと同様の方法で関連を辿ることができるので、あまり凝った構造にせず、表示に必要なデータ構造をそのまま表現するのがいいです。

### モデル定義

なので、スキーマの定義は最初は`Note`と`Tag`だけで十分だと思います。  
そして、各`Note`に`Tag`が複数つけることができるので、`Note`は`Tag`の関連として`tags`というプロパティを持ちます。

構造はScuttle法に似たものになります。

そして、Realmは逆方向の参照を定義することができ、これを使うと、ある`Tag`が付いている`Note`を取得することが簡単にできるようになって便利なのでそれも定義します。

ということでモデルは下記のようになります。

**変更点**

  * `Notedatas_tag`を削除しました
  * 名前を`Note`と`Tag`に変更しました
  * `Note`に`tags`プロパティを追加しました
  * `Tag`に`notes`プロパティを追加しました

以下、このモデルを使って説明します。

[code]

    class Note: Object{
        dynamic var objectId = ""
        dynamic var userId = ""
        dynamic var noteText = ""
        dynamic var menuName = ""
        dynamic var PhotoPath = ""
        dynamic var goaltime: Double = 0
        dynamic var timer: Double = 0
    
        let tags = List<Tag>()
    
        override static func primaryKey() -> String{
            return "objectId"
        }
    }
    
    class Tag: Object {
        dynamic var id = ""
        dynamic var tagname = ""
    
        var notes: [Note] {
            return linkingObjects(Note.self, forProperty: "tags")
        }
    
        override static func primaryKey() -> String{
            return "id"
        }
    }
    
[/code]

### データの追加

例えば、参考サイトにあるようなタグを４つ追加します。

[code]

    let realm = Realm()
    
    let tag1 = Tag()
    tag1.id = "1"
    tag1.tagname = "CSS"
    
    let tag2 = Tag()
    tag2.id = "2"
    tag2.tagname = "HTML"
    
    let tag3 = Tag()
    tag3.id = "3"
    tag3.tagname = "JavaScript"
    
    let tag4 = Tag()
    tag4.id = "4"
    tag4.tagname = "API"
    
    realm.write { () in
        realm.add(tag1)
        realm.add(tag2)
        realm.add(tag3)
        realm.add(tag4)
    }
    
[/code]

ノートにタグを付けるのは下記のようになります。  
例えば`note1`に`tag1`を付けるのは`note1.tags.append(tag1)`となります。  
タグは複数付けることができます。

[code]

    let note1 = Note()
    note1.objectId = "1"
    note1.noteText = "Sample text 1"
    
    note1.tags.append(tag1)
    note1.tags.append(tag2)
    
    let note2 = Note()
    note2.objectId = "2"
    note2.noteText = "Sample text 2"
    
    note2.tags.append(tag2)
    note2.tags.append(tag3)
    
    let note3 = Note()
    note3.objectId = "3"
    note3.noteText = "Sample text 3"
    
    note3.tags.append(tag3)
    note3.tags.append(tag4)
    
    realm.write { () in
        realm.add(note1)
        realm.add(note2)
        realm.add(note3)
    }
    
[/code]

### データの取得

例えば、"HTML"のタグが付いているノートを取得する場合は、下記のようにします。

[code]

    let notesWithHTML = realm.objects(Note).filter("ANY tags.tagname = %@", "HTML")
    
[/code]

またタグのインスタンスがあるなら、そこからそのタグが付いている`Note`を逆方向の関連を辿って取得することができます。

[code]

    // ２番目のタグのインスタンスを持っているとすると、
    let tag2 = realm.objectForPrimaryKey(Tag, key: "2")
    
    // 逆関連のプロパティから簡単にそのタグが付いているノート全部を取得できる
    let notesWithTag2 = tag2.notes
    
[/code]

上記のコードで、`notesWithHTML`と`notesWithTag2`はまったく同じデータ（`objectId = 1`のノートと`objectId
= 2`のノート）が取得されます。


CC BY-SA 3.0
2015-08-16T15:17:49.510
14491
2015-08-16T15:17:49.510
5519
14487
answer