MongooseArrayのindexOfとincludesの挙動の違いについてです。
次のようなユーザー情報があるとします。
const users = [{
"_id" : ObjectId("5acd4da4c271813c48bcd843"),
"friends" : [
ObjectId("5ad4eb200a67063840c158d5"),
ObjectId("5ad4eb200a67063840c158d0")
],
"name" : "Alice"
},
{
"_id" : ObjectId("5ad4eb200a67063840c158d5"),
"friends" : [
],
"name" : "Bob"
},
{
"_id" : ObjectId("5acd4da4c271813c48bcd845"),
"friends" : [
ObjectId("5acd4da4c271813c48bcd843")
],
"name" : "Tom"
},
{
"_id" : ObjectId("5ad4eb200a67063840c158d0"),
"friends" : [
ObjectId("5ad4eb200a67063840c158d5")
],
"name" : "Ann"
}]
ここからfriendsにBob(5ad4eb200a67063840c158d5
)がいるユーザーを抽出したいとします。
indexOfとincludesをそれぞれ使って抽出すると次のようになると思います。これの返す値が異なることが伝えたいことです。
// indexOfを使う場合
users.filter(user => {
user.friends.indexOf('5ad4eb200a67063840c158d5') !== -1
})
/*
[{
"_id" : ObjectId("5acd4da4c271813c48bcd843"),
"friends" : [
ObjectId("5ad4eb200a67063840c158d5"),
ObjectId("5ad4eb200a67063840c158d0")
],
"name" : "Alice"
},{
"_id" : ObjectId("5ad4eb200a67063840c158d0"),
"friends" : [
ObjectId("5ad4eb200a67063840c158d5")
],
"name" : "Ann"
}]
*/
// includesを使う場合
users.filter(user => {
user.friends.includes('5ad4eb200a67063840c158d5')
})
/*
[]
*/
これはmongooseのarrayがindexOf
を独自実装をしていて、String
とObjectId
を比較できるのに対してincludes
は実装しておらず、Array.prototype.includes
を使用するからです。
ObjectIDをtoStringしてから比較すればincludesでも比較可能ですが、忘れると意図していない結果になってしまいます。個人的にはあまり好きではないです。
github上にissueは作られていますが、後方互換性の問題でincludes
が今後mongooseArrayに実装されるかは不明です。