簡體   English   中英

如何在子文檔數組上使用 $lookup

[英]How to use $lookup on array of subdocuments

我有這些架構:

const chatbots = new Schema({
  name: String,
  campaigns: [{
    name: String,
    channels: [{
      _id: String,
      name: String,
      budget: Number
    }]
  }]
});

const chatbotusers = new Schema({
  name: String,
  campaign_channel: String
})

我需要獲得一個活動列表,其中對於每個頻道,我有 ChatbotUsers 的總數。 像這樣的東西:

[
  {
    "name": "Campaign #1",
    "channels": {
      "_id": "eyRyZ1gD0",
      "name": "Channel #1",
      "users": 10
    }
  },
  {
    "name": "Campaign #1",
    "channels": {
      "_id": "tsKH7WxE",
      "name": "Channel #2",
      "users": 4
    }
  }
]

有任何想法嗎?

我得到的最遠的是這樣的:

{
  $lookup: {
    from: "chatbotusers",
    localField: "channels._id",
    foreignField: "campaign_channel",
    as: "users",
  }
},
{
  $project: {
    name: "$name",
    channels: {
      $map: {
        input: "$channels",
        as: "channel",
        in: {
          _id: "$$channel._id",
          name: "$$channel.name",
          users: { $size: "$users" },
        }
      }
    }
  }
}

但它匯總了營銷活動的用戶,而不是頻道。

(對不起,如果問題標題不合適,我什至不知道如何正確提問)

你可以試試這個查詢:

db.chatbots.aggregate([
    {
        $lookup: {
            from: "chatbotusers",
            localField: "campaigns.channels._id",
            foreignField: "campaign_channel",
            as: "users"
        }
    },
    {
        $addFields: {
            campaigns: {
                $map: {
                    input: "$campaigns",
                    as: "eachCampaign",
                    in: {
                        $mergeObjects: ['$$eachCampaign', {
                            channels:
                            {
                                $reduce: {
                                    input: "$$eachCampaign.channels",
                                    initialValue: [],
                                    in: {
                                        $concatArrays: [
                                            "$$value",
                                            [
                                                {
                                                    $mergeObjects: [
                                                        "$$this",
                                                        {
                                                            user: {
                                                                $size: {
                                                                    $filter: {
                                                                        input: "$users",
                                                                        as: "e",
                                                                        cond: {
                                                                            $eq: [
                                                                                "$$e.campaign_channel",
                                                                                "$$this._id"
                                                                            ]
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    ]
                                                }
                                            ]
                                        ]
                                    }
                                }
                            }
                        }]
                    }
                }
            }
        }
    },
    {
        $project: {
            users: 0
        }
    }
])

注意:可以有多種方法來做到這一點,但通過這種方式,我們正在處理來自聊天機器人集合的相同數量的文檔,而不是通過執行$unwind來分解文檔,這在您擁有龐大的數據集時可能會有所幫助。

測試: MongoDB-Playground

上面的查詢應該可以為您提供所需的信息,但無論如何,如果它很慢或者您想增強它,那么在這里:

{
    user: {
        $size: {
            $filter: {
                input: "$users", as: "e",
                    cond: {
                    $eq: [
                        "$$e.campaign_channel",
                        "$$this._id"
                    ]
                }
            }
        }
    }
}

我們在每個廣告系列中的每個頻道遍歷users數組的地方,因此而不是每次都在查找后迭代 - 您可以使用reduce迭代用戶一次以獲取每個唯一的Campaign_channel 的計數,將此數據替換為users數組,即您可以直接獲取用戶數的方式。 通常,上述查詢的主要目的是保留原始文檔結構,使用較少的階段。

或者,您可以使用此查詢,它不會保留原始文檔結構(輸出中的文檔數量也可能超過您收集的文檔數量),但可以執行您需要的操作:

db.chatbots.aggregate([
  {
    $unwind: "$campaigns"
  },
  {
    $unwind: "$campaigns.channels"
  },
  {
    $lookup: {
      from: "chatbotusers",
      localField: "campaigns.channels._id",
      foreignField: "campaign_channel",
      as: "users"
    }
  },
  {
    $addFields: {
      "channels": "$campaigns.channels",
      campaigns: "$campaigns.name"
    }
  },
  {
    $addFields: {
      "channels.users": {
        $size: "$users"
      }
    }
  },
  {
    $project: {
      users: 0
    }
  }
])

測試: MongoDB-Playground

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM