ObjectIDってなんだ?
MongoDBの_idにデフォルトでセットされる値ですが、文字列(string)ではなく、ObjectIdクラスのインスタンスのようです。
なので、以下に挙げますが、_id同士を単純に比較しても常にfalseになってしまいますし、_idの文字列の値(313263686172313263686172
)と_idを比較しても、文字列とインスタンスなので、こちらも常にfalseとなってしまいます。
_idの値の文字列をクエリの検索条件としたい
findById()
は引数にstringを受け付けるので、そのまま渡せます。
const result = await UserModel.findById('313263686172313263686172')
集計関数であるaggregate()
の中で検索条件としたい場合は、$convert
というaggregation演算子を使ってObjectIdインスタンスに変換してあげる必要があります。
以下は、_idの配列のフィールドの中に、特定の_idが含まれているかを検索する例で、他に$in
という演算子を使っています。
// 配列のフィールド(memberIds)にuserIdが含まれているTeamを検索
const userId = '313263686172313263686172'
const result = await TeamModel.aggregate([
$match: {
$expr: {
$in: [
$convert: {
input: userId,
to: 'objectId'
},
'memberIds'
]
}
}
])
※ObjectIDへの$convert
は以下でもいいらしい。
{
$toObjectId: userId
}
_id同士の比較
ObjectIdインスタンスの.equals()
というメソッドを使用します。
const user = await UserModel.findById('313263686172313263686172')
const team = await TeamModel.findOne({})
// x これだとインスタンス同士の比較なので常にfalseになってしまう
const isTeamMember = team.memberIds.some((memberId) => memberId === user._id)
// o equals()というメソッドを使う
const isTeamMember = team.memberIds.some((memberId) => memberId.equals(user._id))
そのほか
ObjectIds in Mongoose - Mastering JS
Mongooseは24個の16進文字列や任意の12個の文字列(12byteの文字列)はObjectIDインスタンスに変換するようです。
また、ObjectIDの値(の文字列)は12byteの文字列で構成され、最初の4byteはタイムスタンプで、_id.getTimestamp()
というメソッドでタイムスタンプの値を取得できるらしい。。。
間違いがありましたら、ぜひご指摘をお願いいたします🙏