所以这是一个问题,我什至不知道从哪里开始,所以即使指向正确方向的指针也很好。

所以我有看起来像这样的数据:

data = {
   "agg": {
      "agg1": [
         {
            "keyWeWant": "*-20.0",
            "asdf": 0,
            "asdf": 20,
            "asdf": 14,
            "some_nested_agg": [
               {
                  "keyWeWant2": 20,
                  "to": 25,
                  "doc_count": 4,
                  "some_nested_agg2": {
                     "count": 7,
                     "min": 2,
                     "max": 5,
                     "keyWeWant3": 2.857142857142857,
                     "sum": 20
                  }
               },
               {
                  "keyWeWant2": 25,
                  "to": 30,
                  "doc_count": 10,
                  "some_nested_agg2": {
                     "count": 16,
                     "min": 2,
                     "max": 10,
                     "keyWeWant3": 6.375,
                     "sum": 102
                  }
               }
            ]
         },
         {
         ...
         },
         {
         ...
         },
         ...
      ]
   }
}

现在从示例中,在“agg”中有N个“agg1”结果,在每个“agg1”结果中都有一个“keyWeWant”。每个“agg1”结果还具有“some_nested_agg”结果列表,每个结果都包含一个“keyWeWant2”。每个“keyWeWant2”值都与层次结构中某个位置的单个“keyWeWant”值相关联。同样,每个“keyWeWant2”也包含“some_nested_agg2”的一组结果(这次不是列表,而是 map )。每个结果集都包含一个“keyWeWant3”。

现在,我想在保持“keyWeWant”,“keyWeWant2”和“keyWeWant3”(本质上是去规范化)之间的关联的同时,使结构扁平化,以获得如下所示的内容:

我想要的功能看起来像什么:
[
   {
      "keyWeWant" : "*-20",
      "keyWeWant2" : 20,
      "keyWeWant3" : 2.857142857142857
   },
   {
      "keyWeWant" : "*-20",
      "keyWeWant2" : 25,
      "keyWeWant3" : 6.375
   },
   {
   ...
   },
   {
   ...
   }
]

这是一个示例,其中只有深度3,但是可能存在任意深度,其中一些嵌套值是列表,而有些是数组/列表。

我想做的是编写一个函数,以接收想要的密钥以及在哪里可以找到它们,然后去获取密钥并进行非规范化。

看起来像这样:
function_name(data_map, {
   "keyWeWant" : ['agg', 'agg1'],
   "keyWeWant2" : ['agg', 'agg1', 'some_nested_agg'],
   "keyWeWant" : ['agg', 'agg1', 'some_nested_agg', 'some_nested_agg2']
})

有任何想法吗?我熟悉Java,Clojure,Java脚本和Python,并且正在寻找一种相对简单的解决方法。

最佳答案

这是您可以使用的JavaScript(ES6)函数:

function flatten(data, keys) {
    var key = keys[0];
    if (key in data)
        keys = keys.slice(1);
    var res = keys.length && Object.keys(data)
        .map( key => data[key] )
        .filter( val => Object(val) === val )
        .reduce( (res, val) => res.concat(flatten(val, keys)), []);
    return !(key in data) ? res
        : (res || [{}]).map ( obj => Object.assign(obj, { [key]: data[key] }) );
}

// Sample data
var data = {
   "agg": {
      "agg1": [
         {
            "keyWeWant": "*-20.0",
            "asdf": 0,
            "asdf": 20,
            "asdf": 14,
            "some_nested_agg": [
               {
                  "keyWeWant2": 20,
                  "to": 25,
                  "doc_count": 4,
                  "some_nested_agg2": {
                     "count": 7,
                     "min": 2,
                     "max": 5,
                     "keyWeWant3": 2.857142857142857,
                     "sum": 20
                  }
               },
               {
                  "keyWeWant2": 25,
                  "to": 30,
                  "doc_count": 10,
                  "some_nested_agg2": {
                     "count": 16,
                     "min": 2,
                     "max": 10,
                     "keyWeWant3": 6.375,
                     "sum": 102
                  }
               }
            ]
         },
      ]
   }
};

// Flatten it by array of keys
var res = flatten(data, ['keyWeWant', 'keyWeWant2', 'keyWeWant3']);

// Output result
console.log(res);


替代使用路径

如注释中所述,上面的代码不使用路径信息。它只是看起来在所有数组中。如果要查找的键也出现在应忽略的路径中,则可能是一个问题。

以下替代方法将使用路径信息,该信息应作为子数组的数组传递,其中每个子数组首先列出路径键,最后一个元素为要保留的值键:

function flatten(data, [path, ...paths]) {
    return path && (
        Array.isArray(data)
            ? data.reduce( (res, item) => res.concat(flatten(item, arguments[1])), [] )
            : path[0] in data && (
                path.length > 1
                    ? flatten(data[path[0]], [path.slice(1), ...paths])
                    : (flatten(data, paths) || [{}]).map (
                        item => Object.assign(item, { [path[0]]: data[path[0]] })
                    )
            )
    );
}

// Sample data
var data = {
   "agg": {
      "agg1": [
         {
            "keyWeWant": "*-20.0",
            "asdf": 0,
            "asdf": 20,
            "asdf": 14,
            "some_nested_agg": [
               {
                  "keyWeWant2": 20,
                  "to": 25,
                  "doc_count": 4,
                  "some_nested_agg2": {
                     "count": 7,
                     "min": 2,
                     "max": 5,
                     "keyWeWant3": 2.857142857142857,
                     "sum": 20
                  }
               },
               {
                  "keyWeWant2": 25,
                  "to": 30,
                  "doc_count": 10,
                  "some_nested_agg2": {
                     "count": 16,
                     "min": 2,
                     "max": 10,
                     "keyWeWant3": 6.375,
                     "sum": 102
                  }
               }
            ]
         },
      ]
   }
};

// Flatten it by array of keys
var res = flatten(data, [
    ['agg', 'agg1', 'keyWeWant'],
    ['some_nested_agg', 'keyWeWant2'],
    ['some_nested_agg2', 'keyWeWant3']]);

// Output result
console.log(res);

07-24 17:33