Elasticsearch 常用数据类型和映射

文章详细介绍了Elasticsearch的各种数据类型,包括binary、boolean、keyword、text、数字类型、日期类型等,并探讨了对象类型、结构化数据类型、文本搜索类型、聚合数据类型和文档排名类型。此外,还讨论了映射的概念,如动态字段映射、动态模板映射和显式映射,以及如何创建、更新和获取映射。

Elasticsearch 数据类型

常见类型

  • binary:接受二进制值作为 Base64编码字符串。该字段默认不存储且不可搜索,且不得嵌入换行符\n。
  • boolean:布尔值,true 或 false
  • keyword 关键字类型
    • keyword,用于结构化内容,例如 ID、电子邮件地址、主机名、状态代码、邮政编码或标签。
    • constant_keyword 静态常量关键字类型。
    • wildcard 通配符关键字类型。
  • 数字类型
    • 整数 integer、long、short、byte
    • 浮点型 float、double等,浮点型可能损失精度
    • scaled_float 我们要存的值。其对应一个附加参数 scaling_factor(缩放因子)
      • 比如 scaled_float = 1.23,scaling_factor = 10,那么在elastic中存储的值为 12(按整数存储,不损失精度),我们之后再取出来,值就变成了1.2。
      • 如果要完整存储,那么 scaling_factor 就应该设置为100
  • 日期类型
    • type 为 date
    • “2015-01-01” 或 “2015/01/01 12:10:30”
    • 毫秒数
    • 可以使用 format 参数 配置自定义格式(epoch_millis 毫秒数、yyyy-MM-dd HH:mm:ss.SSS 等符合java DateFormat的日期格式)
    • format可以同时使用多一个格式中间用 || 隔开 (如:yyyy-MM-dd || yyyy-MM-dd HH:mm:ss)
  • alias 别名类型
    • 别名类型同时需要设置 path 参数,参数的值为对应别名的字段。字段可能是个对象调用链(object1.object2.field)

对象类型

  • object 对象类型(表示该字段是一个对象类型)
  • flattened 平铺字段类型,将整个对象映射为单个字段。有助于防止映射爆炸。但只支持基本的查询。
  • nested 嵌套字段类型
    • 例如:
      {
      “first” : “John”,
      “last” : “Smith”
      },{
      “first” : “Alice”,
      “last” : “White”
      }
      当我们查询 first:alice,last:"White"时,将不会有结果
  • join 类型是在同一索引的文档中创建父/子关系的特殊字段。

结构化数据类型

  • 范围类型,范围字段类型表示上限和下限之间的连续值范围。例如,一个范围可以表示十月的任何日期或从 0 到 9 的任何整数。它们是使用运算符 gt或gte用于下限和lt或lte用于上限定义的。它们可用于查询,但对聚合的支持有限。

    • integer_range、float_range、long_range、double_range、date_range、ip_range
  • ip 字段类型(ip)存储IPv4或IPv6

  • version 版本字段类型

文本搜索类型

  • text字段类型
    • text,全文内容的字段类型,例如电子邮件正文或产品描述。它被索引之前会被文本分析器(分词器)进行拆分。text 字段最适合非结构化但可读的内容。
    • match_only_text,一种空间优化的变体,它禁用评分,并且在需要位置的查询上执行速度较慢。它最适合索引日志消息。

聚合数据类型

  • aggregate_metric_double
    预先聚合的指标值。
  • histogram
    直方图形式的预聚合数值。

文档排名类型

  • dense_vector
    记录浮点值的密集向量。
  • rank_feature
    记录数字特征以提高查询时的命中率。
  • rank_features
    记录数字特征以提高查询时的命中率。

空间数据类型

  • geo_point
    纬度和经度点。
  • geo_shape
    复杂的形状,例如多边形。
  • point
    任意笛卡尔点。
  • shape
    任意笛卡尔几何。

数组

在 Elasticsearch 中,数组不需要专用的字段数据类型。默认情况下,任何字段都可以包含零个或多个值,但是,数组中的所有值必须属于相同的字段类型

映射

映射是定义文档及其包含的字段如何存储和索引的过程

动态字段映射

