LoginSignup
2
2

More than 5 years have passed since last update.

MongoDBでコレクション内の1つのフィールドの値のリストを取得したい

Last updated at Posted at 2018-11-08

Collection.distinct(フィールド, 条件)

次のようなcollectionがあったとします。

> db.users.find()
{ "_id" : ObjectId("5b35deacfdf5eb3c9470f72a"), "name" : "aaa", "age" : 10, "address": {"country": "Japan"}, "histories": [{"country": "UK"}, {"country": "Korea"}] }
{ "_id" : ObjectId("5b3c84da8db0b59d619d12a3"), "name" : "bbb", "age" : 20 , "address": {"country": "US"}, "histories": [{"country": "Canada"}] }
{ "_id" : ObjectId("5b4d8769077d2201603c5e26"), "name" : "ccc", "age" : 30 , "address": {"country": "UK"}, "histories": [{"country": "China"}] }
{ "_id" : ObjectId("5b63b6b20ace659bf75c31c8"), "name" : "ddd", "age" : 40 , "address": {"country": "Japan"}, "histories": [{"country": "Brazil"}] }

_idのリストだけ取りたかったりということ、ありますよね・・・?
今まで私は

> const users = db.users.find().select('_id')
> const ids = users.map(u => u._id)

とかしていました。
これがdistinctという便利な関数のおかげで1行で済みますし、クエリの速度も数倍から数十倍高速です。

> const ids = db.users.distinct('_id')
[
    ObjectId("5b35deacfdf5eb3c9470f72a"),
    ObjectId("5b3c84da8db0b59d619d12a3"),
    ObjectId("5b4d8769077d2201603c5e26"),
    ObjectId("5b63b6b20ace659bf75c31c8")
]

distinctは、第二引数にfindの条件を入れられます。

> db.users.distinct('_id', {age: {$gte: 30}})
[
    ObjectId("5b4d8769077d2201603c5e26"),
    ObjectId("5b63b6b20ace659bf75c31c8")
]

Node.js用MongoDBライブラリのmongooseを使っているならば、次のどちらの書き方でも使えます。
個人的には第二引数にfind条件を渡すのは他のmongooseのメソッドと違うので、1つ目の書き方が好きです。

User.find({age: {$gte: 30}}).distinct('_id')
// or
User.distinct('_id', {age: {$gte: 30}})

// 一応これも使えるっぽいです・・・
User.find().distinct('_id', {age: {$gte: 30}})

また、ネストされているフィールドに対しても使えるので便利です。

> db.users.distinct('address.country')
["Japan", "US", "UK"]
// 配列の中身からも取って来れます
> db.users.distinct('histories.country')
["UK", "Korea", "Canada", "China", "Brazil"]

以上、distinctのススメでした!

2
2
0

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
2
2