web-dev-qa-db-ja.com

条件付きのMongodb集計ルックアップ

すべてのarticle_categoryを格納するarticle_idというコレクションがあり、そのようなデータ形式のcategory_idを持つカテゴリに属します。

コレクション1:article_category

{
  "article_id": 2015110920343902,
  "all_category_id": [5,8,10]
}

それから、私の投稿をすべて保存するarticleという他のコレクションがあります

コレクション2:記事

{
  "title": "This is example rows in article collection"
  "article_id": 2015110920343902,
},
{
  "title": "Something change"
  "article_id": 2015110920343903,
},
{
  "title": "This is another rows",
  "article_id": 2015110920343904,
}

次に、category_id8と等しくなければならないときに、titleregexを見つけるMongoDBクエリを実行します。ここに私のクエリがありますが、動作しません。

db.article.aggregate(
{
  $match: 
  {
    title: 
    {
       $regex: /example/
    }
  }
},
{
    $lookup:
       {
         from: "article_category",
         pipeline: [
            { $match: { category_id: 8 } }
         ],
         as: "article_category"
       }
  }
)

上記のクエリは、regexで一致するがcategory_idで一致しないレコードのみを表示します。

何か案が?

8
vietnguyen09

まず第一に、それはall_category_idではなくcategory_idです。第二に、記事をリンクしないでください-すべてのドキュメントはまったく同じarticle_category配列を持ちます。最後に、カテゴリに一致しない記事を除外することをお勧めします。条件付きパイプラインは次のようになります。

db.article.aggregate([
  { $match: {
      title: { $regex: /example/ }
  } },
  { $lookup: {
    from: "article_category",
    let: {
      article_id: "$article_id"
    },
    pipeline: [
      { $match: {
          $expr: { $and: [
              { $in: [ 8, "$all_category_id" ] },
              { $eq: [ "$article_id", "$$article_id" ] }
          ] }
      } }
    ],
    as: "article_category"
  } },
  { $match: {
    $expr: { $gt: [
      { $size: "$article_category"},
      0
    ] }
  } }
] )

更新:

article_idと一致しない場合、$lookupは、すべての記事と同じarticle_category配列になります。

article_categoryコレクションに別のドキュメントがあるとします。

{
  "article_id": 0,
  "all_category_id": [5,8,10]
}

{ $eq: [ "$article_id", "$$article_id" ] }がパイプラインにある場合、結果のarticle_category

[ 
  { 
    "article_id" : 2015110920343902, 
    "all_category_id" : [ 5, 8, 10 ] 
  } 
]

なし:

[ 
  { 
    "article_id" : 2015110920343902, 
    "all_category_id" : [ 5, 8, 10 ] 
  },
  {
    "article_id": 0,
    "all_category_id": [ 5, 8, 10 ]
  }
]

後者が必要な場合は、リクエストを見つけるのがはるかに簡単になります:

db.article.find({ title: { $regex: /example/ } })

そして

db.article_category.find({ all_category_id: 8 })
15
Alex Blex

ここではいくつか間違っています。 category_idall_category_idでなければなりません。 $lookupで結合条件を使用し、$matchoptimized ルックアップの$lookup$unwindステージの外に移動します。

$projectを除外して使用して、検索されたフィールドを最終応答から削除します。 {$project:{article_category:0}}のようなもの

試して

db.article.aggregate([
  {"$match":{"title":{"$regex":/example/}}},
  {"$lookup":{
    "from":"article_category",
    "localField":"article_id",
    "foreignField":"article_id",
    "as":"article_category"
  }},
  {"$unwind":"$article_category"},
  {"$match":{"article_category.all_category_id":8}}
])

非相関サブクエリの場合

db.article.aggregate([
  {"$match":{"title":{"$regex":/example/}}},
  {"$lookup":{
    "from":"article_category",
    "pipeline":[{"$match":{"all_category_id":8}}],
    "as":"categories"
  }},
  {"$match":{"categories":{"$ne":[]}}}
])
2
user2683814