【问题标题】:Query multiple collections at once with MongoDB using aggregate, match and lookup使用聚合、匹配和查找在 MongoDB 中一次查询多个集合
【发布时间】:2019-03-17 16:30:00
【问题描述】:

我在这里遇到了一些问题,因为在通过多个集合进行查询时,我试图绕开 $lookup 的使用,如下所述:https://stackoverflow.com/a/43653679 和这里:https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/

获得了 3 个收藏:

用户 - 在哪里可以使用“电子邮件”字段

配置 - 在哪里可以使用“vpn”字段

固件 - 在哪里可以使用“version”字段


我的目的是统计符合这些条件的用户数量:

  • 电子邮件 =! @yahoo.com,@gmail.com,@hotmail.com
  • vpn 已开启
  • 版本为 123

您能帮我了解一下我的查询应该是什么样子吗? 非常感谢!

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    我现在不在我的工作站,但我相信这就是您要找的。

    您在上面的问题中提到的链接完美地解释了您想要做什么只是似乎您很难在脑海中解决它(我们都这样做..我知道做很多)

    为了将来的参考,这通常会被视为/标记为您引用的问题的重复,但我看到您是新来的,出于某种原因我心情很好。希望这会有所帮助,如果不告诉我!欢迎加入社区!

    db.Users.aggregate([
        { $match: { email: "test@somemail.com" } }, #Get the users that match the email constraints
        {
            $lookup: { #Get the config document associated to the/each user
                from: "Config",
                localField: "config_id",
                foreignField: "_id",
                as: "config"
            }
        },
        {
            $match: { #limit the configs with VPNs that are "ON"
                "config.vpn": "ON"
            }
        },
        {
            $lookup: { #Get the Firmware associated to the/each User
                from: "Firmware",
                localField: "firmware_id",
                foreignField: "_id",
                as: "firmware"
            }
        },
        {   
            $match: { #Limit to only firmwares that are version 123
                   "firmware.version": 123
            }
        },
        $count: { "_id" }
    ])
    

    这个(理论上)会返回一个像这样的文档:

     { "_id": <the number of Users with specified "email", "vpn", "version"> }
    

    【讨论】:

    • 嗨贾巴。非常感谢您的友好回答!事实证明,我不能真正使用这种方法,因为我实际上有 2 个数据库:设备数据库 > 配置集合 > vpn 字段 + 设备数据库 > 固件集合 > 版本字段和用户数据库 > 用户集合 > 电子邮件字段 绑定这些集合的内容一起是一个名为tenantId的字段,存在于所有这些字段中。我不确定 config_id 是什么意思(通常是 _id),因为根据docs.mongodb.com/manual/reference/operator/aggregation/lookup 的示例,我会说我应该使用 config_id,而不是 vpn 等等。
    • 您是在尝试在 mongo shell 中正确执行此操作,还是在 js 或 python 等中编写此代码?另外,我只使用了那些自定义的_id 来表明我指的是customers_id 字段。这将等同于您的tenant_id
    • 使用 mongo shell。我想我做错了,对吧?
    • 好吧,我建议将您的数据库一起移动并通过集合将它们分开,这样您就可以使用我上面所做的逻辑。如果不是,则无法在一个命令中完成所有这些操作
    【解决方案2】:

    我最终使用了一个 js 脚本。这是大部分内容:

    let vpnConfigs = dbRefs.Devices.VpnConfig.find({"vpn": "on"}).toArray() 
    let firmwareConfigs = dbRefs.Devices.FirmwareConfig.find({"version": "1.2.1"}).toArray()
    
    let tenants = dbRefs.Users.Tenant.find().toArray()
    
    let filteredDevices = vpnConfigs.filter(   vpnConfigModel => firmwareConfigs.some(firmwareConfigModel => vpnConfigModel.parent.id
    === firmwareConfigModel.parent.id) )
    
    let totalDevicesNumber = 0
    
    let filteredTenants = tenants.filter(
        tenant => {
            if(/@psft\.com|@gmail\.com|@yahoo\.com|@maildrop.cc/.test(tenant.ownerEmail)){
                return false;
            }
    
            return filteredDevices.some(configModel => configModel.tenantId === tenant._id)
            let devicesCount = filteredDevices.filter(configModel => configModel.tenantId === tenant._id).length
            totalDevicesNumber += devicesCount
            return devicesCount > 0
        } )
    
    filteredTenants.map(
        tenant => print(tenant.ownerEmail) )
    
    
    print(`Found ${filteredTenants.length} tenant(s)`) 
    print(`Found ${totalDevicesNumber} device(s)`)
    

    【讨论】:

    • 如果这回答了您的问题,请将其标记为答案。这有助于其他人更轻松地找到答案,而您自己也可以获得积分。
    • 完成。谢谢你,先生! :)
    猜你喜欢
    • 1970-01-01
    • 2020-06-29
    • 2011-09-24
    • 2020-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-16
    相关资源
    最近更新 更多