多対多

□未翻訳

□翻訳中

■翻訳完了(細田謙二)

■レビュー(Omi Chiba)

多対多

前述の例では、1匹のdogは1人の所有者(owner)を持つけれど、1人のpersonは多くのdogsを持つようにしました。AlexとCurtによって所有されたSkipperはどうなるのでしょうか?これには多対多のリレーションが必要です。そしてこれは、所有(ownership)関係で1人のpersonと1匹のdogをリンクする中間テーブルを介して実現されます。

In the previous examples, we allowed a dog to have one owner but one person could have many dogs. What if Skipper was owned by Alex and Curt? This requires a many-to-many relation, and it is realized via an intermediate table that links a person to a dog via an ownership relation.

どのようにそれを行うかを以下に示します:

Here is how to do it:

1.

2.

3.

4.

5.

6.

7.

>>> db.define_table('person',

Field('name'))

>>> db.define_table('dog',

Field('name'))

>>> db.define_table('ownership',

Field('person', db.person),

Field('dog', db.dog))

これまでの所有(ownership)関係は次のように書き換えることができます:

the existing ownership relationship can now be rewritten as:

1.

2.

3.

>>> db.ownership.insert(person=1, dog=1) # Alex owns Skipper

>>> db.ownership.insert(person=1, dog=2) # Alex owns Snoopy

>>> db.ownership.insert(person=2, dog=3) # Bob owns Puppy

今度は、CurtがSkipperを共同所有するという新しいリレーションを加えることができます:

Now you can add the new relation that Curt co-owns Skipper:

1.

>>> db.ownership.insert(person=3, dog=1) # Curt owns Skipper too

3方向のテーブル間のリレーションを持っているので、操作を実行する上で、次のような新規のセットを定義するのは便利です:

Because you now have a three-way relation between tables, it may be convenient to define a new set on which to perform operations:

1.

2.

3.

>>> persons_and_dogs = db(

(db.person.id==db.ownership.person) \

& (db.dog.id==db.ownership.dog))

ここで、新規のSetからすべてのpersonsと彼らのdogsを選択するのは簡単です:

Now it is easy to select all persons and their dogs from the new Set:

1.

2.

3.

4.

5.

6.

>>> for row in persons_and_dogs.select():

print row.person.name, row.dog.name

Alex Skipper

Alex Snoopy

Bob Puppy

Curt Skipper

同様に、Alexが所有するすべてのdogsを検索することもできます:

Similarly, you can search for all dogs owned by Alex:

1.

2.

3.

4.

>>> for row in persons_and_dogs(db.person.name=='Alex').select():

print row.dog.name

Skipper

Snoopy

そして、Skipperの所有者も検索することができます:

and all owners of Skipper:

1.

2.

3.

4.

>>> for row in persons_and_dogs(db.dog.name=='Skipper').select():

print row.person.name

Alex

Curt

多対多への軽い代替案はタグ付けです。タグ付けはIS_IN_DBの文脈で後述します。タグ付けは、Google App EngineのようなJOINをサポートしていないデータベース・バックエンドでも機能します。

A lighter alternative to Many 2 Many relations is a tagging. Tagging is discussed in the context of the IS_IN_DB validator. Tagging works even on database backends that does not support JOINs like the Google App Engine.