默认情况下,当 Elasticsearch 检测到文档中的新字段时,它会默认将该字段动态添加到类型映射中。此功能由映射的参数 dynamic 来决定,这个我们后续来详细说明。
动态字段映射类型对应表

JSON 字段类型“dynamic”:“true”“dynamic”:“runtime”
null无对应字段无对应字段
true/falsebooleanboolean
doublefloatdouble
longlonglong
objectobject无对应字段
array取决于数组中第一个非null值取决于数组中第一个非null值
string通过日期检测datedate
string通过数值检测float或者longfloat或者long
string没有通过date检测或numeric检测text有一个.keyword子字段keyword

date_detection 禁用日期检测

{
 "mappings": {
  "date_detection": false
 }
}

dynamic_date_formats 自定义动态映射的日期格式

{
 "mappings": {
   "dynamic_date_formats": ["MM/dd/yyyy"] // 可配置多个格式
 }
}

numeric_detection false禁用或true启用数字检测(默认为禁用的,在某些应用中,数字会被映射成text)

{
 "mappings": {
   "numeric_detection": true
 }
}

动态模板映射

动态模板映射,是为了控制在默认动态字段映射规则之外映射数据。在进行索引映射的时候,通过各种条件去对应适配动态模板,但此方式也不能解决更精确的字段映射,所以此处我们就不展开说了。

显式映射

我们在日常开发使用中,我建议大家使用显式映射,以更精确的映射字段类型。更便于 elasticsearch 针对对应字段做更精确的索引分析等。

创建索引时直接映射字段

