首页 > 解决方案 > mongoDB组查询不起作用

问题描述

因此,我的路线页面上有以下查询:

const testeEa = atendimentos.aggregate([
            {$group : {_id: "$id_atendente", Idcount:{$sum:1}}},
            {$sort: {_id: 1}},
            { '$group': {
                    '_id': null,
                    'eatest': {
                        '$sum': {
                            '$cond' : [ { '$eq': ['$status', 'EA'] },  1, 0]
                            }
                        },
                    //'eatest': {'$push': "$$ROOT"}
                } }
        ]).exec();

我想要做的是:这个 Idcount 正在计算 id_atendente 重复的次数。我需要这个来检查每个人接听了多少支持电话。

完成此操作后,我需要检查所有具有“EA”状态的支持电话。

我有 351 个处于“EA”状态的电话,我想在支持电话中查看谁处于此状态。

我想我在第二个 $group 上遗漏了一些东西,我只是不知道它是什么。

这个 eatest 应该是视图上使用的键。

顺便说一句,我设法查询了每个 id 的支持电话数量,我需要几乎相同的东西,不同之处在于我只需要具有“EA”状态的那些。

编辑 1

const counts = atendimentos.aggregate([
            { '$group': {
                    '_id': null,
                    'fin': {
                        '$sum': {
                            '$cond': [ { '$eq': [ '$status', 'F' ] }, 1, 0 ]
                        }
                    },
                    'ea': {
                        '$sum': {
                            '$cond': [ { '$eq': [ '$status', 'EA' ] }, 1, 0 ]
                        }
                    }
                } }
        ]).exec()

    //Faz uma consulta no mongo e guarda o resultado
    //na variável monthly
    const monthly = atendimentos.aggregate([
        { '$group': {
                '_id': {
                    'year': { '$year': '$date' },
                    'month': { '$month': '$date' }
                },
                'sum': { '$sum':  1 }
            } },
        {  '$group': {
                '_id': null,
                //Chave usada para renderizar os dados
                'back': { '$push':  '$$ROOT' }
            } },
    ]).exec();

    //Verificar quantas vezes um id_atendente se repete, contar e guardar o numero
    const testeAt = atendimentos.aggregate([
     {$group : {_id: "$id_atendente", Idcount:{$sum:1}}},
        {$sort: {_id: 1}},
        { '$group': {
            '_id': null,
                //Chave usada para renderizar os dados
                'test': {'$push': "$$ROOT"}
            } },
    ]).exec();

    const atendente = atendimentos.aggregate([
        { '$group' : {
                '_id': "$id_atendente",
                'Idcount': { '$sum': 1 }
            } },
        { '$sort': { '_id': 1 } }
    ]).exec();

    const testeEa = atendimentos.aggregate([
        { '$group': {
                '_id': null,
                'eatest': {
                    '$sum': {
                        '$cond' : [ { '$eq': ['$status', 'EA'] },  1, 0]
                    }
                }
            } }
    ]).exec();

Promise.all([counts, monthly, testeAt, testeEa]).then(([counts, monthly, testeAt, testeEa]) => {

请注意 atendente 查询和 testeAt 几乎相同。

我想做的是使用这个 testeEa 变量来存储查询的返回值,这些查询返回每个 id_atendente 的“EA”状态的数量。

如果我使用 try catch 我不能这样做,我猜是因为 testeEa 会在其中,我无法将它传递给我的数组。

顺便说一句,eatest 正在返回正确的值。

编辑结束

编辑 2

我想要的数据示例,这是它用于检查呼叫次数/id 的查询。

{
            "_id": 42,
            "Idcount": 3
        },
        {
            "_id": 43,
            "Idcount": 155
        },
        {
            "_id": 46,
            "Idcount": 69
        },
        {
            "_id": 47,
            "Idcount": 16
        },
        {
            "_id": 48,
            "Idcount": 4
        },
        {
            "_id": 49,
            "Idcount": 21
        },
        {
            "_id": 50,
            "Idcount": 4
        },

这正是我想要的方式,但不同之处在于我只想要那些具有“EA”状态的人。

Idcount 将是具有“EA”状态的 id 出现的次数。

编辑结束 2

提前致谢!

标签: node.jsmongodbmongooseaggregation-framework

解决方案


在聚合框架中执行管道时,MongoDB 将运算符通过管道相互连接。这里的“管道”取了 Linux 的意思:一个算子的输出变成了后面的算子的输入。每个运算符的结果是一个新的文档集合。所以当Mongo执行上述管道时,前两步的结果

{ '$group' : { /* First pipeline step */
    '_id': "$id_atendente", 
    'Idcount': { '$sum': 1 }
} },
{ '$sort': { '_id': 1 } } /* Second pipeline step */

将是具有架构的文档数组(例如):

[
    { _id: 'fuzz', IdCount: 2 },
    { _id: 'foo', IdCount: 9 },
    { _id: 'bar', IdCount: 4 },
    ....
]

现在当它执行第三个管道时

{ '$group': {
    '_id': null,
    'eatest': {
    '$sum': {
        '$cond' : [ { '$eq': ['$status', 'EA'] },  1, 0]
        }
    }
} }

来自先前管道的文档通过管道传输到此管道中,期望文档具有名为 status 的字段,该字段不存在,因此结果将不正确。

您需要并行运行多个聚合管道,这只能在单个查询中实现$facet

使用 MongoDB 3.4.4 及更高版本:

atendimentos.aggregate([
    { '$facet': {
        'atendente': [
            { '$group' : {
                '_id': "$id_atendente", 
                'Idcount': { '$sum': 1 }
            } },
            { '$sort': { '_id': 1 } }
        ],
        'eatest': [
            { '$group': {
                '_id': null,
                'eatest': {
                '$sum': {
                    '$cond' : [ { '$eq': ['$status', 'EA'] },  1, 0]
                    }
                }
            } }
        ]
    } }
]).exec((err, result) => console.log(result));

使用 MongoDB 3.2 及以下版本:

(async () => {
    try {
        const atendente = await atendimentos.aggregate([
            { '$group' : {
                '_id': "$id_atendente", 
                'Idcount': { '$sum': 1 }
            } },
            { '$sort': { '_id': 1 } }
        ]).exec();

        const eatest = await atendimentos.aggregate([
            { '$group': {
                '_id': null,
                'eatest': {
                '$sum': {
                    '$cond' : [ { '$eq': ['$status', 'EA'] },  1, 0]
                    }
                }
            } }
        ]).exec();

        const data = { atendente, eatest };
        console.log(JSON.stringify(data, null, 4));

    } catch (err) {
        console.error(err);
    }
})();

或使用 Promise API

(() => {

    const atendente = atendimentos.aggregate([
        { '$group' : {
            '_id': "$id_atendente", 
            'Idcount': { '$sum': 1 }
        } },
        { '$sort': { '_id': 1 } }
    ]).exec();

    const eatest = atendimentos.aggregate([
        { '$group': {
            '_id': null,
            'eatest': {
            '$sum': {
                '$cond' : [ { '$eq': ['$status', 'EA'] },  1, 0]
                }
            }
        } }
    ]).exec();

    Promise.all([atendente, eatest]).then(([ atendente, eatest ]) => {
        const data = { atendente, eatest };
        console.log(JSON.stringify(data, null, 4));
    }).catch((err) => {
        console.error(err);
    });
})();

推荐阅读