MongooseはネストされたフィールドのObjectIdタイプを自動的に変換できません
0. Intro
先日開発の楽屋で奇妙な現象が発見された.明らかに、mongoseアーキテクチャでは同じObjectId
タイプのフィールドであり、一部のフィールドはstring
であり、他のフィールドはObjectId
であり、DBに格納されている.コードで原因が全く分からず、グーグル検索でも原因が見つからないので、一日中原因を探しています.正確な原因はまだ見つかっていないが、簡単な問題の状況と解決方法はここに書くことができるはずだ.
1.問題の状況
問題の状況は以下のように要約する.
mongoseアーキテクチャでnested fieldとして指定されているフィールドがObjectIdフィールドである場合、mongoseはhex stringを自動的にObjectIdに変換しません.
mongoseは基本的にアーキテクチャ上ObjectId
として指定され、MongoDBがIDとして認識されるhex stringを入力すると、自動的にObjectId
タイプに変換されてデータベースに保存される(リファレンス).ただし、ObjectId
タイプのフィールドがネストされたフィールドであれば、ObjectId
タイプのデータを入力すれば問題ありませんが、hex stringを入力すると自動変換は動作しません.{
foo: {
bar: "572bb8222b288919b68abf5b"
},
foobar: ObjectId("572bb8222b288919b68abf5b")
}
"572bb8222b288919b68abf5b"
hex stringは確かに加わっているが、foobar
ではObjectId
に変換され、foo.bar
ではそのままraw stringとして記憶されている.このように異なるストレージ方式では、クライアントから取得する際に異なるタイプで読み取りが行われるため、追跡が困難な問題が発生しやすい.
2.問題の再現
これがプロジェクト内の設定のためであることを理解するために、ローカルでMongoDBとMongooseサーバを簡単に設定しました.import mongoose from 'mongoose'
const hexStr = '572bb8222b288919b68abf5b'
const { connect, disconnect, Schema, model } = mongoose
async function main() {
await connect('mongodb://127.0.0.1:27017/test')
const testSchema = new Schema({
foo: {
type: {
bar: {
type: Schema.Types.ObjectId,
required: true
}
},
required: true
},
foobar: {
type: Schema.Types.ObjectId,
required: true
},
})
const Test = model('Test', testSchema)
// 똑같은 hexStr 문자열을 넣어줌
await Test.create({
foo: {
bar: hexStr
},
foobar: hexStr
})
await disconnect()
}
main().catch((err) => console.log(err))
前述したように、ネストされたフィールドfoo.bar
および通常のフィールドfoobar
は、いずれもObjectId
のタイプとして指定される.上記のコードが実行されると、データベースは、foo.bar
およびfoobar
をフィールドとするドキュメントを生成し、終了する.
3.結果
Mongooseオプションではnested fieldに関する設定が設定されていないため、半分の人が事前にこれが現象だと予想していたので、同じ現象が再び発生することはもちろん知っています.しかし、このように再現された結果、NestedFieldも同様にObjectId
種類でデータに入った.{
"_id": "ObjectId("624ee7997c9b7ed5a9366234")",
"foo": {
"bar": "ObjectId("572bb8222b288919b68abf5b")",
"_id": "ObjectId("624ee7997c9b7ed5a9366235")"
},
"foobar": "ObjectId("572bb8222b288919b68abf5b")",
"__v": 0
}
もしこれが選択肢の違いでなければ、何が違いますか?考えてみると、インストールされている猫王バージョンの違いかもしれないと思います.上のテストコードのmongoseバージョンは6.2.10
で、プロジェクト内のmongoseバージョンは5.9.3
です.そこでmongoseバージョンを下げてコードを再実行しようとしました.{
"_id" : ObjectId("624ee91a03b8168ef8edbc34"),
"foo" : {
"bar" : "572bb8222b288919b68abf5b"
},
"foobar" : ObjectId("572bb8222b288919b68abf5b"),
"__v" : 0
}
あ….その結果、猫王バージョンによって動作が異なります.[email protected]
万の話題かどうかはわかりませんが、設定に関する話題ではないようで、アップロードプロジェクトのmongoseバージョンまでは、これはもう抱えて歩かなければならない問題になっていました.
4.便宜の策
何らかの理由でmongoseを更新できない場合や、攻守が大きい場合は、hex stringを個別にパッケージする関数を定義できます.import mongoose from 'mongoose'
function convertToObjectId(id: string | mongoose.Types.ObjectId) {
if (typeof id === 'string') {
return mongoose.Types.ObjectId(id)
}
return id
}
// 새 document 생성 시 ObjectId를 wrapping
await Test.create({
foo: {
bar: convertToObjectId(hexStr)
},
foobar: convertToObjectId(hexStr)
})
Reference
この問題について(MongooseはネストされたフィールドのObjectIdタイプを自動的に変換できません), 我々は、より多くの情報をここで見つけました
https://velog.io/@peacesong/mongoose-nested-object-id
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
問題の状況は以下のように要約する.
mongoseアーキテクチャでnested fieldとして指定されているフィールドがObjectIdフィールドである場合、mongoseはhex stringを自動的にObjectIdに変換しません.
mongoseは基本的にアーキテクチャ上
ObjectId
として指定され、MongoDBがIDとして認識されるhex stringを入力すると、自動的にObjectId
タイプに変換されてデータベースに保存される(リファレンス).ただし、ObjectId
タイプのフィールドがネストされたフィールドであれば、ObjectId
タイプのデータを入力すれば問題ありませんが、hex stringを入力すると自動変換は動作しません.{
foo: {
bar: "572bb8222b288919b68abf5b"
},
foobar: ObjectId("572bb8222b288919b68abf5b")
}
"572bb8222b288919b68abf5b"
hex stringは確かに加わっているが、foobar
ではObjectId
に変換され、foo.bar
ではそのままraw stringとして記憶されている.このように異なるストレージ方式では、クライアントから取得する際に異なるタイプで読み取りが行われるため、追跡が困難な問題が発生しやすい.2.問題の再現
これがプロジェクト内の設定のためであることを理解するために、ローカルでMongoDBとMongooseサーバを簡単に設定しました.import mongoose from 'mongoose'
const hexStr = '572bb8222b288919b68abf5b'
const { connect, disconnect, Schema, model } = mongoose
async function main() {
await connect('mongodb://127.0.0.1:27017/test')
const testSchema = new Schema({
foo: {
type: {
bar: {
type: Schema.Types.ObjectId,
required: true
}
},
required: true
},
foobar: {
type: Schema.Types.ObjectId,
required: true
},
})
const Test = model('Test', testSchema)
// 똑같은 hexStr 문자열을 넣어줌
await Test.create({
foo: {
bar: hexStr
},
foobar: hexStr
})
await disconnect()
}
main().catch((err) => console.log(err))
前述したように、ネストされたフィールドfoo.bar
および通常のフィールドfoobar
は、いずれもObjectId
のタイプとして指定される.上記のコードが実行されると、データベースは、foo.bar
およびfoobar
をフィールドとするドキュメントを生成し、終了する.
3.結果
Mongooseオプションではnested fieldに関する設定が設定されていないため、半分の人が事前にこれが現象だと予想していたので、同じ現象が再び発生することはもちろん知っています.しかし、このように再現された結果、NestedFieldも同様にObjectId
種類でデータに入った.{
"_id": "ObjectId("624ee7997c9b7ed5a9366234")",
"foo": {
"bar": "ObjectId("572bb8222b288919b68abf5b")",
"_id": "ObjectId("624ee7997c9b7ed5a9366235")"
},
"foobar": "ObjectId("572bb8222b288919b68abf5b")",
"__v": 0
}
もしこれが選択肢の違いでなければ、何が違いますか?考えてみると、インストールされている猫王バージョンの違いかもしれないと思います.上のテストコードのmongoseバージョンは6.2.10
で、プロジェクト内のmongoseバージョンは5.9.3
です.そこでmongoseバージョンを下げてコードを再実行しようとしました.{
"_id" : ObjectId("624ee91a03b8168ef8edbc34"),
"foo" : {
"bar" : "572bb8222b288919b68abf5b"
},
"foobar" : ObjectId("572bb8222b288919b68abf5b"),
"__v" : 0
}
あ….その結果、猫王バージョンによって動作が異なります.[email protected]
万の話題かどうかはわかりませんが、設定に関する話題ではないようで、アップロードプロジェクトのmongoseバージョンまでは、これはもう抱えて歩かなければならない問題になっていました.
4.便宜の策
何らかの理由でmongoseを更新できない場合や、攻守が大きい場合は、hex stringを個別にパッケージする関数を定義できます.import mongoose from 'mongoose'
function convertToObjectId(id: string | mongoose.Types.ObjectId) {
if (typeof id === 'string') {
return mongoose.Types.ObjectId(id)
}
return id
}
// 새 document 생성 시 ObjectId를 wrapping
await Test.create({
foo: {
bar: convertToObjectId(hexStr)
},
foobar: convertToObjectId(hexStr)
})
Reference
この問題について(MongooseはネストされたフィールドのObjectIdタイプを自動的に変換できません), 我々は、より多くの情報をここで見つけました
https://velog.io/@peacesong/mongoose-nested-object-id
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
import mongoose from 'mongoose'
const hexStr = '572bb8222b288919b68abf5b'
const { connect, disconnect, Schema, model } = mongoose
async function main() {
await connect('mongodb://127.0.0.1:27017/test')
const testSchema = new Schema({
foo: {
type: {
bar: {
type: Schema.Types.ObjectId,
required: true
}
},
required: true
},
foobar: {
type: Schema.Types.ObjectId,
required: true
},
})
const Test = model('Test', testSchema)
// 똑같은 hexStr 문자열을 넣어줌
await Test.create({
foo: {
bar: hexStr
},
foobar: hexStr
})
await disconnect()
}
main().catch((err) => console.log(err))
Mongooseオプションではnested fieldに関する設定が設定されていないため、半分の人が事前にこれが現象だと予想していたので、同じ現象が再び発生することはもちろん知っています.しかし、このように再現された結果、NestedFieldも同様に
ObjectId
種類でデータに入った.{
"_id": "ObjectId("624ee7997c9b7ed5a9366234")",
"foo": {
"bar": "ObjectId("572bb8222b288919b68abf5b")",
"_id": "ObjectId("624ee7997c9b7ed5a9366235")"
},
"foobar": "ObjectId("572bb8222b288919b68abf5b")",
"__v": 0
}
もしこれが選択肢の違いでなければ、何が違いますか?考えてみると、インストールされている猫王バージョンの違いかもしれないと思います.上のテストコードのmongoseバージョンは6.2.10
で、プロジェクト内のmongoseバージョンは5.9.3
です.そこでmongoseバージョンを下げてコードを再実行しようとしました.{
"_id" : ObjectId("624ee91a03b8168ef8edbc34"),
"foo" : {
"bar" : "572bb8222b288919b68abf5b"
},
"foobar" : ObjectId("572bb8222b288919b68abf5b"),
"__v" : 0
}
あ….その結果、猫王バージョンによって動作が異なります.[email protected]
万の話題かどうかはわかりませんが、設定に関する話題ではないようで、アップロードプロジェクトのmongoseバージョンまでは、これはもう抱えて歩かなければならない問題になっていました.4.便宜の策
何らかの理由でmongoseを更新できない場合や、攻守が大きい場合は、hex stringを個別にパッケージする関数を定義できます.import mongoose from 'mongoose'
function convertToObjectId(id: string | mongoose.Types.ObjectId) {
if (typeof id === 'string') {
return mongoose.Types.ObjectId(id)
}
return id
}
// 새 document 생성 시 ObjectId를 wrapping
await Test.create({
foo: {
bar: convertToObjectId(hexStr)
},
foobar: convertToObjectId(hexStr)
})
Reference
この問題について(MongooseはネストされたフィールドのObjectIdタイプを自動的に変換できません), 我々は、より多くの情報をここで見つけました
https://velog.io/@peacesong/mongoose-nested-object-id
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
import mongoose from 'mongoose'
function convertToObjectId(id: string | mongoose.Types.ObjectId) {
if (typeof id === 'string') {
return mongoose.Types.ObjectId(id)
}
return id
}
// 새 document 생성 시 ObjectId를 wrapping
await Test.create({
foo: {
bar: convertToObjectId(hexStr)
},
foobar: convertToObjectId(hexStr)
})
Reference
この問題について(MongooseはネストされたフィールドのObjectIdタイプを自動的に変換できません), 我々は、より多くの情報をここで見つけました https://velog.io/@peacesong/mongoose-nested-object-idテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol