Агрегация Mongo – использование переменных, созданных в $project

Можно ли использовать переменные, определенные на этапе $project, на этом же этапе? Например, у меня есть этот конвейер агрегации:

    pipeline = [{   
        '$match': {}
    },
    {
        '$group': {
            '_id': '$_id',
            'n': {'$first': 'n'}
    },
    {
        '$project': {
            'name': 1,
            'n': 1,
            'revenue': {'$multiply': ['$n', 2]},
            'cost': {'$multiply': ['$revenue', 0.25]}
        }
    }]

Я хотел бы использовать переменную $revenue (которую я определил в $project) на той же фазе $project для вычисления значения стоимости, но это не работает.

Есть ли способ сделать это легко и эффективно? Я думал сделать несколько проекций, но мне нужно было бы проецировать много переменных (~ 25 переменных) каждый раз, когда мне нужно вычислить одну дополнительную переменную, и у меня есть куча переменных для вычисления, которые зависят друг от друга (~ 5 переменных), и мой код, вероятно, будет выглядеть плохо, так как будет много проецирования одних и тех же переменных. Как мне это сделать?


person Marc    schedule 17.12.2013    source источник


Ответы (2)


Нет, но вы можете вложить операторы проекции в качестве обходного пути:

pipeline = [{   
    '$match': {}
},
{
    '$group': {
        '_id': '$_id',
        'n': {'$first': 'n'}
},
{
    '$project': {
        'name': 1,
        'n': 1,
        'revenue': {'$multiply': ['$n', 2]},
        'cost': {'$multiply': [{'$multiply': ['$n', 2]}, 0.25]}
    }
}]

Который в этом случае вы могли бы упростить до:

pipeline = [{   
    '$match': {}
},
{
    '$group': {
        '_id': '$_id',
        'n': {'$first': 'n'}
},
{
    '$project': {
        'name': 1,
        'n': 1,
        'revenue': {'$multiply': ['$n', 2]},
        'cost': {'$multiply': ['$n', 2, 0.25]}
    }
}]
person JohnnyHK    schedule 17.12.2013
comment
Правильно, но каждая переменная представляет собой несколько строк кода, и у меня было бы много вложенных переменных внутри каждого вычисления. Мне нужно было бы вкладывать вычисление переменной каждый раз, когда мне нужно ее использовать, что не имело бы смысла, если бы у меня было 5 переменных, зависящих друг от друга, где я должен использовать каждую переменную около 5 раз в каждом вычислении. Но спасибо за предложение! - person Marc; 17.12.2013

Только что приземлился здесь, ища ту же проблему. Мое текущее решение - добавить больше этапов $project и всегда использовать все остальные поля. Для вашего примера это будет выглядеть так:

pipeline = [{   
    '$match': {}
},
{
    '$group': {
        '_id': '$_id',
        'n': {'$first': 'n'}
},
{
    '$project': {
        'name': 1,
        'n': 1,
        'revenue': {'$multiply': ['$n', 2]}
    }
},
{
    '$project': {
        'name': 1,
        'n': 1,
        'revenue': 1,
        'cost': {'$multiply': ['$revenue', 0.25]}
    }
}]

Я пока не нашел лучшего решения, если вы хотите сохранить все предыдущие вычисляемые поля, без повторного использования выражений несколько раз.

person Maik Laschober    schedule 09.06.2021