【问题标题】:jq --stream filter on multiple values of same keyjq --stream 过滤同一键的多个值
【发布时间】:2019-02-18 23:20:52
【问题描述】:

我正在处理一个非常大的 JSON,其中我需要使用键的值过滤内部 JSON 对象。我的 JSON 如下所示:

{"userActivities":{"L3ATRosRdbDgSmX75Z":{"deviceId":"60ee32c2fae8dcf0","dow":"Friday","localDate":"2018-01-20"},"L3ATSFGrpAYRkIIKqrh":{"deviceId":"60ee32c2fae8dcf0","dow":"Friday","localDate":"2018-01-21"},"L3AVHvmReBBPNGluvHl":{"deviceId":"60ee32c2fae8dcf0","dow":"Friday","localDate":"2018-01-22"},"L3AVIcqaDpZxLf6ispK":{"deviceId":"60ee32c2fae8dcf0","dow":"Friday,"localDate":"2018-01-19"}}}

我想对 localDate 值进行过滤,例如 localDate 在 2018-01-20 或 localDate 在“2018-01-21”,这样输出看起来像。

{"userActivities":{"L3ATRosRdbDgSmX75Z":{"deviceId":"60ee32c2fae8dcf0","dow":"Friday","localDate":"2018-01-20"},"L3ATSFGrpAYRkIIKqrh":{"deviceId":"60ee32c2fae8dcf0","dow":"Friday","localDate":"2018-01-21"}}}

我在这里问了一个类似的问题,意识到我需要对多个值进行过滤并保留 JSON 的原始结构。

https://stackoverflow.com/questions/52324497/how-to-filter-json-using-jq-stream

提前致谢!

【问题讨论】:

  • 请准确解释大型 JSON 文件与示例 JSON 的关系。例如。前者是否只包含一个 JSON 对象和一个键?
  • JSON 文件大约 20 GB,它包含 userActivities 密钥以及数百万随机生成的密钥,如 L3ATrosRdbDgSmX75Z,如示例 json 所示。在这些键下存在 localDate 字段,我需要提取输出 json(如问题所示),其中 localDate 落在 2018 年 8 月

标签: json bigdata filtering jq


【解决方案1】:

jq Cookbook借用def atomize(s)

# Convert an object (presented in streaming form as the stream s) into
# a stream of single-key objects
# Examples:
#   atomize({a:1,b:2}|tostream)
#   atomize(inputs) (used in conjunction with "jq -n --stream")
def atomize(s):
  fromstream(foreach s as $in ( {previous:null, emit: null};
      if ($in | length == 2) and ($in|.[0][0]) != .previous and .previous != null
      then {emit: [[.previous]], previous: $in|.[0][0]}
      else { previous: ($in|.[0][0]), emit: null}
      end;
      (.emit // empty), $in) ) ;

由于 OP 描述的顶级对象只包含一个键,我们可以选择 2018 年 8 月的对象如下:

atomize(1|truncate_stream(inputs))
| select( .[].localDate[0:7] == "2018-08")

如果您希望将这些收集到一个复合对象中,您可能需要注意内存,因此您可能希望将选定的对象通过管道传输到另一个程序(例如 awk 或 jq)。否则,我会选择:

def add(s): reduce s as $x (null; .+$x);

{"userActivities": add(
    atomize(1|truncate_stream(inputs | select(.[0][0] == "userActivities")))
    | select( .[].localDate[0:7] =="2018-01") ) }

变化

如果顶级对象有多个键,则以下变体将是合适的:

atomize(1|truncate_stream(inputs | select(.[0][0] == "userActivities")))
| select( .[].localDate[0:7] =="2018-08")

【讨论】:

  • 我的输出包含单独的键对象。但是,如示例输出中所述,我想保留 JSON 结构,但我将每个键作为单独的 JSON 对象获取。
  • 您应该能够找到一种方法来做到这一点,因为有很多很多的可能性。
  • 酷!我将探索将这些 JSON 对象合并到单个 JSON 文件中的选项。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2017-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-24
  • 1970-01-01
  • 2015-08-26
  • 1970-01-01
相关资源
最近更新 更多