如何使用 Java 手动展平 Elasticsearch 嵌套的 JSON 文档?

Posted

技术标签:

【中文标题】如何使用 Java 手动展平 Elasticsearch 嵌套的 JSON 文档?【英文标题】:How to manually flatten Elasticsearch nested JSON documents using Java? 【发布时间】:2015-11-12 13:21:15 【问题描述】:

我想为我的 Elasticsearch 文档结构生成一些文档。问题是我将嵌套的 JSON 存储在我的索引中,但我想记录 Elasticsearch 生成的扁平化 JSON 格式¹。

有没有一种类似于 Elasticsearch 使用 ES Java API 生成的方式来扁平化这个 JSON 的方法?

如果可能的话,我不想为这个任务启动 Elasticsearch。

示例 JSON:


  "title": "Nest eggs",
  "body":  "Making your money work...",
  "tags":  [ "cash", "shares" ],
  "comments": [ 
    
      "name":    "John Smith",
      "comment": "Great article",
      "age":     28,
      "stars":   4,
      "date":    "2014-09-01"
    ,
    
      "name":    "Alice White",
      "comment": "More like this please",
      "age":     31,
      "stars":   5,
      "date":    "2014-10-22"
    
  ]

在 Elasticsearch 将其展平后,文档将如下所示。


  "title":            [ eggs, nest ],
  "body":             [ making, money, work, your ],
  "tags":             [ cash, shares ],
  "comments.name":    [ alice, john, smith, white ],
  "comments.comment": [ article, great, like, more, please, this ],
  "comments.age":     [ 28, 31 ],
  "comments.stars":   [ 4, 5 ],
  "comments.date":    [ 2014-09-01, 2014-10-22 ]

[1]https://www.elastic.co/guide/en/elasticsearch/guide/current/nested-objects.html

【问题讨论】:

something like this 或 this 有帮助吗?其他解决方案也是available here。 【参考方案1】:

我编写了自己的算法,将用于创建 JSON 的 Map 展平。

private void flatten(Map<String, Object> map, Map<String, Object> output, String key) throws JSONException 
        String prefix = "";
        if (key != null) 
            prefix = key + ".";
        
        for (Entry<String, Object> entry : map.entrySet()) 
            String currentKey = prefix + entry.getKey();
            if (entry.getValue() instanceof Map) 
                flatten((Map<String, Object>) entry.getValue(), output, prefix + entry.getKey());
             else if (entry.getValue() instanceof List) 
                output.put(currentKey, entry.getValue());
             else 
                output.put(currentKey, entry.getValue());
            
        
    

使用示例:

    Map<String, Object> outputMap = new TreeMap<>();
    flatten(inputMap, outputMap, null);
    JSONObject json = new JSONObject(outputMap);
    String jsonStr = json.toString(4);

【讨论】:

你测试了吗?它是如何处理集合的? 我的模型只使用列表、地图和字符串。列表被保留,地图被折叠。到目前为止我还没有遇到问题。 很高兴你能成功。我问是因为几周前我做了一些非常相似的事情,当这些对象是 POJO 时,扁平化嵌套对象的集合特别棘手。

以上是关于如何使用 Java 手动展平 Elasticsearch 嵌套的 JSON 文档?的主要内容,如果未能解决你的问题,请参考以下文章

如何展平嵌套元组?

GDB:打印/转储到文件时自动展平结构

展平对象中的数组

使用 Streams 展平 Java 对象

如何使用 linq 表达式展平嵌套对象

如何使用 linq 表达式展平嵌套对象