Прогноз сворачивания субдокумента на основе стоимости - PullRequest
0 голосов
/ 08 мая 2018

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

{ 
    "_id" : "xxxxx", 
    "dept_ids" : [
        {
            "dept_id" : "dd7867535", 
            "dept_name" : "d1"
        }, 
        {
            "dept_id" : "dl97087079", 
            "dept_name" : "d2"
        }
    ]
}

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

{ 
    "_id" : "xxxxx", 
    "d1" : "dd7867535",
    "d2" : "dl97087079"
}

У меня проблемы с поиском способа сделать это в рамках агрегации. Любые предложения приветствуются.

Спасибо, Alex

1 Ответ

0 голосов
/ 08 мая 2018

Если у вас есть поддержка MongoDB $replaceRoot и $arrayToObject, вы можете использовать это:

db.collection.aggregate([
  { "$replaceRoot": {
    "newRoot": {
      "$mergeObjects": [
        { "_id": "$_id" },
        { "$arrayToObject": {
          "$map": {
            "input": "$dept_ids",
            "in": { "k": "$$this.dept_name", "v": "$$this.dept_id" }
          }
        }}
      ]
    }
  }}
])

Но вам это даже не нужно, вместо этого просто преобразуйте возвращенные документы:

db.collection.find().map(d =>
  Object.assign(
    { _id: d._id },
    d.dept_ids.reduce((acc,dep) => Object.assign(acc,{ [dep.dept_name]: dep.dept_id }), {})
  )
);

В современных средах ECMASCRIPT, не оболочкой Mongo, а чем-то вроде NodeJS, вы можете немного очистить синтаксис. то есть с драйвером NodeJS:

const mapper = ({ _id, dept_ids }) => ({
  _id, ...dept_ids.reduce((acc, { dept_name: k, dept_id: v }) => ({ ...acc, [k]: v }),{})
});

let results = await db.collection('departments').find().map(mapper).toArray();

Оба дают одинаковый результат:

{ "_id" : "xxxxx", "d1" : "dd7867535", "d2" : "dl97087079" }

Так что вам действительно не нужно обрабатывать вещи через конвейер агрегации, что можно сделать довольно просто из полученных данных на клиенте. Вы не «сокращаете» никакие данные, что на самом деле является точкой агрегирования. Таким образом, подобные преобразования действительно «должны» быть сделаны при последующей обработке результатов курсора.

...