Feast は高レベルの FeatureStore APIを提供しており、機能と機能のグループ( 機能ビュー )、オンライン ストレージとオフラインストレージ、およびオフラインからオンラインストレージにデータを動的に移動する能力( マテリアライズド)を定義できます。 MongoDB統合により、 MongoDB をFeast のオンラインとオフラインの両方のストアとして使用できるため、個別のストレージシステムを維持することなく、機能を一度定義して、モデル訓練やオンライン推論で一貫して提供できます。
MongoDB の柔軟なドキュメントモデルとMQLにより、オフライン ストアに必要な複雑なクエリ パターンを処理できます。オンライン ストアでは、 MongoDBはウェブスケールのアクセス パターン(高速読み取り/書込み、水平スケーリング、結合やラウンド トリップを最小限に抑える柔軟なスキーマ)に最適化されています。
この統合の概要では、次の項目が見つかります。
Feast のオンラインおよびオフライン ストアとしてのMongoDBの紹介。
Feast の概念がMongoDBにどのようにマッピングされるか。
MongoDB のオフラインとオンライン ストアのデザインの詳細な説明。
Feast にMongoDBストアを設定するための構成例。
重要な概念
オンラインストアとオフラインストア
オンライン ストアは、オンライン推論中にエンティティごとの最新機能を低レイテンシで取得するために最適化された、単一のMongoDBコレクション を基盤としたキーと値のストアです。
オフラインレイヤーは、データセットの訓練、スコアリング、マテリアライズド(オンラインストアにデータを推奨)するために、 MongoDBコレクション(通常は
feature_historyと呼ばれる)に保存されている履歴機能データの行をクエリするコンピューティングおよび翻訳レイヤーです。
一般的なワークフロー パターン
一般的なエンドツーエンドのワークフローは次のようになります。
MongoDBベースのコレクションを点エンティティ、機能ビュー、データソースを定義します。
offline_write_batch経由で機能データをオフライン ストアに取り込みます。PyArrow テーブルを入力として受け入れ、オフライン ストアスキーマに従ってfeature_historyMongoDBコレクションにデータを挿入します。get_historical_featuresを使用して訓練データを生成します。これにより、 MongoDBに保存されている履歴機能行に対して効率的なポイントインタイム結合が実行されます。pull_latest_from_table_or_queryとonline_write_batchを使用して、オフライン ストアの最新の機能値をオンライン ストアに具体化します。Feast のオンライン API 経由で機能をオンラインで提供します。この API は、シリアル化されたエンティティ キーでキー付けされた単一のMongoDBコレクションから読み取ります。
Feast の概念がMongoDBにどのようにマッピングされるか
MongoDB の統合は Feast の標準概念モデルに従いますが、それらの抽象化をエンティティ中心のオンライン ドキュメントと追加のみの履歴イベント用に設計されたMongoDBスキーマにマッピングします。
概念マッピング
フィーストの概念 | Feast でのロール | MongoDB表現 |
|---|---|---|
エンティティ | 説明する機能を持つドメインオブジェクト(例:ドライバー、ユーザー)。 | シリアル化されたエンティティキーにエンコードされます。オンライン ストアでは |
結合キー | データフレーム内のエンティティ行を識別するために使用される列。 |
|
直列化された EntityKey | 結合キー名と値の決定的なバイナリ エンコーディング。 | オンライン: |
機能 | 特定の点における型指定された測定値。 |
|
FeatureView | 機能をエンティティ、データソース、 TTL にバインドします。組織の単位。 | オフライン: 各履歴ドキュメントの |
DataSource | 履歴機能が存在する場所へのメタデータ ポインター。 |
|
OFFlineStore | 履歴機能と PIT 結合用の読み取り/書込みインターフェース。 |
|
OnlineStore | エンティティごとの最新機能値の低レイテンシ ストア。 | ネストされた |
TTL | FeatureView レベルの リフレッシュウィンドウ。 | 履歴機能を計算するときにオフライン クエリとPython後フィルタリングで強制されます。は、インデックスの |
FeatureService | モデルの機能参照の名前付きリスト。 | MongoDB の直接表現ではありません。 Feast は、オンライン ストアから読み取る |
レジストリ | エンティティ、機能ビュー、サービスのメタデータ ストア。 | 変更されていない。 MongoDB統合は Feast レジストリを置き換えるものではありません。 |
RetrievalJob | 機能テーブルを返す延期された実行ラッパー。 | MongoDBオフライン ストアの場合、 はMQL集計をカプセル化し、カーソルから Arrow への変換を基盤とした Arrow のエクスポートを公開します。 |
マテリアライズド | 最新のオフライン機能をオンライン ストアに提供する予定です。 |
|
MongoDBオフライン ストア
データモデル
MongoDBオフライン ストアは、すべての機能ビューに対する追加のみの履歴機能行を保存する単一の共有コレクション(デフォルトでは feature_history)を使用します。
各ドキュメントは、特定のイベントタイムスタンプにおける 1 つの FeatureView の 1 つのエンティティの 1 つの観察を表します。
{ "entity_id": "Binary(...)", "feature_view": "driver_stats", "event_timestamp": "ISODate(2024-01-15T12:00:00Z)", "created_at": "ISODate(2024-01-15T12:01:00Z)", "features": { "conv_rate": 0.72, "acc_rate": 0.91, "avg_daily_trips": 14 } }
主なプロパティ:
追加のみ:
created_at履歴データは不変として扱われます。修正は、インプレース アップデートではなく、新しい行として書き込まれます。時系列に適しています:
event_timestampは機能値が観察された時間を表します。created_atは、複数の観察が同じイベントタイムスタンプを共有する場合に、タイブレークとして使用されます。FeatureView による機能グループ化:
feature_viewは行が属する FeatureView を識別するため、単一のコレクションで複数の FV をホストできます。
単一の複合インデックスで、すべての主要クエリ パターンがサポートされます。
(entity_id ASC, feature_view ASC, event_timestamp DESC, created_at DESC)
このインデックス、エンティティや機能集計に対する効率的な範囲スキャンが可能になると同時に、(entity_id, feature_view) ごとの最新の観察が最初に認識されるようになります。
クエリ パターン | インデックスの動作 |
|---|---|
|
|
| ソートは一切操作されません。つまり、インデックス順がソート順と一致します。 |
| カーソルは最初に |
|
|
このインデックスがない場合、4 つのクエリ パターンはすべて COLLSCAN に降格します。インデックスは _ensure_indexes 経由で最初の使用時に遅延して作成され、プロセスレベルの _indexes_ensured セットの接続文字列ごとにキャッシュされるため、プロセス有効期間ごとに 1 回だけ作成されます。
主要オフライン操作
MongoDBオフライン ストアは、標準の Feast オフライン ストア インターフェイスを実装します。
offline_write_batch- 構成されたMongoDBSourceメタデータを使用して、connection_string、database、collectionを決定し、基礎のMongoDBコレクションに機能データのpyarrow.Tableを書き込みます。get_historical_features- エンティティとイベントタイムスタンプのentity_dfと FeatureView のセットを指定すると、 は、各行に特定の時点の正しい機能値が含まれる拡大テーブルを返します。それぞれの(entity_id, event_timestamp)ペアについて、event_timestamp <= entity_event_timestampを持つ最新の機能値TTL 内の と が選択されます。pull_latest_from_table_or_query- オンライン ストアをシードするために Feast のマテリアライズドエンジンによって使用される 時間ウィンドウの最新の機能値を含むエンティティごとに 1 行を返します。pull_all_from_table_or_query- 同じfeature_historyスキーマとインデックスに基づき、エクスポートまたは検査のために指定された日付範囲内のすべての行をデータソースから取得します。persist(RetrievalJob.persist経由)- 履歴機能クエリの結果を、SavedDatasetStorage経由で別のコレクションまたは外部シンクに書き込みます。feature_historyとは異なります。
呼び出しパス:
FeatureStore.write_to_offline_store(feature_view_name, df) → provider.ingest_df_to_offline_store(feature_view, arrow_table) → OfflineStore.offline_write_batch(config, feature_view, table, progress)
insert_many(ordered=False)10追加のみのセマンティクス:,000 ドキュメントバッチに を使用してドキュメントが挿入されます。書き込み時にアップサートや重複除外は行われません。同じ(entity_id, feature_view, event_timestamp) ペアの複数のドキュメントが許可され、保持されます。
競合の解決は読み取り時間まで延期されます。
pull_latest_from_table_or_queryは、選出されたevent_timestampグループ内で最も高いcreated_atを持つドキュメントを選択します。get_historical_features(スコアリング パス)は$sort … created_at DESCを使用するため、タイムスタンプが同点になった場合には$group $firstも最高のcreated_atを選択します。
したがって、後の created_at を使用して書き込まれた修正は、削除または更新操作なしで選出されます。
pull_latest_from_table_or_query は、 [start_date, end_date]ウィンドウ内の最新の機能値を含むエンティティごとに 1 行を返します。 entity_df が提供されていません。
パイプライン ステージ:
$match { feature_view, event_timestamp: {$gte, $lte} } → $sort { entity_id, event_timestamp DESC, created_at DESC } → $group $first by entity_id → $project { entity_id, event_timestamp, features.* }
複合インデックスは$match + $sort を効率的に処理します。 $group $first は、残りをマテリアライズドせずにエンティティごとに 1 つのドキュメントを選択します。
集計実装
推奨されるオフライン実装は、MongoDBOfflineStore という名前の集計ベースのMongoDBオフライン ストアです。
主な特徴:
すべての FeatureView で共有される単一の
feature_historyコレクションを使用します(feature_viewで区別されます)。すべてのクエリで複合インデックス
(entity_id, feature_view, event_timestamp, created_at)に依存し、コレクションのフル スキャンを回避します。「スコアリング」ワークロード(エンティティごとに 1 行)にはサーバーサイドの
$group $firstを使用し、エンティティ ID が繰り返されるワークロードを「訓練」するにはpd.merge_asofを使用し、正確性とパフォーマンスのバランスをとります。チャンク化によるメモリ使用量の限界が設定されているため、 RAM を枯渇することなく、大きな
entity_df値を処理できます。
ベンチマークは、この実装が代替のMongoDBオフライン アプローチと比較して、スループットとメモリ効率の最高の組み合わせを提供することを示しています。
get_historical_features は、コア Feast APIです。 entity_df(エンティティ キー列の N 行 + event_timestamps)および K FeatureView オブジェクトを受け入れ、同じ N 行と M の機能列を含む DataFrame を返します。値は各行の event_timestamp(ポイント-時間枠の正確性)。
表記:
N → エンティティ数
M → 機能数
P → 観察数
F → 機能ビュー数
K → 1 回の
get_historical_features呼び出しでリクエストされた機能ビューの数
スコアリング パス
スコアリング パスは、entity_df に繰り返されるエンティティ ID がない場合にアクティブ化されます。これは、各行が異なるタイムポイントで個別のエンティティの機能を要求する一般的な推論シナリオです。
検出:
scoring_path = ( entity_df[all_entity_id_cols].drop_duplicates().shape[0] == len(entity_df) )
スコアリング時に、サーバー側の $group $first ステージが追加されます。
$match → $sort → $group $first → $project
$group は (entity_id, feature_view) でグループ化し、最も高い (event_timestamp, created_at) を持つドキュメントを選択します。つまり、先行する $sort の後のインデックス順 の最初のドキュメントです。 MongoDB は、機能ビューごとに各エンティティの他の P-1 ドキュメントを具体化することはありません。カーソルは、1 つのドキュメントを選択した後、単純に次のグループ キーに進みます。エンティティあたりのコストは O(P) ではなく、O(ログ P)(インデックス検索)です。
$match は event_timestamp: {$lte: max_ts} を使用します。max_ts は現在のチャンク内の最大エンティティリクエストタイムスタンプです。これは控えめな近似値(「オーバーシューティング」)です。サーバーは一部のエンティティについて、若干将来にドキュメントを返す場合があります。以下のPython後フィルターは、無効な行を null で除外することで、これを修正します。
# Merge on entity_id (left = entity_df rows, right = server results) merged = result[["_fv_entity_id", event_timestamp_col]].merge( fv_join, on="_fv_entity_id", how="left" ) # Null out rows where the server doc is in the future or outside TTL future_mask = merged["_fv_ts"] > merged[event_timestamp_col] if fv.ttl: ttl_mask = merged["_fv_ts"] < ( merged[event_timestamp_col] - fv.ttl ) bad_mask = future_mask | ttl_mask else: bad_mask = future_mask for feat in features: vals = merged[feat].copy() vals[bad_mask | merged["_fv_ts"].isna()] = None result[col] = vals.values
これは、単一の pd.merge 呼び出しとそれに続くベクトル化されたブール値インデックスの作成です。O(N) は Panas Cコードで、P と M とは独立して動作します。
訓練パス
entity_df に繰り返しのエンティティ ID がある場合(エンティティごとに多数のタイムスタンプ スナップショットを持つ訓練データセット)、$group ステージは省略されます。この集計では、各エンティティのタイムスタンプウィンドウ内のすべてのドキュメントが返されます。Pythonはpd.merge_asof を使用して各行の event_timestamp またはその前に最新のドキュメントを見つけます。
$match → (no $group)
result = pd.merge_asof( result.sort_values(event_timestamp_col), fv_df_subset.sort_values("_fv_ts"), left_on=event_timestamp_col, right_on="_fv_ts", by="_fv_entity_id", direction="backward", )
メモリ使用量を制御するチャンクの 2 つのレベル
レベル | 定数 | 目的 |
|---|---|---|
外 | 50,000 行 |
|
インナー | 10,000 エンティティ ID | 集計呼び出しごとに |
entity_df が CHUNK_SIZE より大きい場合、外側のループは複数の _run_single 呼び出しを実行し、結果を連結します。
if len(working_df) <= CHUNK_SIZE: result_df = _run_single(working_df, coll) else: chunks = [ _run_single(chunk, coll) for chunk in _chunk_dataframe(working_df, CHUNK_SIZE) ] result_df = pd.concat(chunks, ignore_index=True)
したがって、合計 N に関係なく、Python 側のピークメモリは O(CHUNK_SIZE x M x K) になります。
MongoDB features サブドキュメントは、pd.json_normalize ではなく pd.apply を使用して個々の列に展開されます。これにより、json_normalize はフラット化または失敗する複雑な型(マップと構造体の決定、配列のリスト)が保持されます。プロジェクションされた列名が FeatureView の定義と一致するように、逆フィールドマッピングも適用されます。
if "features" in fv_df.columns: for feat in features: src_col = reverse_fm.get(feat, feat) fv_df[feat] = fv_df["features"].apply( lambda d, _s=src_col: ( d.get(_s) if isinstance(d, dict) else None ) ) fv_df = fv_df.drop(columns=["features"])
オフライン ストアの機能
機能 | サポートされていますか? | ノート |
|---|---|---|
| はい | インデックス付き集計と Ppanda のマージを使用して |
| はい |
|
| はい |
|
| はい | 構成された |
| はい |
|
データレイクや倉庫に直接エクスポートするような追加のオプションは、特定の RetrievalJob実装によって異なります。また、オフライン ストアでは、Feast の標準パターンに従うことが予想されます。
MongoDBオンラインストア
データモデル
MongoDBオンライン ストアでは、シリアル化されたエンティティ キーをキーとするすべての FeatureView に対して単一のコレクションが使用されます。
_id:serialized_entity_key(entity_key)。エンティティ名と値をソートしてバイトにエンコードする Feast の安定エンコーディング関数によって生成されます。features: 各 FeatureView が独自の機能名前空間を維持するネストされたサブドキュメント。event_timestamps: その FeatureView の最新値がいつ書き込まれたかを示す FeatureView ごとのタイムスタンプ。created_timestampまたはupdated_at: TTL インデックスと診断に便利なブックキーピング フィールド。
例(簡略化):
{ "_id": "b\"<serialized_entity_key>\"", "features": { "driver_stats": { "rating": 4.91, "trips_last_7d": 132 }, "pricing": { "surge_multiplier": 1.2 } }, "event_timestamps": { "driver_stats": "ISODate(2026-01-01T12:00:00Z)", "pricing": "ISODate(2026-01-21T12:00:00Z)" }, "created_timestamp": "ISODate(2026-01-21T12:00:00Z)" }
設計理由:
単一のコレクションは各エンティティの状態を 1 つのドキュメントで保持するため、キーベースの検索に関する Feast の予想と一致し、FeatureView ごとのコレクション間での状態の断片化を回避します。
シリアル化されたエンティティキーを
_idとして使用すると、Feast の決定的エンコーディングが再利用され、コレクション間で重複するプライマリキーが回避され、エンティティごとに単一のキー検索が取得されます。
オフライン ストア(feature_view 弁別子フィールドを持つ単一の feature_historyコレクションを使用するもの)と同様に、オンライン ストアもすべての FeatureView に対して単一のコレクションを使用します。
Atlas Online Store は基本的にエンティティキー向けであり、機能ビュー向けではありません。高レベルの FeatureStore API は1 つの FeatureView を使用して online_read と online_write_batch を呼び出しますが、Feast の基礎となるストレージモデルは、エンティティ キーごとに 1 つの論理行を対象に設計されています。その行には、時間の経過とともに複数の FeatureView からの機能が蓄積される可能性があります。
1 つのコレクションを使用すると、エンティティごとに統合されたドキュメントを維持し、コレクション間でエンティティキーを重複させることなく、関連するサブドキュメント(例: features.<feature_view_name>)のみを不可分的に更新できます。
単一コレクションのデザインは最初から Feast の標準であり(最初は Reds 用に設計されています)、MongoDB の強度に適しています。メリットには、次のようなものがあります。
書込み保証 (write concern) の削減
簡素化されたインデックス管理(プライマリ
_idインデックスは1 つだけ)複数の FeatureView が同じエンティティを共有する場合、コレクション間の調整は行われません
Feast のキーベースのフェッチモデルによる一貫した検索モデルによる一貫した検索モデル
Feature-View ごとのコレクション設計では、エンティティの状態がフラグメント化され、機能が構成されている場合は追加の調整や複数のコレクション クエリが必要になり、Feast のアクセス パターンのパフォーマンス上の利点なしに運用オーバーヘッドが増加します。
直列化されたエンティティキーとして _id: Feast は、予測可能なバイトシーケンス(バイトを生成する struct.pack で型指定)を確保するために、連結する前にエンティティ名と値を明示的にソートする安定したエンコーディング関数である serialize_entity_key を提供します。つまり、_id として直接使用できます。
注意
serialize_entity_key は安定した _id を提供しますが、その出力は均等に分散されていないため、シャーディングには理想的ではありません。配置でオンライン ストアのコレクション をシャーディング必要がある場合は、ハッシュされたシャードキーまたは追加のフィールドを検討してください。
主要オンライン操作
MongoDBオンライン ストアには、Feast の標準オンライン ストアAPIが実装されています。
online_write_batch- マテリアライズ中に、Feast は各エンティティの最新の機能値をMongoDBドキュメントに書込みます。各バッチするアップサートでは、関連するネストされたfeatures.<feature_view>サブドキュメントと、event_timestamps内の対応するエントリのみが更新され、エンティティ ドキュメントはアトミックで一貫性が保たれます。online_readとget_online_features- オンラインで提供すると、オフラインと同じ直列化ロジックを使用してエンティティキーを_id値に解決し、キー検索を実行します。各検索は、ネストされたfeatures構造を活用して、エンティティに要求された機能を 1 回のラウンド トリップですべて返します。TTL と最新性 - 機能 TTL は FeatureView で構成され、主にオフラインの PIT 結合で使用されます。オンライン TTL は、
updated_atまたは同様のタイムスタンプのインデックスを使用して実装できます。これは、オンライン ストアが最新の状態を保持している間は、オフライン ストアは追加専用であるという Feast の概念と一致します。
構成
オフライン ストアの構成
オフライン ストアは MongoDBOfflineStoreConfig を使用して構成されています。
class MongoDBOfflineStoreConfig(FeastConfigBaseModel): type: str = "...MongoDBOfflineStore" connection_string: str = "mongodb://localhost:27017" database: str = "feast" collection: str = "feature_history"
例feature_store.yaml :
offline_store: type: feast.infra.offline_stores.contrib.mongodb_offline_store.mongodb.MongoDBOfflineStore connection_string: "mongodb+srv://user:pass@cluster.mongodb.net" database: feast collection: feature_history
MongoDBSource は、対応するDataSource です。そのname feature_viewフィールドは、すべてのドキュメントに保存される 弁別子になります。完全な構成オプションについては、Feast ドキュメントのMongoDBデータソース参照を参照してください。
source = MongoDBSource( name="driver_stats", timestamp_field="event_timestamp", created_timestamp_column="created_at", )
次のステップ
Feast クイックスタート に従ってローカル機能ストアを設定し、このページの構成例を使用してMongoDB をオンラインおよびオフライン ストアとしてスワップします。
構成オプション、非同期サポート、完全な機能マトリックスについては、Feast ドキュメントのMongoDB Online Store参照を確認してください。
オフライン ストアの構成とサポートされている機能については、 「 MongoDB OFFline Store 」の参照を確認してください。
オプションとスキーマの詳細については、 MongoDBデータソースに関する参照を確認してください。
MongoDBSource