---
title: "データの結合"
slug: "joining-data"
abstract: "結合はデータベース内の2つ以上のテーブルからのレコードを統合します。"
---
# データの結合

ジョイン(またはジョイン文)は、データベース内の2つ以上のテーブルのレコードを組み合わせるものです。このトピックでは、ジョインを使う際に考慮すべき点について説明します。

LINQレイヤーは以下の4つの結合( Join、Self Join、Group Join、Select Many)をサポートしています。これら4つの方法は、ユーザーがデータをページングする際に評価されるサブクエリを使用します。Solrは特定の側面のみをサポートしています。

> !重要これらの方法はできるだけ避けるべきです。これらはすべて、処理時間、I/O量、メモリ使用量の両面でパフォーマンスに悪影響を及ぼします。

例えば、LINQを使ったJoinクエリを使って、連絡先をこれまでの関与状態に結合します。ユーザーがデータをページングする際、ジョインまたはサブクエリは最初のページのみを実行します。つまり、IDが与えられたとき、そのIDを通じて別のドキュメントを調べるためにサブクエリを実行します。

LINQでJoinクエリを実行すると、実質的に1つまたは複数のドキュメントのユニオンセットを返します。LINQクエリを書く際も、結合付きクエリを書くのと同様にパフォーマンスSQL考慮する必要があります。また、データを適切に保存・インデックス化することも必要です。Sitecore LINQでは多対1または多対多クエリ(例えば、複数の関与状態を参照し、それらを関与状態文書に連結するContact)をサポートしていません。

「foreign-key」をEngagement Stateに付与すれば、代わりにContactIdのようなものを使って参加できます:

public class Contact {
public string Name { get; set; }
public Guid ContactId { get; set; }
}
public class EngagementState {
public string Name { get; set; }
public Guid ContactId { get; set; }
public Guid Id { get; set; }
}

上記のクラスを踏まえ、データの重複を生むものの、ContactIdを通じてContactsをEngagement Statesに結合することが可能になります。LINQレイヤーはこれをサポートしています。例えば:

var repo = this.CreateVisitors();
var repoPlans = this.GetStates();
var result = from t in repo
join x in repoPlans on t.ContactId equals x.ContactId
where x.Id == new Guid("E1B604F1-EE0E-408E-A344-869CC45D25D9")
select t;

## LINQScratchPadでのテスト

LinqScratchPad.aspxでは大量のデータに対してジョインをテストできます。例えば:

using (var context = ContentSearchManager.GetIndex("sitecore\_master\_index").CreateSearchContext())
{
 using (var context2 = ContentSearchManager.GetIndex("sitecore\_web\_index").CreateSearchContext())
 {
 return context.GetQueryable<SearchResultItem>().Join(context2.GetQueryable<SearchResultItem>()
 .Where(i => i.Name.StartsWith("S")), i => i.ItemId, o => o.ItemId, (o, i) => o).Take(10).ToList();
 }
}

これにより2つの別々の検索コンテキストが開かれ、ItemIdに基づいてそれらに結合を実行します。この例では、名前フィールドがSで始まる項目がwebとmasterの両方に含まれているかをチェックし、webインデックス(外側)の結果を返します。

## ソルに加わる

Solrプロバイダーを使う場合、Self Joinだけが実際のSolrジョインを実行します。他の方法( JoinやGroup Joinなど)は、Lucene.netプロバイダーが使う列挙技術を用いています。列挙時にサブクエリを実行して他のドキュメントを取得します。

## ジョインを使うタイミング

LINQレイヤーで、別のドキュメントへの参照を含むドキュメントがある場合、ジョインを使う必要があります。その参照は通常ID参照です。

Sitecoreクロールするオブジェクトをフラット化するわけではありません。クローラー実装はSitecoreにデータの保存方法を指示しなければなりません。 Join、Self Join、またはGroup Joinメソッドは、ジョインのサブクエリを実行し、別のドキュメントを取得してID/キーに基づいて評価します。

データを適切に保存する必要があります。データを準備して参加できるようにすることも、完全に結合なしで取得できるように準備することもできます。どちらの方法にも利点と欠点があります。

ソリューションがうまくスケールできるように、以下のルールに従ってください:

-   ジョインの数を制限しましょう。
-   結合の代わりにデータをフラット化することを検討してください。これにより、多値フィールドや多くの列が生成されます。
-   ジョインを使う場合は、データのページ数を小さく、10〜20項目ずつに保ちましょう。理由は、クエリが100ミリ秒かかる場合、サブクエリと最初のクエリの返却に1.1秒かかる可能性があるからです。
-   100%必要なものだけを保存またはインデックスしてください(パフォーマンスに影響がない限り)。

## ジョイン、セルフジョイン、グループジョイン方法の違い

例えば、以下の2つのデータ表がある場合:

ID

価値

1

A

2

B

3

C

ID

チャイルドバリュー

1

A1

1

A2

1

A3

2

B1

2

B2

Idフィールドの2つのリストにJoin法を使うと、結果は次のようになります。

価値

チャイルドバリュー

A

A1

A

A2

A

A3

B

B1

B

B2

Idフィールドの2つのリストにGroup Joinメソッドを使うと、結果は次のようになります。

価値

チャイルドバリュー

A

\[a1, a2, a3\]

B

\[b1, b2\]

C

\[\]

Idフィールドの2つのリストにSelf Joinメソッドを使うと、結果は次のようになります。

価値

チャイルドバリュー

A

A1

A

A2

A

A3

B

B1

B

B2

Self Joinメソッドを使う場合は、resultSelectorパラメータを提供する必要はありません。外部の結果を返すと推定されます。これは本質的に内側の結合と外部結合の違いです。

> !注結合クエリを実行する際、内側または外部の結合には結果を制限するフィルターが必要です。そうでなければ、結合クエリはインデックス内のすべてのドキュメントで結合しようとします。