2014-02-10 3 views
0

У меня есть довольно сложная модель документа, который структурно так:MongoDB Aggregation с очень сложными документами

{ 
    _id: 1, 
    "title": "I'm number one", 
    ... (many other meta data text fields not desired in the summary) 
    "foo": { 
     "tom": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
     "dick": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
     "harry": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
     ... (Total of 14 fields in foo) 
    }, 
    "bar": { 
     "joe": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
     "fred": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
     "bob": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
     ... (Total of 14 fields in bar) 
    }, 
    "dodads": [ 
     { 
     "contraption": 0, 
     "doohickey": 0, 
     "gewgaw": 0, 
     "gizmo": 0, 
     ... (total of 15 elements in each doodad object) 
     }, 
     { 
     "contraption": 0, 
     "doohickey": 0, 
     "gewgaw": 0, 
     "gizmo": 0, 
     ... 
     }, 
     ... (total of 6 objects in dodads object array) 
    ] 
}, 
... (a couple hundred documents in total) 

Что я ищу это список всех объектов/массивов, которые имеют числовые данные. Я хотел бы, чтобы результат был документом в исходном формате, который содержит числовые поля, суммированные. Пока, скажем, все документы имеют одинаковую структуру.

В результате агрегации будет иметь следующего

{ 
    "foo": { 
     "tom": [35, 65, 13, 22, 36, 58, 93, 43, 56, 44, 23, 72], 
     "dick": [56, 87, 28, 49, 34, 22, 48, 86, 29, 23, 88, 29], 
     ... (All 14 fields in foo) 
    }, 
    "bar": { 
     "joe": [87, 28, 49, 34, 22, 48, 86, 29, 23, 88, 29, 47], 
     "fred": [13, 22, 36, 58, 93, 43, 56, 44, 23, 72, 35, 65], 
     ... (All 14 fields in bar) 
    }, 
    "dodads": [ 
     { 
     "contraption": 45, 
     "doohickey": 88, 
     "gewgaw": 23, 
     "gizmo": 64, 
     ... (All 15 elements in each doodad object) 
     }, 
     { 
     "contraption": 12, 
     "doohickey": 73, 
     "gewgaw": 57, 
     "gizmo": 86, 
     ... 
     }, 
     ... (All 6 objects in dodads object array) 
    ] 
} 

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

Что мне интересно, есть ли сокращенный способ определения суммирования? Например, могу ли я сказать, что мне нужна сводка foo или foo.tom и вернуться к их содержанию?

+1

Можете ли вы уточнить, что вы подразумеваете под «обобщать» ? Вы запрашиваете только числовые поля и никакие другие поля на выходе –

+0

@NeilLunn Да сводка всех объектов/массивов, которые имеют числовые данные. Я добавил образец вывода, чтобы, надеюсь, уточнить результат, который я ищу. – Jim

ответ

0

В вашей структуре документа есть некоторые вещи, которые на самом деле вам не помогут. То есть, прежде всего, использование поддокументов, подобные этим:

"foo": { 
    "tom": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
    "dick": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
    "harry": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
}, 
"bar": { 
    "joe": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
    "fred": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
    "bob": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
} 

Это делает вещи довольно трудно, как вы можете, как правило, только получить в содержащиеся поля с обозначениями, такие как «foo.tom», «bar.fred "и т.д. по причинам, которые я комментировал ранее, и который лучше всего объясняется следующими через links, но подведение итогов, где это возможно, что вы собираетесь сделать жизнь проще за счет изменения структуры документов:

"foo": [ 
    { "name": "tom", "values": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }, 
    { "name": "dick", "values": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }, 
    { "name": "harry", "values": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] } 
], 

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

Что касается того, что вы хотите сделать, чтобы найти поля, которые являются числовыми, I asked this question here, который в основном является переформулировкой того, что вам нужно. От ответа есть подход к этому, используя mapReduce.

map = function() { 
    function isNumber(n) { 
     return !isNaN(parseFloat(n)) && isFinite(n); 
    } 

    var numerics = []; 
    for(var fn in this) { 
     if (isNumber(this[fn])) { 
      numerics.push({f: fn, v: this[fn]}); 
     } 
     if (Array.isArray(this[fn])) { 
      // example ... more complex logic needed 
      if(isNumber(this[fn][0])) { 
       numerics.push({f: fn, v: this[fn]}); 
      } 
     } 
    } 
    emit(this._id, { n: numerics }); 
}; 

reduce = function(key, values) { 
    return values; 
}; 

Это может быть то, что вам нужно, но от этого скелета учтите, что вам может понадобиться, чтобы сделать некоторые сложные раскручивание полей в документе, чтобы проверить это, как там на самом деле не простой способ сделать это. Вам в основном придется добавить много логики обхода в это, чтобы придумать то, что вы хотите в структуре, которую у вас есть.

Как вы, кажется, после того, как «найти информацию о структуре документов», то вы можете посмотреть на ответы на этот вопрос: MongoDB Get names of all keys in collection

+0

Это структура документа, которую я создал, поэтому у меня есть контроль над ее изменением. Это моя первоначальная структура (это просто фиктивные имена полей, например, для целей).Он работает для моего пользовательского интерфейса, но может быть изменен для облегчения агрегации. Поэтому речь идет только о суммировании числовых значений, распределенных в нескольких документах. Другими словами, сверните. – Jim

Смежные вопросы