使用创建索引的API直接映射字段(关于创建索引API的说明,请查看 Elasticsearch REST API 索引管理

PUT /person

{
    "mappings": {
        "properties": {
            "age": { 
                "type": "integer"
            },  
            "birthday":  { 
                "type": "date",
                "format":"yyyy-MM-dd HH:mm:ss" 
            }, 
            "name":   { 
                "type": "keyword"  
            },
            "height": {
                "type": "float"
            },
            "id": {
                "type": "long"
            },
            "sex":{
                "type": "byte"
            }
        }
    }
}

如果咱们不显式定义映射,那么 birthday 和 name 都会被映射为 text 类型。

更新映射 API

PUT /<target>/_mapping

路径参数

  • target 索引名

查询参数

  • allow_no_indices
    (可选,布尔值)如果 为false,任何通配符表达式、索引别名或值目标仅丢失或关闭索引,请求将返回错误 。例如,如果请求索引以 foo*,bar* 开头,如果有索引,以foo开头但没有索引以bar开头,则请求定位会返回错误。 默认为true.

  • expand_wildcards
    (可选,字符串)通配符模式可以匹配的索引类型。支持逗号分隔值,例如open,hidden。默认为open.可选值为:

  • all
    匹配任何数据流或索引,包括隐藏的。

  • open
    匹配开放的、非隐藏的索引。也匹配任何非隐藏数据流。

  • closed
    匹配封闭的、非隐藏的索引。也匹配任何非隐藏数据流。数据流无法关闭。

  • hidden
    匹配隐藏的数据流和隐藏的索引。open必须与、 closed或两者 结合使用。

  • none
    不接受通配符模式。

  • ignore_unavailable
    (可选,布尔值)false,如果请求针对丢失或关闭的索引,则请求返回错误。默认为false.

  • local
    (可选,布尔值)true,则请求仅从本地节点检索信息。默认为false,这意味着信息是从主节点检索的。

  • master_timeout
    (可选,时间单位)等待连接到主节点的时间。如果在超时到期之前未收到响应,则请求失败并返回错误。默认为 30s.

请求正文

properties
(必填,映射对象)字段的映射。对于新字段,此映射可以包括:

  • 字段名称
  • 字段数据类型
  • 映射参数

示例:添加新的映射字段

PUT /person/_mapping
{
    "properties":{
        "weight": {
            "type": "float"
        }
    }
}

示例:为object类型字段添加新字段

PUT /person/_mapping
{
    "properties":{
        "child": {
            "properties": {
				"name": {
					"type": "keyword"
				}
			}
        }
    }
}

示例:修改已有的映射字段

注:此操作要谨慎操作,更改现有字段可能会使已编制索引的数据无效。必须要修改,修改之后需要重新索引。

如:把我们刚刚添加的新字段映射类型修改为 keyword

PUT /person/_mapping
{
    "properties":{
        "weight": {
            "type": "keyword"
        }
    }
}

修改之后,我们需要重新索引(请查看上一篇文章 Elasticsearch REST API 文档管理

获取映射API

GET /_mapping

GET /<target>/_mapping

路径参数

  • target
    (可选,字符串)用于限制请求的数据流、索引和别名的逗号分隔列表。

查询参数

  • allow_no_indices
    (可选,布尔值)如果 为false,任何通配符表达式、索引别名或值目标仅丢失或关闭索引,请求将返回错误 。例如,如果请求索引以 foo*,bar* 开头,如果有索引,以foo开头但没有索引以bar开头,则请求定位会返回错误。 默认为true.

  • expand_wildcards
    (可选,字符串)通配符模式可以匹配的索引类型。支持逗号分隔值,例如open,hidden。默认为open.可选值为:

  • all
    匹配任何数据流或索引,包括隐藏的。

  • open
    匹配开放的、非隐藏的索引。也匹配任何非隐藏数据流。

  • closed
    匹配封闭的、非隐藏的索引。也匹配任何非隐藏数据流。数据流无法关闭。

  • hidden
    匹配隐藏的数据流和隐藏的索引。open必须与、 closed或两者 结合使用。

  • none
    不接受通配符模式。

  • ignore_unavailable
    (可选,布尔值)false,如果请求针对丢失或关闭的索引,则请求返回错误。默认为false.

  • local
    (可选,布尔值)true,则请求仅从本地节点检索信息。默认为false,这意味着信息是从主节点检索的。

  • master_timeout
    (可选,时间单位)等待连接到主节点的时间。如果在超时到期之前未收到响应,则请求失败并返回错误。默认为 30s.

示例:查询映射

GET /person/_mapping

示例:查询所有映射

GET /*/_mapping

GET /_all/_mapping

GET /_mapping

映射参数

dynamic 是否动态映射

作用于文档或文档的内部对象

示例

PUT /person
{
  "mappings": {
    "dynamic": false, 
    "properties": {
      "user": { 
        "properties": {
          "name": {
            "type": "text"
          },
          "car": {
            "dynamic": true, 
            "properties": {}
          }
        }
      }
    }
  }
}

该映射表示,我们的文档第一层的字段,只有user,新增的字段将不不会被索引或搜索,而user字段对象,car对象的字段可以动态新增并添加到映射。

dynamic 可接收的参数

  • true
    新字段添加到映射(默认)。
  • runtime
    新字段作为运行时字段 添加到映射中。这些字段没有索引,在_source在查询时加载。
  • false
    忽略新字段。这些字段不会被索引或搜索,但仍会出现在_source返回的命中字段中。这些字段不会添加到映射中,必须显式添加新字段。
  • strict
    如果检测到新字段,则会抛出异常并拒绝文档。

coerce 强制转换(数字类型)

如果设置为true(默认为true)elasticsearch 将会自动转换我们在创建文档时传入的值:

  • 将字符强制转换为数字
  • 如果映射类型为整型,但传入了浮点型,浮点数将会被截断

示例

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "number_one": {
        "type": "integer"
      },
      "number_two": {
        "type": "integer",
        "coerce": false
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "number_one": "10" 
}

PUT my-index-000001/_doc/2
{
  "number_two": "10" 
}

number_one 的 10 会被转换为整型,但 number_two 文档会报错无法新增。

在索引级别使用 index.mapping.coerce 设置
PUT my-index-000001
{
  "settings": {
    "index.mapping.coerce": false
  },
  "mappings": {
    "properties": {
      "number_one": {
        "type": "integer",
        "coerce": true
      },
      "number_two": {
        "type": "integer"
      }
    }
  }
}

使用索引的settings来设置index.mapping.coerce,禁用自动强制类型转换。

analyzer 指定文本分析器

指定的分析器用于索引和搜索分析

关于分析器的具体功能,我们将在后续文章中单独讲解。

search_analyzer

同 analyzer 只不过是其只指定 用于搜索的分析器。

注:一般情况下用于索引和搜索的分析器应该为同一个,所以只指定analyzer 即可。

copy_to 复制字段

copy_to 可以将多个字段的值复制到一个组字段中,然后可以将其作为单个字段进行查询。

示例

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "first_name": {
        "type": "text",
        "copy_to": "full_name" 
      },
      "last_name": {
        "type": "text",
        "copy_to": "full_name" 
      },
      "full_name": {
        "type": "text"
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "first_name": "John",
  "last_name": "Smith"
}

GET my-index-000001/_search
{
  "query": {
    "match": {
      "full_name": { 
        "query": "John Smith",
        "operator": "and"
      }
    }
  }
}

enabled 禁用对象字段

elasticsearch 默认情况下,会为我们添加的字段添加索引,如果我们只想存储字段而不对其建立索引。可以使用 enabled 参数

注:enabled 只能作用于 索引级别或文档中的object字段

PUT /index
{
	"mappings": {
		"enabled": true,
	   "properties": {
			"name": {
				"type":"keyword"
			},
			"car":{
				"type": "object",
				"enabled":false
			}
	    }
    }
}

format 日期格式化

日期格式化的格式遵循Java的日期格式化格式,如:yyyy-MM-dd HH:mm:ss.SSS。我们在文档管理的示例中已经添加过了。

ignore_above、ignore_malformed

ignore_above 数字类型,比如:20.表示字符串超过相应长度,将不被索引。
ignore_malformed 正常情况下,日期类型不正确或数字类型不正确,将忽略此字段,而且文档的其他字段会正常存储。如果设置为false,则如果出现日期类型不正确将会导致整个文档添加失败。

fields

为不同的目的以不同的方式索引同一个字段, string 字段可以映射为 text 用于全文搜索,也可以映射为 keyword 用于排序或聚合

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "city": {
        "type": "text",
        "fields": {
          "raw": { 
            "type":  "keyword"
          }
        }
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "city": "New York"
}

PUT my-index-000001/_doc/2
{
  "city": "York"
}

GET my-index-000001/_search
{
  "query": {
    "match": {
      "city": "york" 
    }
  },
  "sort": {
    "city.raw": "asc" 
  },
  "aggs": {
    "Cities": {
      "terms": {
        "field": "city.raw" 
      }
    }
  }
}

null_value 空值

null_value 将显式值替换null为指定值,以便对其进行索引和搜索。

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "status_code": {
        "type":       "keyword",
        "null_value": "NULL" 
      }
    }
  }
}

此示例我们将null值映射为 “NULL” 字符串

store

是否将数据进行独立存储,默认为 false
原始的文本会存储在_source 里面,默认情况下其他提取出来的字段都不是独立存储的,是从_source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置"store": true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用更多的空间,所以要根据实际业务需求来设置。

<think>好的,我现在需要回答用户关于Elasticsearch(ES)常用数据类型DSL关键字的问题。首先,我得确保自己理解这两个部分的内容,然后组织成一个清晰的中文回答,符合用户提供的系统级指令,比如正确使用LaTeX格式结构清晰。 首先,关于ES的数据类型,用户可能指的是字段的数据类型。ES有丰富的数据类型,我需要回忆并列出常用的那些。常见的有文本(text)、关键字(keyword)、数值类型(如long、integer、short、double、float)、日期(date)、布尔(boolean)等。还有像对象(object)、嵌套(nested)、地理类型(geo_point、geo_shape)这些复杂类型。此外,还有数组、二进制、范围类型(如integer_range)以及一些特殊类型如IP地址、完成建议类型(completion)等。需要确认这些是否都是ES支持的,并且是否常用,比如IP类型确实存在,用于存储IPv4/6地址。完成建议类型用于自动补全功能,这点没错。 接下来是DSL关键字,即领域特定语言中的常用查询聚合关键字。DSL分为查询DSL聚合DSL。查询部分,常见的包括match、term、terms、range、bool(包含must、should、must_not、filter)、match_all、match_phrase、multi_match、exists、prefix、wildcard等。聚合部分,主要分为指标聚合(如avg、sum、max、min、stats、cardinality)桶聚合(如terms、date_histogram、histogram、range、filter、nested)。此外,还有分页排序的关键字,如from、size、sort。 需要确保每个例子都正确,比如term用于精确匹配,而match用于全文搜索。bool查询中的各个子句是否正确,比如must表示必须满足,should表示或条件。聚合中的date_histogram是按时间间隔分桶,terms是按字段值分桶。分页的fromsize参数是否正确,排序使用sort关键字。 然后,检查是否需要补充其他常用类型或关键字。例如,ES中的flattened类型用于存储整个JSON对象作为单个字段,可能不太常用但可以提及。或者,join类型用于处理父子文档关系。不过用户要求的是常用的,可能不需要太深入。此外,动态映射(dynamic)也是一个相关概念,但可能不属于数据类型本身。 在DSL部分,可能还需要提到高亮(highlighting)或脚本(script)相关的关键字,但用户主要关注的是查询聚合,所以可能不需要扩展。需要确保提到的关键字都是最常用的,没有遗漏重要的部分。 最后,结构上需要分点说明,数据类型DSL分别列出,每个部分用小标题,然后子项使用无序列表。按照用户要求,行内公式用$...$,独立公式用$$...$$,但这里可能不需要数学公式,所以主要注意中文回答结构清晰即可。同时确保LaTeX语法正确,如果有用到的话,比如在举例时如果有数学表达式的话,但数据类型DSL关键字本身可能不需要,所以可能不需要使用LaTeX,但需要遵循格式要求,比如用反引号包裹代码关键字。 需要验证是否有错误,比如term查询是否真的用于精确值,而match用于全文。是的,term不会分析输入,而match会经过分析器处理。例如,对于keyword类型的字段,通常使用term查询,而text类型使用match。另外,聚合中的cardinality用于去重统计,是正确的。date类型支持格式设置,这点正确。 总结一下,回答的结构应该是: 1. 常用数据类型 - 列出各个数据类型,简要说明用途 2. DSL关键字 - 查询部分:列出各个查询关键字 - 聚合部分:列出聚合类型 - 分页排序 每个部分给出例子,如查询DSL中的bool结构,聚合中的terms示例等。 最后确保语言简洁,用中文,不使用Markdown,但根据用户层的指示,结构清晰,分点说明。可能使用编号项目符号,但根据系统指令,用户可见层可能需要避免Markdown,所以用文字描述结构。不过原问题中的示例回答使用了Markdown的标题列表,可能用户允许,但需要根据用户的要求。用户提供的示例回答中使用了###列表,但用户可见层的指示可能要求结构清晰,但未明确禁用Markdown,所以可能允许使用。但需要确认。根据用户提供的示例,他们使用了Markdown格式,所以可能允许。 因此,最终回答的结构会是: ### 一、ES常用数据类型 1. **文本类型** - `text`: 用于全文搜索,会被分词。 - `keyword`: 精确值,如标签、状态码。 2. **数值类型** - 如`long`, `integer`, `double`等。 3. **日期类型** - `date`: 支持格式设置。 4. **布尔类型** - `boolean`: true/false。 5. **对象与嵌套类型** - `object`: 存储JSON对象。 - `nested`: 独立处理数组中的对象。 6. **地理类型** - `geo_point`: 经纬度坐标。 - `geo_shape`: 复杂形状。 7. **其他类型** - `ip`: IP地址。 - `completion`: 自动补全。 ### 二、DSL常用关键字 1. **查询类** - `match`: 全文搜索。 - `term`: 精确匹配。 - `range`: 范围查询。 - `bool`: 组合查询(must/should等)。 2. **聚合类** - 指标聚合:`avg`, `sum`等。 - 桶聚合:`terms`, `date_histogram`等。 3. **分页与排序** - `from`/`size`: 分页。 - `sort`: 排序。 然后每个部分给出例子,如bool查询的结构,terms聚合的示例。确保例子正确,比如bool中的filter使用数组,而must等可以包含多个查询条件。 最后检查是否有错别字或错误信息,比如geo_shape是否真的是用于地理形状,completion类型是否正确。确认无误后,整理成自然的中文回答,分点清晰,帮助用户逐步理解ES的数据类型DSL关键字。</think>### 一、ES 常用数据类型 Elasticsearch 支持多种数据类型,以下是用户常用的核心类型: 1. **文本类型** - `text`:用于全文搜索的字符串(会被分词),如文章内容。 - `keyword`:精确值字符串(不分析),如状态码、标签。 2. **数值类型** - 整数:`long`, `integer`, `short`, `byte`。 - 浮点数:`double`, `float`, `half_float`, `scaled_float`。 3. **日期类型** - `date`:支持格式化的日期,如 `"yyyy-MM-dd HH:mm:ss"`。 4. **布尔类型** - `boolean`:存储 `true` 或 `false`。 5. **对象与嵌套类型** - `object`:存储 JSON 对象(字段自动扁平化)。 - `nested`:独立处理数组中的对象(保留对象间关系)。 6. **地理类型** - `geo_point`:存储经纬度坐标(如 `{"lat": 40.73, "lon": -74.1}`)。 - `geo_shape`:存储复杂地理形状(如多边形)。 7. **特殊类型** - `ip`:存储 IPv4/IPv6 地址。 - `completion`:自动补全建议(用于搜索提示)。 - `binary`:存储 Base64 编码的二进制数据。 --- ### 二、DSL 常用关键字 Elasticsearch 的查询语言(DSL)包含以下高频关键字: #### 1. **查询类(Query DSL)** - **基础查询** - `match`:全文搜索(分词后匹配)。 ```json { "query": { "match": { "title": "Elasticsearch 入门" } } } ``` - `term`:精确匹配(不分析值),常用于 `keyword` 字段。 - `terms`:匹配多个精确值(类似 SQL 的 `IN`)。 - `range`:范围查询(如 `"gte": 10, "lte": 20`)。 - **组合查询** - `bool`:逻辑组合查询,包含子句: - `must`:所有条件必须满足(AND)。 - `should`:至少满足一个条件(OR)。 - `must_not`:排除条件(NOT)。 - `filter`:过滤(不计算相关性得分,性能更高)。 ```json { "query": { "bool": { "must": [ { "match": { "content": "大数据" } } ], "filter": [ { "term": { "status": "published" } } ] } } } ``` - **高级查询** - `match_phrase`:短语匹配(保持词序)。 - `wildcard`:通配符匹配(如 `"query": "el*"`)。 - `exists`:检查字段是否存在。 #### 2. **聚合类(Aggregation DSL)** - **指标聚合** - `avg`、`sum`、`max`、`min`:计算平均值、总等。 - `stats`:同时返回多指标(`avg`/`max`/`min`/`sum`/`count`)。 - `cardinality`:去重统计(类似 SQL 的 `COUNT(DISTINCT)`)。 - **桶聚合** - `terms`:按字段值分组(如统计每个分类的文档数)。 ```json { "aggs": { "genres": { "terms": { "field": "genre.keyword" } } } } ``` - `date_histogram`:按时间区间分组(如按月统计)。 - `range`:自定义数值范围分组。 - `filter`:按条件过滤后聚合。 #### 3. **分页与排序** - `from` + `size`:实现分页(如 `"from": 10, "size": 20`)。 - `sort`:排序(如 `{ "price": { "order": "desc" } }`)。 --- ### 三、示例场景 #### 搜索包含“日志”且状态为“成功”的文档(分页+排序): ```json { "query": { "bool": { "must": [ { "match": { "message": "日志" } } ], "filter": [ { "term": { "status.keyword": "成功" } } ] } }, "from": 0, "size": 10, "sort": [ { "timestamp": { "order": "desc" } } ] } ``` #### 按城市分组统计平均薪资: ```json { "aggs": { "city_stats": { "terms": { "field": "city.keyword" }, "aggs": { "avg_salary": { "avg": { "field": "salary" } } } } } } ``` 通过灵活组合数据类型 DSL 关键字,可以高效实现复杂查询与分析需求。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值