2

我有一个 Firebase 数据库的转储,它代表我们存储在 JSON 中的用户表。我想对其进行一些数据分析,但问题是它太大而无法完全加载到内存中并使用纯 JavaScript(或_类似库)进行操作。

到目前为止,我一直在使用JSONStream包来处理我的小块数据(它为 JSON 转储中的每个用户调用一次回调)。

不过,我现在遇到了障碍,因为我想根据用户 ID 的值过滤它们。我试图回答的“问题”的形式是“哪些用户 x”,而之前我只是问“有多少用户 x”,并不需要知道他们是谁。

数据格式如下:

{
    users: {
        123: {
            foo: 4
        },
        567: {
            foo: 8
        }
    }
}

我想要做的基本上123567根据foo. _.each现在,如果这是一个小列表,那么使用诸如迭代键和值并提取我想要的键之类的东西将是微不足道的。

不幸的是,由于它不适合无法工作的内存。var parser = JSONStream.parse('users.*');使用 JSONStream,我可以通过使用它并将其传递到一个处理它的函数中来迭代它,如下所示:

var stream = fs.createReadStream('my.json');

stream.pipe(parser);

parser.on('data', function(user) {
    // user is equal to { foo: bar } here
    // so it is trivial to do my filter
    // but I don't know which user ID owns the data
});

但问题是我无法访问代表我传入的星号通配符的密钥JSONStream.parse。换句话说,我不知道是{ foo: bar}代表 user123还是 user 567

问题是双重的:

  1. 如何从回调中获取当前路径?
  2. 有没有更好的方法来处理这个太大而无法放入内存的 JSON 数据?
4

1 回答 1

4

我继续编辑 JSONStream 以添加此功能。

如果有人遇到此问题并想以类似方式对其进行修补,则可以替换line 83以前的

stream.queue(this.value[this.key])

有了这个:

var ret = {};
ret[this.key] = this.value[this.key];

stream.queue(ret);

在原始问题的代码示例user{ foo: bar },它现在将是{ uid: { foo: bar } }

由于这是一项重大更改,我没有将拉取请求提交回原始项目,但我确实将其留在了问题中,以防他们将来想为此添加标志或选项。

于 2013-12-19T20:06:21.187 回答