Elasticsearch动态字段嵌套检测

4

您好,我正在尝试在Elasticsearch中创建索引,但不想定义映射。因此,我进行了以下操作:

PUT my_index1/my_type/1
{
  "group" : "fans",
  "user" : [
    {
      "first" : "John",
      "last" :  "Smith",
      "age" :  "1",
      "enabled": false
    },
    {
      "first" : "Alice",
      "last" :  "White",
      "age" :  "10",
      "enabled": true
    }
  ]
}

如果这样做,Elasticsearch将为此索引创建一个映射,结果如下:
{
   "my_index1": {
      "mappings": {
         "my_type": {
            "properties": {
               "group": {
                  "type": "text",
                  "fields": {
                     "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                     }
                  }
               },
               "user": {
                  "properties": {
                     "age": {
                        "type": "text",
                        "fields": {
                           "keyword": {
                              "type": "keyword",
                              "ignore_above": 256
                           }
                        }
                     },
                     "enabled": {
                        "type": "boolean"
                     },
                     "first": {
                        "type": "text",
                        "fields": {
                           "keyword": {
                              "type": "keyword",
                              "ignore_above": 256
                           }
                        }
                     },
                     "last": {
                        "type": "text",
                        "fields": {
                           "keyword": {
                              "type": "keyword",
                              "ignore_above": 256
                           }
                        }
                     }
                  }
               }
            }
         }
      }
   }
}

如果您注意到“user”属性没有嵌套其他属性的类型,那么它们自己的类型由Elasticsearch定义。有没有一种方法可以自动完成映射,以便用户属性的格式如下所示:
"user": {
type:"nested"
                  "properties": {
                     "age": {
                        "type": "text",
                        "fields": {
                           "keyword": {
                              "type": "keyword",
                              "ignore_above": 256
                           }
                        }
                     },
                     "enabled": {
                        "type": "boolean"
                     },
                     "first": {
                        "type": "text",
                        "fields": {
                           "keyword": {
                              "type": "keyword",
                              "ignore_above": 256
                           }
                        }
                     },
                     "last": {
                        "type": "text",
                        "fields": {
                           "keyword": {
                              "type": "keyword",
                              "ignore_above": 256
                           }
                        }
                     }
                  }
               }
            }

这里出现了缺失的内容。我目前正在使用Nest。

是否有一种方法可以定义动态映射,以便检测索引上新添加的数据是否是嵌套的?

2个回答

2
默认情况下,Elasticsearch/Lucene没有内部对象的概念。因此,它将对象层次结构展平为一个简单的字段名称和值列表。
上述文档将在内部转换为一个更像这样的文档:(有关更多详细信息,请参见嵌套字段类型
{
  "group" :        "fans",
  "user.first" : [ "alice", "john" ],
  "user.last" :  [ "smith", "white" ]
}

这里没有美好的答案。一种常见的方法是使用动态模板将object转换为nested(然而,一个副作用是object类型的所有字段都会被改变为nested类型)。
{
    "mappings": {
        "dynamic_templates": [
            {
                "objects": {
                    "match": "*",
                    "match_mapping_type": "object",
                    "mapping": {
                        "type": "nested"
                    }
                }
            }
        ]
    }
}

另一种方法是在插入数据之前指定字段的映射。
PUT <your index>
{
  "mappings": {
    "properties": {
      "user": {
        "type": "nested" 
      }
    }
  }
}

2
您可以定义一个动态模板,在其中定义自己的自定义映射,这些映射在索引文档时稍后可以使用。
通过以下步骤,帮助您自动将user字段的映射映射到nested类型:
首先,您需要为索引定义一个动态模板,如下所示,该模板具有一个match参数,该参数将匹配与user*模式类似的字段名称,并将其映射到nested类型。
PUT /<index-name>
{
  "mappings": {
    "dynamic_templates": [
      {
        "nested_users": {
          "match": "user*",
          "mapping": {
            "type": "nested"
          }
        }
      }
    ]
  }
}

创建这个模板后,你需要把文档索引到里面。
POST /<index-name>/_doc/1
{
  "group": "fans",
  "user": [
    {
      "first": "John",
      "last": "Smith",
      "age": "1",
      "enabled": false
    },
    {
      "first": "Alice",
      "last": "White",
      "age": "10",
      "enabled": true
    }
  ]
}

现在,当您使用Get Mapping API查看索引文档的映射时,映射将类似于您期望看到的内容。
GET /<index-name>/_mapping?pretty
{
  "index-name": {
    "mappings": {
      "dynamic_templates": [
        {
          "nested_users": {
            "match": "user*",
            "mapping": {
              "type": "nested"
            }
          }
        }
      ],
      "properties": {
        "group": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "user": {
          "type": "nested",                  // note this
          "properties": {
            "age": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "enabled": {
              "type": "boolean"
            },
            "first": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "last": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        }
      }
    }
  }
}

或者,正如@Jacky1205所提到的,如果它不是特定于字段的,则可以使用下面的模板,该模板将匹配所有object类型字段为nested类型。
{
  "mappings": {
    "dynamic_templates": [
      {
        "nested_users": {
          "match": "*",
          "match_mapping_type": "object",
          "mapping": {
            "type": "nested"
          }
        }
      }
    ]
  }
}

@Pants,请查看答案,如果解决了您的问题,请告诉我。 - ESCoder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接