🗂
【MongoDB】lookupで結合した先のコレクションの結果をsortしたりlimitをかけてみる
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