【问题标题】:Mongodb Aggregation with very complex documents具有非常复杂文档的 Mongodb 聚合
【发布时间】:2014-03-08 12:25:36
【问题描述】:

我有一个相当复杂的文档模型,其结构如下:

{
   _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,第二个只是 bar ...)。

我想知道的是,是否有指定摘要的简写方式?例如,我可以说我想要foofoo.tom 的摘要并取回它们的摘要内容吗?

【问题讨论】:

  • 你能解释一下你所说的“总结”是什么意思吗?您是否只要求输出中的数字字段而不要求其他字段
  • @NeilLunn 是所有具有数字数据的对象/数组的摘要。我添加了一个示例输出,希望能澄清我正在寻找的结果。

标签: mongodb aggregation-framework


【解决方案1】:

在您的文档结构中有些东西在这方面确实对您没有帮助。这主要是使用这样的子文档:

"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] }
],

因为这将使您能够更好地访问查询元素,而不是您需要使用的 explicit 引用。我之前给出的答案更深入地介绍了这一点。

至于您想在查找数字字段时做什么,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

【讨论】:

  • 这是我创建的文档结构,因此我可以控制更改它。这是我的初始结构(出于示例目的,这些只是虚拟字段名称)。它适用于我的用户界面,但可以修改以促进聚合。因此,只需汇总分布在多个文档中的数值即可。换句话说,就是一个汇总。
猜你喜欢
  • 2019-11-04
  • 1970-01-01
  • 2014-10-21
  • 2016-10-07
  • 1970-01-01
  • 2018-10-31
  • 1970-01-01
  • 1970-01-01
  • 2020-10-05
相关资源
最近更新 更多