🗂

【MongoDB】lookupで結合した先のコレクションの結果をsortしたりlimitをかけてみる

2021/01/05に公開

lookupについて

MongoDBのバージョン3.2以降では、他のコレクションとの結合をlookupを使用して実現できます。詳細はこちらのドキュメントにまとめられていますが、基本的な仕様としては左外部結合かつ、結合先のデータは配列形式で取得となっています。具体的なデータの取得については、MongoDBでJOINっぽいことをしてみるの記事がイメージがつきやすいと思います。

やりたいこと

では結合先のコレクションから取得した配列に対して、sortをかけたりlimitをかけたりできるのか、というのが今回の記事です。バージョン3.6以降になりますが、lookupではpipelineを使用できるようになっていて、この中に抽出条件などを書くことができます。pipelineの詳細についてはMongoDB で コレクションを結合する 方法で解説されています。

sortやlimitをどのように書くか

MongoDB $lookup with max document by dateの記事にある通り、pipelineの中でsortとlimitを指定します。

実装サンプル

例としてuserコレクションを結合元、結合先をpostコレクションとした場合の、Golangでの実装例を以下に記します。userコレクションの_id列をキーに結合しています。なお、クエリ部分のみを記しますので、接続箇所等の実装はMongoDB.com公式Goドライバを使った基本操作を参照してください。

sample.go
// 接続処理は省略・・・
col := c.Database(os.Getenv("DB_NAME")).Collection("user")
// pipleLineの内容を配列に格納
pipleLineLookup := bson.A{}
// pipeLineに含めるlimit
pipleLineLookup = append(pipleLineLookup, bson.D{{Key: "$limit", Value: limit}})
// pipeLineに含めるsort
pipleLineLookup = append(pipleLineLookup, bson.D{{Key: "$sort", Value:bson.D{{Key: "post_date", Value: -1},
}}})
// 結合用の配列
var eqBsonA bson.A
eqBsonA = append(eqBsonA, "$$user_id")
eqBsonA = append(eqBsonA, "$post_user_id")
pipleLineLookup = append(pipleLineLookup, bson.D{{Key: "$match", Value: bson.D{{Key: "$expr", Value: bson.D{{Key: "$eq", Value: eqBsonA}}}}}})
// lookupの文
lookupStage := bson.D{{Key: "$lookup", Value: bson.D{
	{Key: "from", Value: "post"},
	{Key: "let", Value: bson.D{{Key: "user_id", Value: "$_id"}}},
	{Key: "pipeline", Value: pipleLineLookup},
	{Key: "as", Value: "posts"},
}}}
projectStage := bson.D{{Key: "$project", Value: bson.D{
	{Key: "_id", Value: 1},
	{Key: "name", Value: 1},
	{Key: "posts._id", Value: 1},
	{Key: "posts.contents", Value: 1},
	{Key: "posts.post_date", Value: 1},
}}}
pipeLine := mongo.Pipeline{lookupStage, projectStage}
cur, err := col.Aggregate(context.Background(), pipeLine)
// 結果のデコード処理は省略・・

Discussion