映射之删除映射类型

前言

在Elasticsearch 6.0.0或更高版本中创建的索引可能只包含一个映射类型。在5.x中创建索引。具有多种映射类型的将继续在Elasticsearch 6.x中发挥作用。类型将在Elasticsearch 7.0.0的api中被弃用,并在8.0.0中完全删除。

什么是映射类型

自从第一次发布Elasticsearch以来,每个文档都存储在一个索引中,并分配了一个映射类型。映射类型用于表示被索引的文档或实体的类型,例如,一个twitter索引可能有一个user类型和一个tweet类型。

每种映射类型都可以有自己的字段,因此user类型可能有full_name字段、user_name字段和email字段,而tweet类型可能有content字段、tweeted_at字段和user类型一样的user_name字段。

每个文档都有一个包含类型名的_type元字段,通过在URL中指定类型名,可以将搜索限制为一个或多个类型:

GET twitter/user,tweet/_search
{
  "query": {
    "match": {
      "user_name": "kimchy"
    }
  }
}

_type字段与文档的_id相结合,生成了一个_uid字段,因此具有相同_id的不同_type的文档可以存在于单个索引中。

还使用了映射类型来建立文档之间的父子关系,因此类型为question的文档可以是类型为answer的文档的父文档。

为什么映射类别要被移除

最初,我们谈到"index"类似于SQL数据库中的“数据库”,而“类型”相当于“表”。

这是一个错误的类比,导致了错误的假设。在SQL数据库中,表是相互独立的。一个表中的列与另一个表中具有相同名称的列没有关系。这与映射类型中的字段不同。

在Elasticsearch索引中,不同映射类型中具有相同名称的字段在内部由相同的Lucene字段支持。换句话说,使用上面的示例,user类型中的user_name字段与tweet类型中的user_name字段存储在完全相同的字段中,而且两个user_name字段在两种类型中必须具有相同的映射(定义)。

这可能会导致问题,例如,当您希望删除同一索引中的一个类型的日期字段和另一个类型的布尔字段时。

最重要的是,存储在同一索引中具有很少或没有字段的不同实体会导致数据稀疏,并影响Lucene有效压缩文档的能力。

基于这些原因,我们决定将映射类型的概念从Elasticsearch中移除。

映射类型的替代方案

按文档类型索引

**第一种方法是为每个文档类型建立一个索引。**您可以将tweets存储在tweets索引中,而将user存储在user索引中,而不是将tweetsuser存储在单个twitter索引中。索引之间是完全独立的,因此在索引之间不存在字段类型的冲突。

这种方法有两个好处:

  • 数据更可能是密集的,因此受益于Lucene中使用的压缩技术。
  • 在全文检索中用于评分的术语统计信息更有可能是准确的,因为同一索引中的所有文档都具有代表性

自定义类型字段

当然,集群中可以存在多少主碎片是有限制的,因此您可能不希望为了一个只有几千个文档的集合而浪费整个碎片。在这种情况下,您可以实现自己的自定义类型字段,其工作方式与旧的_type类似。
让我们以上面的user/tweet为例。最初,工作流应该是这样的:

PUT twitter
{
  "mappings": {
    "user": {
      "properties": {
        "name": { "type": "text" },
        "user_name": { "type": "keyword" },
        "email": { "type": "keyword" }
      }
    },
    "tweet": {
      "properties": {
        "content": { "type": "text" },
        "user_name": { "type": "keyword" },
        "tweeted_at": { "type": "date" }
      }
    }
  }
}

PUT twitter/user/kimchy
{
  "name": "Shay Banon",
  "user_name": "kimchy",
  "email": "[email protected]"
}

PUT twitter/tweet/1
{
  "user_name": "kimchy",
  "tweeted_at": "2017-10-24T09:00:00Z",
  "content": "Types are going away"
}

GET twitter/tweet/_search
{
  "query": {
    "match": {
      "user_name": "kimchy"
    }
  }
}

你可以通过添加自定义类型字段来达到同样的效果,如下所示:

PUT twitter
{
  "mappings": {
    "_doc": {
      "properties": {
        "type": { "type": "keyword" }, 
        "name": { "type": "text" },
        "user_name": { "type": "keyword" },
        "email": { "type": "keyword" },
        "content": { "type": "text" },
        "tweeted_at": { "type": "date" }
      }
    }
  }
}

PUT twitter/_doc/user-kimchy
{
  "type": "user", 
  "name": "Shay Banon",
  "user_name": "kimchy",
  "email": "[email protected]"
}

PUT twitter/_doc/tweet-1
{
  "type": "tweet", 
  "user_name": "kimchy",
  "tweeted_at": "2017-10-24T09:00:00Z",
  "content": "Types are going away"
}

GET twitter/_search
{
  "query": {
    "bool": {
      "must": {
        "match": {
          "user_name": "kimchy"
        }
      },
      "filter": {
        "match": {
          "type": "tweet" 
        }
      }
    }
  }
}

将多类型索引迁移到单一类型

Reindex API可用于将多类型索引转换为单类型索引。下面的例子可以用在Elasticsearch 5.6Elasticsearch 6.x中。在6.x,不需要指定index.mappingsingle_type是默认值。

按文档类型索引

第一个例子将我们的twitter索引分为tweets索引和users索引:

PUT users
{
  "settings": {
    "index.mapping.single_type": true
  },
  "mappings": {
    "_doc": {
      "properties": {
        "name": {
          "type": "text"
        },
        "user_name": {
          "type": "keyword"
        },
        "email": {
          "type": "keyword"
        }
      }
    }
  }
}

PUT tweets
{
  "settings": {
    "index.mapping.single_type": true
  },
  "mappings": {
    "_doc": {
      "properties": {
        "content": {
          "type": "text"
        },
        "user_name": {
          "type": "keyword"
        },
        "tweeted_at": {
          "type": "date"
        }
      }
    }
  }
}

POST _reindex
{
  "source": {
    "index": "twitter",
    "type": "user"
  },
  "dest": {
    "index": "users"
  }
}

POST _reindex
{
  "source": {
    "index": "twitter",
    "type": "tweet"
  },
  "dest": {
    "index": "tweets"
  }
}

自定义类型字段

下一个示例添加一个自定义类型字段,并将其设置为原始_type的值。它还将类型添加到_id中,以防有任何不同类型的文档具有冲突的id:

PUT new_twitter
{
  "mappings": {
    "_doc": {
      "properties": {
        "type": {
          "type": "keyword"
        },
        "name": {
          "type": "text"
        },
        "user_name": {
          "type": "keyword"
        },
        "email": {
          "type": "keyword"
        },
        "content": {
          "type": "text"
        },
        "tweeted_at": {
          "type": "date"
        }
      }
    }
  }
}


POST _reindex
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
  },
  "script": {
    "source": """
      ctx._source.type = ctx._type;
      ctx._id = ctx._type + '-' + ctx._id;
      ctx._type = '_doc';
    """
  }
}

原文地址: Removal of mapping types

原创文章 61 获赞 3 访问量 3794

猜你喜欢

转载自blog.csdn.net/qq_40179479/article/details/105903338
今日推荐