LoginSignup
0

More than 5 years have passed since last update.

MongooseのindexOfとincludes

Posted at

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を独自実装をしていて、StringObjectIdを比較できるのに対してincludesは実装しておらず、Array.prototype.includesを使用するからです。

ObjectIDをtoStringしてから比較すればincludesでも比較可能ですが、忘れると意図していない結果になってしまいます。個人的にはあまり好きではないです。

github上にissueは作られていますが、後方互換性の問題でincludesが今後mongooseArrayに実装されるかは不明です。

参考:mongoose/lib/types/array.js

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0