🔬
【MongoDB】抽出条件にlookupで結合した先のコレクションを含める
概要
以前に【MongoDB】lookupで結合した先のコレクションの結果をsortしたりlimitをかけてみるの記事で、コレクションの結合機能であるlookup
の機能を紹介しました。
今回はそのlookup
で、結合した先のコレクションを抽出条件に含める実装を紹介します。(Golangで実装しています)
やりたいこと
まず取得したい結果は、以下のような構造を想定します。
type ItemResponse struct {
ID string `json:"_id" bson:"_id"`
Name string `json:"name" bson:"name"`
Detail string `json:"detail" bson:"detail"`
ShopID string `json:"shop_id" bson:"shop_id"`
ShopName string `json:"shop_name" bson:"shop_name"`
}
結合元のコレクションはitem
とし、以下の通りshop_id
を持つものとします。
type Item struct {
ID string `json:"_id" bson:"_id"`
Name string `json:"name" bson:"name"`
Detail string `json:"detail" bson:"detail"`
ShopID string `json:"shop_id" bson:"shop_id"`
}
結合先のコレクションshop
でショップの情報を保持しているものとします。
type Shop struct {
ID string `json:"_id" bson:"_id"`
Name string `json:"name" bson:"name"`
}
今回はキーワード検索を想定し、item
のname
もしくはshops
のname
のいずれかに、マッチしているドキュメントを抽出するものとします。
実装サンプル
方針としてはlookupで結合した後に、一度shopをunwind
し、その後に抽出条件を設定していきます。Select with sub queryの記事も参考になると思います。
sample.go
// 接続処理は省略・・・
col := c.Database(os.Getenv("DB_NAME")).Collection("item")
// lookupでの結合
lookUpStage := bson.D{{Key: "$lookup", Value: bson.D{
{Key: "from", Value: "shop"},
{Key: "localField", Value: "shop_id"},
{Key: "foreignField", Value: "_id"},
{Key: "as", Value: "shop"},
}}}
// shopをunwindする
unwindStage := bson.D{{Key: "$unwind", Value: "$shop"}}
// 取得項目の指定
projectStage := bson.D{{Key: "$project", Value: bson.D{
{Key: "_id", Value: 1},
{Key: "name", Value: 1},
{Key: "detail", Value: 1},
{Key: "shop_id", Value: 1},
{Key: "shop.name", Value: 1},
}}}
// 抽出条件
matchStage := bson.D{{Key: "$match", Value: bson.D{{Key: "$or", Value: bson.A{
bson.M{"name": bson.D{{Key: "$regex", Value: primitive.Regex{Pattern: "検索ワード", Options: "i"}}}},
bson.M{"shop.name": bson.D{{Key: "$regex", Value: primitive.Regex{Pattern: "検索ワード", Options: "i"}}}},
}}}}}
// クエリの実行
pipeLine := mongo.Pipeline{lookupStage, unwindStage, projectStage, matchStage}
cur, err := col.Aggregate(context.Background(), pipeLine)
// 結果のデコード処理は省略・・
Discussion