【问题标题】:elasticsearch mapping for loop structure循环结构的弹性搜索映射
【发布时间】:2018-02-03 18:39:33
【问题描述】:

我正在尝试对 JSON 数据进行一些映射,如下所示

    "0": {
    "ip": "147.135.210.114",
    "countryName": "United States",
    "countryCode": "US",
    "frequency": "46",
    "updown": -0.25579565572885,
    "viewCount": "28"
},
"1": {
    "ip": "171.255.199.129",
    "danger": "94.42262",
    "countryName": "Viet Nam",
    "countryCode": "VN",
    "frequency": "40",
    "updown": -0.088216630501414,
    "viewCount": null
},
"2": {
    "ip": "52.163.62.13",
    "danger": "94.18168",
    "countryName": "United States",
    "countryCode": "US",
    "frequency": "46",
    "updown": -0.016932485456378,
    "viewCount": "5"
},
"3": {
    "ip": "151.80.140.233",
    "danger": "93.77446",
    "countryName": "Unknown",
    "countryCode": "Unknown",
    "frequency": "46",
    "updown": -0.31354507272874,
    "viewCount": "10"
},

如您所见,有很多对象(我什至不确定它是否称为对象)。 该对象具有不同的名称(0,1,2,3,4...)和相同的元素(ip,danger ...)。

如何同时映射具有不同名称的元素?有可能吗?

提前感谢 :-)

【问题讨论】:

    标签: elasticsearch mapping


    【解决方案1】:

    您可以使用相同的映射来映射具有不同名称的元素,但这不太可能有用(取决于您的用例)。

    主要有两种选择:

    • 使用dynamic_templates描述重复结构的数据;
    • 重塑数据并使用 nested 数据类型

    dynamic_templates

    优点:

    • 完成任务
    • 无需更改数据

    缺点:

    • 很难或不可能查询
    • 地图爆炸的风险

    重塑 + nested

    优点:

    • 完成任务
    • 查询能力没有限制

    缺点:

    • 必须更改数据格式

    下面是详细信息。

    dynamic_templates 使用动态映射

    一般来说,使用dynamic mapping 可以添加任意结构的对象,其类型将根据some predefined rules 动态猜测。

    动态映射使您对数据结构的控制更少,并可能导致mapping explosion

    如果您对动态映射很满意,并且只想调整其应用方式,您可以使用dynamic_templates

    您必须在插入任何数据之前创建一个映射,可能如下所示:

    PUT dyno
    {
      "mappings": {
        "dyno": {
          "dynamic_templates": [
            {
              "dynoField": {
                "path_match": "myPath.*",
                "mapping": {
                  "properties": {
                    "ip": {
                      "type": "keyword"
                    },
                    "danger": {
                      "type": "float"
                    },
                    "countryName": {
                      "type": "keyword"
                    },
                    "countryCode": {
                      "type": "keyword"
                    },
                    "frequency": {
                      "type": "integer"
                    },
                    "updown": {
                      "type": "float"
                    },
                    "viewCount": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          ],
          "properties": {
            "myPath": {
              "type": "object"
            }
          }
        }
      }
    }
    

    这里dynamic_templates 部分应用于myPath 对象的所有键(0、1、2、3、4 等)。

    索引第一个文档后,您从 ES 获得的映射实际上如下所示:

    {
      "dyno": {
        "aliases": {},
        "mappings": {
          "dyno": {
            "dynamic_templates": [
              ...
            ],
            "properties": {
              "myPath": {
                "properties": {
                  "0": {
                    "properties": {
                      "countryCode": {
                        "type": "keyword"
                      },
                      "countryName": {
                        "type": "keyword"
                      },
                      "danger": {
                        "type": "float"
                      },
                      "frequency": {
                        "type": "integer"
                      },
                      "ip": {
                        "type": "keyword"
                      },
                      "updown": {
                        "type": "float"
                      },
                      "viewCount": {
                        "type": "integer"
                      }
                    }
                  },
                  "1": {
                    "properties": {
                      "countryCode": {
                        "type": "keyword"
                      }, ...
                  },
                  "2": {
                    "properties": {
                      "countryCode": {
                        "type": "keyword"
                      }, ...
                  },
                  "3": {
                    "properties": {
                      "countryCode": {
                        "type": "keyword"
                      }, ...
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    

    请注意,对于对象的每个不同“名称”,ES 都会创建一个单独的映射部分。

    虽然这完全符合您的要求,但它可能没有用。如果您有一个用例,希望选择具有特定countryCode 的所有文档,您可以构建这样的查询:

    POST dyno/dyno/_search
    {
      "query": {
        "match": {
          "myPath.1.countryCode": "VN"
        }
      }
    }
    

    但这只会返回与“名称”1 的对象匹配。如果“名称”集合很大和/或事先不知道,那么查询它们将非常复杂。

    重塑数据并使用nested 类型

    为了能够搜索任何对象的countryCode,您可能需要通过以下方式重塑您的数据:

    {
      "myPath": [
        {
          "__name": "0",
          "ip": "147.135.210.114",
          "countryName": "United States",
          "countryCode": "US",
          "frequency": "46",
          "updown": -0.25579565572885,
          "viewCount": "28"
        },
        {
          "__name": "1",
          "ip": "171.255.199.129",
          "danger": "94.42262",
          "countryName": "Viet Nam",
          "countryCode": "VN",
          "frequency": "40",
          "updown": -0.088216630501414,
          "viewCount": null
        }, ...
      ]
    }
    

    棘手的部分是,为了能够单独搜索myPath列表中的项目,必须使用nested数据类型。

    在这种情况下,您的映射可以是 dynamicstrict,无论哪种方式最适合您。 dynamic 案例中的映射可能看起来很简单:

    PUT dyno
    {
      "mappings": {
        "dyno": {
          "properties": {
            "myPath": {
              "type": "nested"
            }
          }
        }
      }
    }
    

    这将允许您进行这样的查询:

    POST dyno/dyno/_search
    {
      "query": {
        "nested": {
          "path": "myPath",
          "query": {
            "match": {
              "myPath.countryCode.keyword": "VN"
            }
          }
        }
      }
    }
    

    请注意,要查询nested 字段,您必须使用nested query。开始使用nested 数据类型的好地方是指南的this chapter

    关于嵌套字段的最后说明

    事实上,对于nested 字段,ES 为列表中的每个项目索引一个隐式文档,因此索引和搜索这种类型的对象比非嵌套对象慢。

    您可以考虑将这些具有不同“名称”的对象拆分为单独的 ES 文档。


    希望有帮助!

    【讨论】:

    • 非常感谢。我确实改变了数据格式,它就像一个魅力:-)
    • @DavidK 太棒了!如果它解决了问题,请随时接受答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    • 2016-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多