この記事はバージョン Spring ’26 において執筆しています。
現在の動作と異なる場合がありますので、ご認識おきください。
RAGにおける「データの形」問題
AgentforceのRAG(検索拡張生成)を構築する際、最も頭を悩ませるのが「データ構造のフラット化」です。
Salesforceのデータモデルは、正規化(リレーション)によって美しく管理されていますが、AIのベクトル検索にとっては、情報がバラバラに散らばっている状態は好ましくありません。AIは「1つのレコードに全ての文脈が詰まっている」状態を好みます。
今回は、架空の不動産検索システム「Real Estate Search」の構築事例を元に、1対Nで紐づく設備データを、Data 360のデータ変換ビジュアルエディタだけで「1行のテキスト」にまとめ上げるテクニックをシェアします。
前提:今回のデータモデル(多対多の構造)
まず、今回扱うデータ構造を見てみましょう。不動産データは典型的な「多対多」の関係を持っています。
- 物件 (Building): 募集住戸がある「建物」。
- 募集住戸 (Listing): 貸し出しを募集している「部屋」。
- 設備マスタ (Feature): 「オートロック」「システムキッチン」などの設備定義。
- 住戸設備 (ListingFeature): どの部屋にどの設備があるかを繋ぐ中間テーブル。

データの重要ポイント:「AI検索用タグ」
特筆すべきは、設備マスタに持たせた SearchKeywords__c という項目です。
この項目には、設備名そのものではなく、ユーザーが検索しそうな「話し言葉」や「類義語」を定義しています。
| 設備名 (Name) | AI検索用タグ (SearchKeywords__c) |
| オートロック | 防犯, 安心, 女性, 安全, エントランス, 鍵 |
| 宅配ボックス | 不在, 荷物, 通販, Amazon, 受取, 置き配 |
このキーワード群を、募集住戸データ側に持ってくることが今回のゴールです。
課題:単純な結合(JOIN)はNG
Data 360でこれらを結合しようとすると、通常は以下のような問題が発生します。
失敗パターン:単純なJOIN
1つの部屋(101号室)に設備が3つある場合、JOINするとレコードが3行に増殖してしまいます。
| 住戸 | 設備 |
| 101号室 | オートロック (防犯…) |
| 101号室 | 宅配ボックス (不在…) |
| 101号室 | システムキッチン (料理…) |
これでは、AIが「101号室」を3つの別々のチャンクとして認識してしまい、正確な検索ができません。
欲しいのは、以下のような「1部屋1行」の完全なデータです。
101号室: オートロック 防犯… 宅配ボックス 不在… システムキッチン 料理… (これら全てを1つのテキスト項目に入れたい!)
しかし、Data 360に搭載されているデータ変換の「集計(Aggregate)」ノードには、テキストを結合する関数(Group Concat等)が存在しません。
解決策:ウィンドウ関数による「積み上げと抽出」
そこで、「累積結合」と「ランク付け」の組み合わせで解決です。
Step 1: 数式で「雪だるま式」にテキストを積み上げる
まず、[変換] ノードで行数式の数式をONにしてウィンドウ関数を使用し、設備キーワードを前の行からどんどん繋げていきます。
- 使用する関数:
array_joinとcollect_list - 数式:
array_join(collect_list("FeatureMaster__c_Home.SearchKeywords_c__c"), ',') - ウィンドウ設定:
- パーティションの基準: 募集住戸(部屋ごとに区切る)
- 並び替えの基準: 設備
- 並び替えの方向: 昇順

collect_list(field): 重複を含む複数値を返します。
array_join(mvField, delimiter, nullReplacement(optional)): 指定された区切り文字で区切られた要素を使用して、複数値を文字列に変換します。nullReplacement に文字列が指定されていない場合、null は無視されます。
この処理を通すと、データは以下のように変化します。
| 行 | データの中身 | 状態 |
| 1行目 | 「防犯…」 | まだ途中 |
| 2行目 | 「防犯…, 不在…」 | まだ途中 |
| 3行目 (同住戸内の最後) | 「防犯…, 不在…, 料理…」 | 全部入り(これが欲しい!) |
Step 2: 降順ランクで「最後の行」を特定する
欲しいのは「全部入り」になった最後の行だけです。そこで、同じくウィンドウ関数でランク付けを行います。
- 使用する関数:
row_number() - ウィンドウ設定:
- パーティションの基準: 募集住戸(部屋ごとに区切る)
- 並び替えの基準: 設備
- 並び替えの方向: 降順★

★ここがポイント:
Step 1と同じ並び順キーを使い、ここで「降順」にします。すると、最もデータが積み上がった最後の行が、常に「ランク1位」になります。
Step 3: フィルタで1位だけを抽出する
最後に [検索条件] ノードで不要な行を捨てます。
- 条件: 募集住戸内のランク計算 次の文字列と一致する
1

完成したデータと効果

この処理を経て出力された CombinedSearchText は、以下のような「情報の塊」になります。
物件: スカイハイツ横浜 601
キーワード: スカイハイツ横浜 601。横浜駅徒歩圏内の大規模マンション。築年数は経っているが、大規模修繕済みで管理体制は良好。敷地内に公園があり、子育て世帯が多い。スーパーも隣接しており生活利便性が非常に高い。誰が来た, 訪問者, 顔が見える, 防犯, 安心,セパレート, 独立, ゆったり, 脱衣所,ウォシュレット, 快適, トイレ, 清潔, 洗浄,朝の支度, 化粧, ヘアセット, 鏡, 収納, コンセント,ネット, Wi-Fi, リモートワーク, コスト削減, 使い放題,光回線, ヌルヌル, ゲーム, 動画, 配信, テレワーク,不在, 荷物, 通販, Amazon, 受取, 置き配
参考JSON
私が作成した一括処理データ変換のJSONデータをダウンロードできます。ご参考までにどうぞ。
Agentforceでの検索効果
このデータ変換を行ったことで、Agentforceは以下のようなユーザーの曖昧な発言を拾えるようになりました。
- 「Amazonよく頼むんだけど」
- → 「Amazon」「通販」が含まれるため、宅配ボックス付きの物件がヒット。
- 「ネット環境はヌルヌルがいい」
- → 「ヌルヌル」「配信」が含まれるため、高速ネット回線付きの物件がヒット。
- 「セキュリティ重視で」
- → 「顔が見える」「防犯」が含まれるため、TVモニタホン・オートロック付きがヒット。

まとめ
Data 360のデータ変換において、1対Nの関連レコードをフラット化する際、 「累積結合(ウィンドウ関数)」+「逆順ランク」+「フィルタ」 の3段活用をマスターすれば、どんな複雑なリレーションデータもAIにとって最適な形に整形できます。
ぜひ、皆さんのRAG構築でもこのテクニックを活用してみてください。
参考URL
数式のウィンドウ関数
数式の複数値関数



読者の声