将1d数组转换为2d数组nodejs和mongodb

时间:2016-01-14 21:45:09

标签: javascript arrays node.js mongodb

我有一个数组(作为mongoDB查询的输出) 根据字段“数字”'

进行排序
results = [{
  user: u1,
  number: 1,
  msg: m1
}, {
  user: u2,
  number: 2,
  msg: m2
}, {
  user: u3,
  number: 3,
  msg: m3
}, {
  user: u2,
  number: 4,
  msg: m4
}, {
  user: u1,
  number: 5,
  msg: m5
}]

我想将此数组转换为二维数组,如下所示。请注意,嵌套数组是根据'数字排序的。字段

newResults = [{
  user: u1,
  msg: [{nmsg: m1, number: 1}, {nmsg: m5, number: 5}]
}, {
  user: u2,
  msg: [{nmsg: m2, number: 2 }, {nmsg: m4, number: 4}]

}, {
  user: u3,
  msg: [{nmsg: m3, number 3}]
}    
}]

我可以通过2个for循环来实现这一点,但是,2个循环似乎效率低下,因为数组可以增长到非常大的大小。

有没有办法,可能是使用库还是直接从mongoDB中获得相同的结果?

此外,Mongodb的结构非常简单

作为

{
user
number
msg
}

谢谢

2 个答案:

答案 0 :(得分:0)

你可以使用mongodb aggregation来做到这一点。您需要按编号(使用$sort)按用户进行排序,并生成按键共享同一组的数据数组(使用$group$push)。

db.collection.aggregate([
  { $sort: {number: 1}}, 
  {$group: {
    _id: "$user", 
    msg: {$push: {nmsg: "$msg", number: "$number" }}
  }}
])

为您的数据获得了这样的结果:

{
    "_id" : "u1",
    "msg" : [
            {
                    "nmsg" : "m1",
                    "number" : 1
            },
            {
                    "nmsg" : "m5",
                    "number" : 5
            }
    ]
}
{
    "_id" : "u2",
    "msg" : [
            {
                    "nmsg" : "m2",
                    "number" : 2
            },
            {
                    "nmsg" : "m4",
                    "number" : 4
            }
    ]
}
{ "_id" : "u3", "msg" : [ { "nmsg" : "m3", "number" : 3 } ] }

答案 1 :(得分:0)

您可以使用lodash缩减和订购结果。我在下面的示例中使用了_.chain(),因为它使代码更具可读性,并且可以提高效率。

var results = [
  { user: 'u1', number: 1, msg: 'm1' },
  { user: 'u2', number: 2, msg: 'm2' },
  { user: 'u3', number: 3, msg: 'm3' },
  { user: 'u2', number: 4, msg: 'm4' },
  { user: 'u1', number: 5, msg: 'm5' }
];

var reduced = _.chain(results)
  .groupBy('user').toArray().map(function(record) {
    return {
      user : _.chain(record).head().get('user'),
      msg  : _.chain(record).map(function(data) {
          return { nmsg: data.msg, number: data.number };
        }).sortBy('number')
    }
  }).sortBy('user').value();

var types = [
  { name : 'str', pattern : /("(?:\\.|[^"\\])*")/g },
  { name : 'num', pattern : /(\b[-+]?[0-9]*\.?[0-9]+\b)/g }
]
document.querySelector('code.javascript').innerHTML = types.reduce(function(code, type) {
  return code.replace(type.pattern, '<span class="' + type.name + '">$1</span>')
}, JSON.stringify(reduced, null, '  '))
code.javascript {
  font-family: Consolas,Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace,sans-serif;
  font-size: 12px;
  white-space: pre;
}
code.javascript .str { color: #007F00; }
code.javascript .num { color: #7F007F; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.0.0/lodash.min.js"></script>
<code class="javascript"></code>