MongoDB Aggregation Framework $ map в оригинальном списке документов - PullRequest
0 голосов
/ 23 октября 2019

У меня есть эти документы:

[
  { "ruleId": "1", "ruleProperty": 111, "composeOfRules": [ "2", "3" ]},
  { "ruleId": "2", "ruleProperty": 222, "composeOfRules": [ "3" ]},
  { "ruleId": "3", "ruleProperty": 333, "composeOfRules": []},
]

Я хочу дополнить каждое правило в composeOfRules его ruleProperty:

[
  { "ruleId": "1", "ruleProperty": 111, "composeOfRules": [ { "ruleId": "2", "ruleProperty": 222 }, { "ruleId": "3", "ruleProperty": 333 } ]},
  { "ruleId": "2", "ruleProperty": 222, "composeOfRules": [ { "ruleId": "3", "ruleProperty": 333 } ]},
  { "ruleId": "3", "ruleProperty": 333, "composeOfRules": []},
]

Я знаю, что могу использовать $project с $map в массиве, но я не знаю, как использовать исходную коллекцию в input поле $map:

$map: {
    input: ??

Заранее спасибо!

1 Ответ

1 голос
/ 24 октября 2019

Единственный способ, которым вы можете ссылаться на коллекцию в полном объеме, как вы, кажется, хотите, - это использовать lookup , и даже тогда это будет только началом. Вам нужно сделать гораздо больше, чем просто поиск или карту, чтобы получить результат, который вы ищете.

Попробуйте это:

db.NameOfYourCollection.aggregate([{
    $unwind: {
        path: "$composeOfRules",
        preserveNullAndEmptyArrays: true
    }
}, {
    $lookup: {
        "from": "NameOfYourCollection",
        "localField": "composeOfRules",
        "foreignField": "ruleId",
        "as": "rule"
    }
}, {
    $unwind: {
        path: "$rule",
        preserveNullAndEmptyArrays: true
    }
}, {
    $group: {
        "_id": {
            "ruleId": "$ruleId",
            "ruleProperty": "$ruleProperty"
        },
        "composeOfRules": {
            "$push": "$rule"
        }
    }
}, {
    $project: {
        "_id": 0,
        "ruleId": "$_id.ruleId",
        "ruleProperty": "$_id.ruleProperty",
        "composeOfRules": {
            "$map": {
                "input": "$composeOfRules",
                "as": "rule",
                "in": {
                    "ruleId": "$$rule.ruleId",
                    "ruleProperty": "$$rule.ruleProperty"
                }
            }
        }
    }
}])

Этот запрос раскручивает поле массива composeOfRulesна более управляемые части, сохраняя запись с пустым массивом. Поиск получит все детали правил по разбитому composeOfRules. Результаты поиска будут более удобными для следующей операции. Группа соберет все вместе и объединит более подробные правила в массив. И окончательный проект очистит результаты, чтобы они выглядели так, как вы хотите.

ОБНОВЛЕНИЕ

Если окажется, что документы, представленные в вопросе, являются окончательным результатом агрегации. Вы можете добавить следующее, чтобы получить желаемые результаты. (Еще не проверено)

...previous operations of the aggregation...
{
    "$project": {
        "_id": 0,
        "ruleId": 1,
        "ruleProperty": 1,
        "composeOfRules": 1,
        "rootField": "$$ROOT"
    }
}, {
    "$group": {
        "_id": null,
        "rootArray": {
            "$push": "rootField"
        },
        "originalFields": {
            "$push": {
                "ruleId": "$ruleId",
                "ruleProperty": "$ruleProperty",
                "composeOfRules": "$composeOfRules"
            }
        }
    }
}, {
    "$unwind": "$originalFields"
}, {
    "$project": {
        "_id": 0,
        "ruleId": "$originalFields.ruleId",
        "ruleProperty": "$originalFields.ruleProperty",
        "composeOfRules": {
            "$map": {
                "input": { "$filter": {
                    "input": "$rootArray",
                    "as": "rootObj",
                    "cond": { "$in": [ "$$rootObj.ruleId", "$originalFields.composeOfRules" ] }
                } },
                "as": "rule",
                "in": { "ruleId": "$$rule.ruleId", "ruleProperty": "$$rule.ruleProperty" }
            }
        }
    }
}
...