MongoDB 8.0以降、等価一致式で nullと比較しても、 undefined値と一致しません。
たとえば、これらのドキュメントとクエリについて考えてみます。
// create the people collection db.people.insertMany( [ { _id: 1, name: null }, { _id: 2, name: undefined }, { _id: 3, name: [ "Gabriel", undefined ] }, { _id: 4, names: [ "Alice", "Charu" ] } ] )
db.people.find( { name: null } )
MongoDB 8.0より前では、上記のクエリは次のドキュメントと一致します。
nameフィールドはnull(_id: 1)nameフィールドはundefinedであるか、 またはundefined配列要素を含みています(_id: 2と_id: 3)nameフィールドは存在しません(_id: 4)
MongoDB 8.0 以降では、上記のクエリでは、nameフィールドが undefined であるか、 または undefined 配列要素が含まれているドキュメントは一致しません。 クエリは、次の条件を満たすドキュメントのみに一致します。
nameフィールドはnullであるか、 またはnull配列要素を含みています(_id: 1)nameフィールドは存在しません(_id: 4)
このクエリ動作の変更は、次の操作にも影響します。
この動作の変更を考慮するには、次のことを実行します。
注意
undefined は、非推奨のBSON type です。 MongoDB Shell とドライバーの最近のバージョンでは、挿入とアップデートを実行するときに、undefined 値を null に自動的に変換します。 このページのガイダンスは、古いドライバー バージョンまたはレガシーのmongo シェルからの undefined 値を持つ配置に適用されます。
未定義フィールドの排除
ドキュメント内に undefined 値を持つフィールドを保持する必要がない場合は、それらのフィールドを削除できます。 MongoDB の柔軟なデータモデルにより、コレクションのドキュメントフィールドは一貫している必要はなく、ドキュメントのサブセットから特定のフィールドを削除できます。
ドキュメントから未定義のフィールドをどのように削除するかは、削除するフィールド名を知っているかどうかによって異なります。 フィールド名がわかっている場合は、インデックスを使用できるため、操作のパフォーマンスが向上します。
次のいずれかを参照してください。
既知の名前のフィールドを削除
削除対象の undefined 値を含むフィールドの名前がわかっている場合は、次の例を使用します。 この例では、 peopleコレクションを更新して次の要素を削除します。
値がスカラー値
undefinedの場合のnameフィールド。undefinednameフィールドの配列要素。
db.people.updateMany( { name: { $type: "undefined" } }, [ { $set: { "name": { $cond: { // When "name" is an array, convert { name: [ "Alice", undefined ] } // to { name: [ "Alice" ] } if: { $eq: [ { $type: "$name" }, "array" ] }, then: { $filter: { input: "$name", cond: { $not: { $eq: [ { $type: "$$this" }, "undefined" ] } } }, }, // When "name" is scalar undefined, remove it else: "$$REMOVE" } } } } ] )
操作の実行後、peopleコレクションには次のドキュメントが含まれます。
[ { _id: 1, name: null }, { _id: 2 }, { _id: 3, name: [ "Gabriel" ] } { _id: 4, names: [ "Alice", "Charu" ] } ]
不明な名前のフィールドの排除
undefined 値が含まれるフィールドがわからない場合は、次の例を使用して、undefined の最上位フィールドをすべて削除します。
注意
アップデートのフィールド名を指定しない場合、クエリはインデックスを使用できないため、操作はパフォーマンスが良くありません。 大規模なコレクションで次の例を実行すると、クエリは遅くなり、リソースを消費する可能性があります。
次の例では、値が undefined である peopleコレクションから最上位のドキュメントフィールドを排除しています。
db.people.updateMany( { }, [ { $replaceWith: { // Detect undefined top-level fields under the root and remove them $arrayToObject: { $filter: { input: { $objectToArray: "$$ROOT" }, cond: { $not: { $eq: [ { $type: "$$this.v" }, "undefined" ] } } } } } } ] )
操作の実行後、peopleコレクションには次のドキュメントが含まれます。
[ { _id: 1, name: null }, { _id: 2 }, { _id: 3, name: [ "Gabriel", undefined ] } { _id: 4, names: [ "Alice", "Charu" ] } ]
注意
上記のアプローチでは、最上位のフィールドのみが変更されます。 _id: 3 を含むドキュメントには引き続き undefined 値が含まれます。これは、値が配列に表示されるためです。
未定義の値を null に更新
undefined データ値を nullデータ型に更新できます。 このアプローチを使用して、ドキュメントフィールドを保持しながら、非推奨の undefinedデータ型からデータを移行します。
未定義のフィールドをどのように更新するかは、更新対象のフィールド名がわかっているかどうかによって異なります。 フィールド名がわかっている場合は、インデックスを使用できるため、操作のパフォーマンスが向上します。
次のいずれかを参照してください。
既知の名前でフィールドを更新
null に設定する undefined 値を含むフィールドの名前がわかっている場合は、次の例を使用します。 この例では、 peopleコレクションを更新して、次の値を null に設定します。
値がスカラー値
undefinedの場合のnameフィールド。undefinednameフィールドに表示される配列要素。
db.people.updateMany( { name: { $type: "undefined" } }, [ { $set: { "name": { $cond: { // When "name" is an array, convert { name: [ "Alice", undefined ] } // to { name: [ "Alice", null ] } if: { $eq: [ { $type: "$name" }, "array" ] }, then: { $map: { input: "$name", in: { $cond: { if: { $eq: [ { $type: "$$this" }, "undefined" ] }, then: null, else: "$$this" } } }, }, // When "name" is the scalar undefined, convert to null else: null } } } } ] )
操作の実行後、peopleコレクションには次のドキュメントが含まれます。
[ { _id: 1, name: null }, { _id: 2, name: null }, { _id: 3, name: [ "Gabriel", null ] } { _id: 4, names: [ "Alice", "Charu" ] } ]
不明な名前を持つフィールドの更新
undefined 値が含まれるフィールドがわからない場合は、次の例を使用して、すべての undefined の最上位フィールドを null に設定します。
注意
アップデートのフィールド名を指定しない場合、クエリはインデックスを使用できないため、操作はパフォーマンスが良くありません。 大規模なコレクションで次の例を実行すると、クエリは遅くなり、リソースを消費する可能性があります。
次の例では、 peopleコレクションを更新して、undefined の最上位ドキュメントフィールドを null に設定します。
db.people.updateMany( { }, [ { $replaceWith: { // Detect undefined top-level fields under the root and replace them with null $arrayToObject: { $map: { input: { $objectToArray: "$$ROOT" }, in: { $cond: { if: { $eq: [ { $type: "$$this.v" }, "undefined" ] }, then: { k: "$$this.k", v: null }, else: "$$this" } } } } } } ] )
操作の実行後、peopleコレクションには次のドキュメントが含まれます。
[ { _id: 1, name: null }, { _id: 2, name: null }, { _id: 3, name: [ "Gabriel", undefined ] } { _id: 4, names: [ "Alice", "Charu" ] } ]
注意
上記のアプローチでは、最上位のフィールドのみが変更されます。 _id: 3 を含むドキュメントには引き続き undefined 値が含まれます。これは、値が配列に表示されるためです。
未定義の値に一致するようにクエリを更新する
データ型を null から undefined に移行できない場合は、未定義の値と一致するようにクエリを書き換えることができます。 このアプローチを使用しても、データには非推奨の undefined BSON型が引き続き含まれます。
null のクエリが未定義の値と一致するようにするには、undefined 型に明示的に一致するクエリ述語を追加します。 例、次のクエリは、name が undefined、null、または欠落しているドキュメントに一致します。
db.people.find( { $or: [ { name: null }, { name: { $type: "undefined" } } ] } )
このクエリでは、 peopleコレクション内のすべてのドキュメントが返されます。
[ { _id: 1, name: null }, { _id: 2, name: undefined }, { _id: 3, name: [ "Gabriel", undefined ], { _id: 4, names: [ "Alice", "Charu" ] } ]