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のススメでした!