首页 > 解决方案 > 基于路径展平/减少嵌套 JSON,收集路径/层次结构中的字段

问题描述

更新:2018 年 11 月 18 日:我在这篇文章的末尾添加了更多示例和说明。

我嵌套了由 Elasticsearch 聚合产生的 JSON 结构,看起来与此类似(为示例而简化):

{
"some_field": "ignore",
"buckets": [
  {
    "key": "a",
    "buckets": [
      { "key": "foo", "name": "FOO" },
      { "key": "bar", "name": "BAR" }
    ]
  },
  {
    "key": "b",
    "buckets": [
      { "key": "boo", "name": "BOO" },
      { "key": "baa", "name": "BAA" }
    ]
  }
]
}

我想将其转换为

[ 
    {key: "a", name: "FOO"},
    {key: "a", name: "FOO"},
    {key: "b", name: "BOO"},
    {key: "b", name: "BAA"}
]

虽然这对于任何特定情况都是一个简单的问题,但我不想每次都“重新发明轮子”并为其编码。嵌套级别可能会有所不同,我可能会选择(沿路径)的字段可能会有所不同。

上面是一些简化的例子。由于这些来自 Elasticsearch 响应,另一个示例可能是:

"aggregations": {
"boo": {
  "buckets": [
    {
      "key": "keyA",
      "foo": {
        "buckets": [
          {
            "key": "keyA.a",
            "bar": {
              "hits": {
                "hits": [{"_index": "indexA", "_id": "idA", "_source": {"name": "nameA"}}]
              }
            }
          }
        ]
      }
    },
    {
      "key": "keyB",
      "foo": {
        "buckets": [
          {
            "key": "keyA.a",
            "bar": {
              "hits": {
                "hits": [{"_index": "indexB", "_id": "idB", "_source": {"name": "nameB"}}]
              }
            }
          }
        ]
      }
    }
  ]
}

}

我想要的结果,对于展平/采摘字段是

[
{"boo": "keyA", "foo": "keyA.a", "name": "nameA", "id": "idA"},
{"boo": "keyB", "foo": "keyA.a", "name": "name", "id": "idB"}
]

有谁知道如何处理 JMESPath、JSONPath、lodash 等?使用 JSONPath 或 JMESPath 之类的东西,我可以轻松地选择“叶”值,但我试图在层次结构中沿路径收集字段。

如前所述,我可以对每种情况进行编码,但我想重用一个库并声明我的投影。

我想我可以用 jq 做到这一点,但我需要它在浏览器中运行。

谢谢

标签: javascriptelasticsearch

解决方案


Lodash 在您的情况下很有用,可以在浏览器中使用。 襟翼地图和地图功能是您所需要的。

const _ = require('lodash');
var obj = {
  "some_field": "ignore",
  "buckets": [
    {
      "key": "a",
      "buckets": [
        { "key": "foo", "name": "FOO" },
        { "key": "bar", "name": "BAR" }
      ]
    },
    {
      "key": "b",
      "buckets": [
        { "key": "boo", "name": "BOO" },
        { "key": "baa", "name": "BAA" }
      ]
    }
  ]
};

var res = _.flatMap(obj.buckets, x => {
  return _.map(x.buckets, y => {
    y.key = x.key;
    return y;
  });
});

console.log(res);
//  Output:
//  [ { key: 'a', name: 'FOO' },
//    { key: 'a', name: 'BAR' },
//    { key: 'b', name: 'BOO' },
//    { key: 'b', name: 'BAA' }]

推荐阅读