定義
$fillバージョン 5.3 で追加。
ドキュメント内の
nullと欠落しているフィールド値を入力します。欠落しているデータ ポイントを入力するには、
$fillを使用します。周囲の値に基づくシーケンス内。
固定値の場合。
構文
$fillステージの構文は次のとおりです。
{ $fill: { partitionBy: <expression>, partitionByFields: [ <field 1>, <field 2>, ... , <field n> ], sortBy: { <sort field 1>: <sort order>, <sort field 2>: <sort order>, ..., <sort field n>: <sort order> }, output: { <field 1>: { value: <expression> }, <field 2>: { method: <string> }, ... } } }
$fillステージは次のフィールドを持つドキュメントを取得します。
フィールド | 必要性 | 説明 |
|---|---|---|
任意 | ドキュメントをグループ化する式を指定します。 partitionBy と partitionByFields を省略すると、 partitionBy と partitionByField は相互に排他的です。 | |
任意 | ドキュメントをグループ化するための複合キーとしてフィールドの配列を指定します。 partitionBy と partitionByFields を省略すると、 partitionBy と partitionByField は相互に排他的です。 | |
メソッドが少なくとも 1 つのフィールド..<field> で指定されている場合は必須です。 それ以外は任意です。 | 各パーティション内のドキュメントをソートするフィールドを指定します。 | |
必須 | ||
必須 | ターゲット フィールドに欠落値を入力する方法を示すオブジェクトを指定します。 オブジェクト名は |
行動と限界
partitionByFields 制限事項
$fillは、 partitionByFields配列内のいずれかのフィールド名がある場合にエラーを返します。
非 string 値として評価されます。
$から始まります。
linear 動作
The linear 埋め込みメソッドは、シーケンス内の周囲の null 以外の値に基づき、線形補間 を使用して null と欠落フィールドを埋めます。
フィールドが
nullまたは欠落しているドキュメントごとに、linearFillはsortBy順序に従って、周囲のnull以外の値間の欠落値範囲に比例してそれらのフィールドを埋めます。 欠落しているフィールドの値を決定するために、linearFillは以下を使用します。周囲の
nullの値との差。周囲の値の間に入力する
nullフィールドの数。
linearメソッドでは、 sortByの順序に従って、それらの値が先行してnull以外の値に続く場合、複数の連続するnull値を入力できます。例
これらのドキュメントがコレクションに含まれている場合:
{ index: 0, value: 0 }, { index: 1, value: null }, { index: 2, value: null }, { index: 3, value: null }, { index: 4, value: 10 } linear入力メソッドを使用してnull値を入力すると、ドキュメントは次のようになります。{ index: 0, value: 0 }, { index: 1, value: 2.5 }, { index: 2, value: 5 }, { index: 3, value: 7.5 }, { index: 4, value: 10 } nullnullの値が先行せず、その後に続く値はnullのままになります。linearfill メソッドを使用するには、 sortByフィールドも使用してデータを並べ替える必要があります。
linear入力メソッドを使用する完全な例については、「線形補間で欠落しているフィールド値を入力する 」を参照してください。
locf 動作
locf は、転送された最後の結果を表します。
入力されているフィールドに
nullと null 以外の値の両方が含まれている場合、locfはnullと欠落値を、 sortBy順序に従ってフィールドの最後に確認された null 以外の値に設定します。フィールドに
nullまたは欠落値のみが含まれている場合、locfはそのパーティションのフィールド値をnullに設定します。null並べ替え順序 で null 以外の値の前に表示される欠落しているフィールド値はnullのままです。
locffill メソッドを使用するには、 sortByフィールドも使用してデータを並べ替える必要があります。
locf入力メソッドを使用する完全な例については、「 最後に確認された値に基づいて、欠落しているフィールド値を入力する 」を参照してください。
$fillと集計演算子の比較
ドキュメント内でnullと欠落しているフィールド値を入力するには、次のコマンドを使用します。
$fillステージ。$fillステージを使用する場合、出力で指定するフィールドはソース データと同じフィールドになります。$linearFillと$locf集計演算子$linearFillまたは$locfの場合、ソース データとして使用されるフィールドとは異なるフィールドに値を設定できます。
例
このセクションの例では、 $fillを使用して欠落値を入力する方法を示します。
欠落しているフィールド値を定数値で入力
ある金物店では、毎日の売上を要約するドキュメントを含むdailySalesコレクションを管理しています。 鍵店では次のタイプの鍵を販売しています。
bootssandalssneakers
次の dailySales コレクションを作成します。
db.dailySales.insertMany( [ { "date": ISODate("2022-02-02"), "bootsSold": 10, "sandalsSold": 20, "sneakersSold": 12 }, { "date": ISODate("2022-02-03"), "bootsSold": 7, "sneakersSold": 18 }, { "date": ISODate("2022-02-04"), "sneakersSold": 5 } ] )
dailySalesコレクション内のすべてのドキュメントに各ドライバーが含まれているわけではありません。 在庫のあり、
次の例では、 $fillを使用して、毎日の販売に欠落しているキー タイプの販売数量を0に設定します。
db.dailySales.aggregate( [ { $fill: { output: { "bootsSold": { value: 0 }, "sandalsSold": { value: 0 }, "sneakersSold": { value: 0 } } } } ] )
上記のパイプラインでは、
出力例:
[ { _id: ObjectId("6202df9f394d47411658b51e"), date: ISODate("2022-02-02T00:00:00.000Z"), bootsSold: 10, sandalsSold: 20, sneakersSold: 12 }, { _id: ObjectId("6202df9f394d47411658b51f"), date: ISODate("2022-02-03T00:00:00.000Z"), bootsSold: 7, sneakersSold: 18, sandalsSold: 0 }, { _id: ObjectId("6202df9f394d47411658b520"), date: ISODate("2022-02-04T00:00:00.000Z"), sneakersSold: 5, bootsSold: 0, sandalsSold: 0 } ]
線形補間で欠落しているフィールド値を入力
次のドキュメントを含む stockコレクションを作成します。このドキュメントは 1 時間ごとの単一会社の株価を追跡します。
db.stock.insertMany( [ { time: ISODate("2021-03-08T09:00:00.000Z"), price: 500 }, { time: ISODate("2021-03-08T10:00:00.000Z"), }, { time: ISODate("2021-03-08T11:00:00.000Z"), price: 515 }, { time: ISODate("2021-03-08T12:00:00.000Z") }, { time: ISODate("2021-03-08T13:00:00.000Z") }, { time: ISODate("2021-03-08T14:00:00.000Z"), price: 485 } ] )
コレクション内の一部のドキュメントでpriceフィールドが欠落しています。
線形補間 を使用して欠落しているprice $fill値を入力するには、linear と 入力メソッドを使用します。
db.stock.aggregate( [ { $fill: { sortBy: { time: 1 }, output: { "price": { method: "linear" } } } } ] )
上記のパイプラインでは、
$fillは、欠落しているフィールドの値を入力します。sortBy: { time: 1 }は、ドキュメントをtimeフィールドで最初から最新の順に昇順でソートします。出力は以下を指定します。
price欠落値を入力するフィールドとして。{ method: "linear" }入力メソッドとして。linearを満たす- メソッドは、シーケンス内の周囲の
price値に基づき線形補間を使用することで、欠落しているprice値を埋めます。
出力例:
[ { _id: ObjectId("620ad41c394d47411658b5e9"), time: ISODate("2021-03-08T09:00:00.000Z"), price: 500 }, { _id: ObjectId("620ad41c394d47411658b5ea"), time: ISODate("2021-03-08T10:00:00.000Z"), price: 507.5 }, { _id: ObjectId("620ad41c394d47411658b5eb"), time: ISODate("2021-03-08T11:00:00.000Z"), price: 515 }, { _id: ObjectId("620ad41c394d47411658b5ec"), time: ISODate("2021-03-08T12:00:00.000Z"), price: 505 }, { _id: ObjectId("620ad41c394d47411658b5ed"), time: ISODate("2021-03-08T13:00:00.000Z"), price: 495 }, { _id: ObjectId("620ad41c394d47411658b5ee"), time: ISODate("2021-03-08T14:00:00.000Z"), price: 485 } ]
最後に確認された値に基づいて、欠落しているフィールド値を入力する
次のドキュメントを含む restaurantReviewsコレクションを作成します。このコレクションは 1 件のレストランのレビュー スコアを一定の期間保存します。
db.restaurantReviews.insertMany( [ { date: ISODate("2021-03-08"), score: 90 }, { date: ISODate("2021-03-09"), score: 92 }, { date: ISODate("2021-03-10") }, { date: ISODate("2021-03-11") }, { date: ISODate("2021-03-12"), score: 85 }, { date: ISODate("2021-03-13") } ] )
コレクション内の一部のドキュメントでscoreフィールドが欠落しています。
欠落しているscoreフィールドに入力し、データに差がないようにするには、 $fillを使用します。 次の例では、 $fillはlocf埋め込みメソッドを使用して、欠落しているscore値をシーケンス内の前のscoreで埋めます。
db.restaurantReviews.aggregate( [ { $fill: { sortBy: { date: 1 }, output: { "score": { method: "locf" } } } } ] )
上記のパイプラインでは、
$fillは欠落しているscore値を埋めます。sortBy: { date: 1 }は、ドキュメントをdateフィールドで最初から最新の順に昇順でソートします。出力は以下を指定します。
score欠落値を入力するフィールドとして。{ method: "locf" }入力メソッドとして。locfを満たす- メソッドは、欠落している
score値をシーケンス内で最後に確認されたscoreで埋めます。
出力例:
[ { _id: ObjectId("62040bc9394d47411658b553"), date: ISODate("2021-03-08T00:00:00.000Z"), score: 90 }, { _id: ObjectId("62040bc9394d47411658b554"), date: ISODate("2021-03-09T00:00:00.000Z"), score: 92 }, { _id: ObjectId("62040bc9394d47411658b555"), date: ISODate("2021-03-10T00:00:00.000Z"), score: 92 }, { _id: ObjectId("62040bc9394d47411658b556"), date: ISODate("2021-03-11T00:00:00.000Z"), score: 92 }, { _id: ObjectId("62040bc9394d47411658b557"), date: ISODate("2021-03-12T00:00:00.000Z"), score: 85 }, { _id: ObjectId("62040bc9394d47411658b558"), date: ISODate("2021-03-13T00:00:00.000Z"), score: 85 } ]
個別のパーティションのデータを入力
レストランのレビューを含む前の例を検討してみましょうが、1 つのレストランを追跡するのではなく、 コレクションには複数のレストランのレビューが含まれています。
restaurantReviewsMultipleという名前のコレクションを作成し、そのコレクションに次のドキュメントを入力します。
db.restaurantReviewsMultiple.insertMany( [ { date: ISODate("2021-03-08"), restaurant: "Joe's Pizza", score: 90 }, { date: ISODate("2021-03-08"), restaurant: "Sally's Deli", score: 75 }, { date: ISODate("2021-03-09"), restaurant: "Joe's Pizza", score: 92 }, { date: ISODate("2021-03-09"), restaurant: "Sally's Deli" }, { date: ISODate("2021-03-10"), restaurant: "Joe's Pizza" }, { date: ISODate("2021-03-10"), restaurant: "Sally's Deli", score: 68 }, { date: ISODate("2021-03-11"), restaurant: "Joe's Pizza", score: 93 }, { date: ISODate("2021-03-11"), restaurant: "Sally's Deli" } ] )
コレクション内の一部のドキュメントでscoreフィールドが欠落しています。
欠落しているscoreフィールドに入力し、データに差がないようにするには、 $fillを使用します。 次の例では、 $fillはlocf埋め込みメソッドを使用して、欠落しているscore値をシーケンス内の前のscoreで埋めます。
db.restaurantReviewsMultiple.aggregate( [ { $fill: { sortBy: { date: 1 }, partitionBy: { "restaurant": "$restaurant" }, output: { "score": { method: "locf" } } } } ] )
上記のパイプラインでは、
$fillは欠落しているscore値を埋めます。sortBy: { date: 1 }は、ドキュメントをdateフィールドで最初から最新の順に昇順でソートします。partitionBy: { "restaurant": "$restaurant" }はrestaurantでデータを分割します。Joe's PizzaとSally's Deliの 2 つのレストランがあります。出力は以下を指定します。
score欠落値を入力するフィールドとして。{ method: "locf" }入力メソッドとして。locfを満たす- メソッドは、欠落している
score値をシーケンス内で最後に確認されたscoreで埋めます。
出力例:
[ { _id: ObjectId("620559f4394d47411658b58f"), date: ISODate("2021-03-08T00:00:00.000Z"), restaurant: "Joe's Pizza", score: 90 }, { _id: ObjectId("620559f4394d47411658b591"), date: ISODate("2021-03-09T00:00:00.000Z"), restaurant: "Joe's Pizza", score: 92 }, { _id: ObjectId("620559f4394d47411658b593"), date: ISODate("2021-03-10T00:00:00.000Z"), restaurant: "Joe's Pizza", score: 92 }, { _id: ObjectId("620559f4394d47411658b595"), date: ISODate("2021-03-11T00:00:00.000Z"), restaurant: "Joe's Pizza", score: 93 }, { _id: ObjectId("620559f4394d47411658b590"), date: ISODate("2021-03-08T00:00:00.000Z"), restaurant: "Sally's Deli", score: 75 }, { _id: ObjectId("620559f4394d47411658b592"), date: ISODate("2021-03-09T00:00:00.000Z"), restaurant: "Sally's Deli", score: 75 }, { _id: ObjectId("620559f4394d47411658b594"), date: ISODate("2021-03-10T00:00:00.000Z"), restaurant: "Sally's Deli", score: 68 }, { _id: ObjectId("620559f4394d47411658b596"), date: ISODate("2021-03-11T00:00:00.000Z"), restaurant: "Sally's Deli", score: 68 } ]
を使用してフィールドが入力されたかどうかを示す $fill
欠損値を入力しても、出力には値が$fill演算子によって入力されたかどうか、あるいは値が最初にドキュメントに存在していたかどうかが示されません。 入力値と既存値を区別するには、 $fillの前に$setステージを使用し、値が存在するかどうかに基づいて新しいフィールドを設定します。
例、次のドキュメントを含む restaurantReviewsコレクションを作成します。これはレストランのレビュー スコアを一定期間保存するものです。
db.restaurantReviews.insertMany( [ { date: ISODate("2021-03-08"), score: 90 }, { date: ISODate("2021-03-09"), score: 92 }, { date: ISODate("2021-03-10") }, { date: ISODate("2021-03-11") }, { date: ISODate("2021-03-12"), score: 85 }, { date: ISODate("2021-03-13") } ] )
コレクション内の一部のドキュメントで scoreフィールドが欠落しています。欠落している score 値を入力するには、$fill 演算子を使用します。
次のアクションを実行するためのパイプラインを作成します。
$setを使用して各ドキュメントに新しいフィールドを追加し、$fill演算子が値を入力する前にドキュメントのscoreフィールドが存在するかどうかを示します。この新しいフィールドはvalueExistedと呼ばれます。欠落している
score値に、シーケンス内で最後に確認されたscoreを入力します。 入力メソッドlocfは「last observation carried forward(LOCF)」を表します。
パイプラインは、次のコードのようになります。
db.restaurantReviews.aggregate( [ { $set: { "valueExisted": { "$ifNull": [ { "$toBool": { "$toString": "$score" } }, false ] } } }, { $fill: { sortBy: { date: 1 }, output: { "score": { method: "locf" } } } } ] )
注意
ゼロの値の処理
出力:
[ { _id: ObjectId("63595116b1fac2ee2e957f15"), date: ISODate("2021-03-08T00:00:00.000Z"), score: 90, valueExisted: true }, { _id: ObjectId("63595116b1fac2ee2e957f16"), date: ISODate("2021-03-09T00:00:00.000Z"), score: 92, valueExisted: true }, { _id: ObjectId("63595116b1fac2ee2e957f17"), date: ISODate("2021-03-10T00:00:00.000Z"), valueExisted: false, score: 92 }, { _id: ObjectId("63595116b1fac2ee2e957f18"), date: ISODate("2021-03-11T00:00:00.000Z"), valueExisted: false, score: 92 }, { _id: ObjectId("63595116b1fac2ee2e957f19"), date: ISODate("2021-03-12T00:00:00.000Z"), score: 85, valueExisted: true }, { _id: ObjectId("63595116b1fac2ee2e957f1a"), date: ISODate("2021-03-13T00:00:00.000Z"), valueExisted: false, score: 85 } ]
異なるパーティションでの同一の値の補間
バージョン8.1で変更。
MongoDB 8.1 以降、異なるパーティションに同じ値がある場合、$fill は linear メソッドを使用して補間できます。
同一の日付にレストランのレビュー スコアを保存する次のドキュメントを含む次の restaurantReviewsMultipleコレクションを作成します。
db.restaurantReviewsMultiple.insertMany( [ { date: ISODate("2021-03-08"), restaurant: "Steve's Pizza", score: 90 }, { date: ISODate("2021-03-08"), restaurant: "Sally's Deli", score: 75 } ] )
次の集計例では、"linear" を使用して、異なるパーティション内の同一の日付を補間します。
db.restaurantReviewsMultiple.aggregate( [ { $fill: { sortBy: { date: 1 }, partitionBy: { "restaurant": "$restaurant" }, output: { "score": { method: "linear" } } } } ] )
MongoDB 8.1 以降では、この例では次の出力が返されます。
[ { _id: ObjectId("620559f4394d47411658b590"), date: ISODate("2021-03-08T00:00:00.000Z"), restaurant: "Sally's Deli", score: 75 }, { _id: ObjectId("620559f4394d47411658b58f"), date: ISODate("2021-03-08T00:00:00.000Z"), restaurant: "Steve's Pizza", score: 90 } ]
このページの Node.js の例では、Atlas サンプルデータセットの sample_weatherdata.data コレクションを使用します。無料の MongoDB Atlas クラスターを作成し、サンプルデータセットをロードする方法を学ぶには、MongoDB Node.js ドライバーのドキュメント「使用開始」をご覧ください。
MongoDB Node.jsドライバーを使用して $fill ステージを集計パイプラインに追加するには、パイプラインオブジェクトで $fill 演算子を使用します。
次の例では、null または欠損値を入力するパイプラインを作成します。このパイプラインには、次のステージが含まれています。
$groupステージでは、入力ドキュメントをtsフィールドごとにグループ化し、各グループの平均seaSurfaceTemperature.valueを計算します。$fillステージは、グループ化されたデータを_idseaSurfaceTemperatureフィールドで昇順にソートし、線形補間を使用して null または欠落している 値を埋めます。
const pipeline = [ { $group: { _id: "$ts", seaSurfaceTemperature: { $avg: "$seaSurfaceTemperature.value" }, } }, { $fill: { sortBy: { _id: 1 }, output: { seaSurfaceTemperature: { method: "linear" } } } } ]; const cursor = collection.aggregate(pipeline); return cursor;