Elasticsearch:映射(mapping)的实用实践指南

动态映射适用于开发环境,但对于生产级集群禁用它。 将动态配置为 “strict” 以对索引的字段值实施严格模式。有关动态映射的详细描述,请阅读文章 “Elasticsearch:Dynamic mapping”。

PUT /twitter
{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "subscriptionName": {
        "type": "text"
      }
    }
  }
}

当文档大量存储时,可以在定义字段映射时使用优化来节省磁盘空间。

禁用强制(coerce)。强制给你自由,但缺乏纪律。 导致混乱。有关 coerce 的更多描述,请参阅文章 “Elasticsearch:Elasticsearch 中的数据强制匹配”。

PUT /product/_doc/1
{
  "price": 890.90
}

PUT /product/_doc/2
{
  "price": "890.90"
}

我们可以看出来,第一个是成功的。针对第二个命令,虽然指定为字符串,但 ES 只看到引号 “” 内的浮点数,将数据结构存储为浮点数。它将是成功的。

我们接下来使用如下的命令来写入另外一个文档:

PUT /product/_doc/3
{
  "price": "890.90m"
}

上面的命令返回:

{
  "error": {
    "root_cause": [
      {
        "type": "document_parsing_exception",
        "reason": "[2:12] failed to parse field [price] of type [float] in document with id '3'. Preview of field's value: '890.90m'"
      }
    ],
    "type": "document_parsing_exception",
    "reason": "[2:12] failed to parse field [price] of type [float] in document with id '3'. Preview of field's value: '890.90m'",
    "caused_by": {
      "type": "number_format_exception",
      "reason": "For input string: \"890.90m\""
    }
  },
  "status": 400
}

这会失败,因为它在内部以浮点形式存储在数据结构中。

我们使用如下的命令来获得文档 2:

GET /product/_doc/2

上面的命令返回:

{
  "_index": "product",
  "_id": "2",
  "_version": 1,
  "_seq_no": 1,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "price": "890.90"
  }
}

从上面的输出中,我们可以看到 price 的值还是以字符串的形式来存储的。

我们可以做如下的查询:

GET product/_search?filter_path=**.hits
{
  "query": {
    "range": {
      "price": {
        "gte": 890.90
      }
    }
  }
}

上面的命令返回的结果为:r

{
  "hits": {
    "hits": [
      {
        "_index": "product",
        "_id": "1",
        "_score": 1,
        "_source": {
          "price": 890.9
        }
      },
      {
        "_index": "product",
        "_id": "2",
        "_score": 1,
        "_source": {
          "price": "890.90"
        }
      }
    ]
  }
}

从上面的输出中,我们可以看到尽管文档 2 的 price 为 “890.90” 字符串类型,但是查询的结果还是包含它。我们如果做如下的查询:

GET product/_search
{
  "query": {
    "match": {
      "prce": "890.90"
    }
  }
}

上述查询不会有任何的结果,这个是因为 price 为 float 类型。

请注意数字数据类型,如果足够的话请使用 float,因为 double 需要更多空间。 如果足够的话就使用 Integer,因为 Long 占用更多空间。

对于字符串字段,不需要同时使用文本和关键字映射。 使用多重映射需要空间。 仅当需要聚合、排序、精确匹配过滤时才使用关键字,以确保不进行分词。 使用文本进行全文搜索。 仅在需要时同时使用两者。

多字段(multi-feild)映射 - 将 keyword 映射添加到文本字段

PUT /subscriptions
{
  "mappings": {
    "properties": {
      "description": {
        "type": "text"
      },
      "subscriptionsName": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

写入一个文档:

POST /subscriptions/_doc
{
  "description": "Detailed subs...",
  "subscriptionsName": ["Monthly", "Weekly", "Quarterly"]
}

查询文档:

GET /subscriptions/_search
{
  "query": {
    "match_all": {}
  }
}

查询文本:

GET /subscriptions/_search
{
  "query": {
    "match": {
      "subscriptionsName": "Monthly"
    }
  }
}

对 keyword 字段进行查询:

GET /subscriptions/_search
{
  "query": {
    "term": {
      "subscriptionsName.keyword": "Monthly"
    }
  }
}

有关 keyword 及 text 查询的比较,请详细阅读文章 “Elasticsearch:Text vs. Keyword - 它们之间的差异以及它们的行为方式”。

当不需要排序、聚合、过滤时,请将 doc_value 设置为 false。

当不需要相关性评分时,设置 norms 为 false

当不需要对值进行过滤时,请将 index 设置为 false(仍然可以进行聚合,例如时间序列数据)。

猜你喜欢

转载自blog.csdn.net/UbuntuTouch/article/details/131512932
今日推荐