ES 既不像 MySQL 这样有严格的 Schema,也不像 MongoDB 那样完全无 Schema,而是介于两者之间。
1️⃣ ES 的 Schema 模式
ES 默认是 Schema-less(无模式) 的,允许动态添加字段。
但 ES 也支持 Schema(映射 Mapping),可以手动定义字段类型,类似 MySQL。
区别: MySQL 需要提前定义表结构,ES 则可以自动识别字段类型(但推荐手动定义)。
2️⃣ ES vs MySQL vs MongoDB
特性 | ES(Elasticsearch) | MySQL | MongoDB |
---|---|---|---|
Schema 约束 | 动态 Schema,可手动定义 | 严格 Schema(表必须有固定结构) | 无 Schema(每条记录可有不同字段) |
数据存储格式 | JSON 文档 | 表行列存储 | BSON 文档 |
索引方式 | 自动索引所有字段(全文检索优化) | 索引需手动创建 | 可选索引 |
扩展性 | 分布式架构,横向扩展方便 | 主从复制,扩展有限 | 分片+副本,可扩展 |
查询方式 | DSL 查询(类似 SQL) | SQL 查询 | BSON 查询 |
3️⃣ ES 的 Schema 示例
💡 默认动态模式(Schema-less) 如果你没有手动定义 Mapping,ES 会自动推测字段类型:
PUT my_index/_doc/1
{
"name": "iPhone",
"price": 999.99,
"release_date": "2025-02-11"
}
📌 ES 会自动创建 my_index 索引,并推测:
name: text
price: float
release_date: date
💡 手动定义 Schema
PUT my_index
{
"mappings": {
"properties": {
"name": {
"type": "keyword" },
"price": {
"type": "float" },
"release_date": {
"type": "date" }
}
}
}
📌 这样可以避免 ES 自动推测错误(例如 keyword vs text)。
🚀 ES 适用于大规模搜索场景,但不是严格关系型数据库的替代品!
在 Elasticsearch(ES)中,索引(Index) 相当于 关系型数据库中的表,它存储的是一组结构化的数据文档。每个索引包含多个 文档(Document),每个文档都有唯一的 ID,并且存储在多个 分片(Shard) 中。
📌 示例:广告投放日志索引
假设我们在 广告投放业务 中存储广告曝光日志,索引名为 ad_impressions_2025-02-11(按日期分索引)。
1️⃣ 定义索引(Mapping)
PUT ad_impressions_2025-02-11
{
"settings": {
"number_of_shards": 10,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"ad_id": {
"type": "keyword" },
"campaign_id": {
"type": "keyword" },
"user_id": {
"type": "keyword" },
"timestamp": {
"type": "date" },
"device_type": {
"type": "keyword" },
"country": {
"type": "keyword" },
"click": {
"type": "boolean" },
"cost": {
"type": "float" }
}
}
}
📌 说明
索引名称:ad_impressions_2025-02-11(每天创建一个新索引)
分片:10 个(number_of_shards: 10,适用于大数据量)
副本:1 份(number_of_replicas: 1,保证数据安全)
字段类型:
ad_id、campaign_id、user_id:keyword(精准查询)
timestamp:date(时间筛选)
click:boolean(是否点击广告)
cost:float(广告投放成本)
2️⃣ 插入数据(广告曝光日志)
POST ad_impressions_2025-02-11/_doc/1
{
"ad_id": "AD12345",
"campaign_id": "CMP67890",
"user_id": "U001",
"timestamp": "2025-02-11T10:30:00Z",
"device_type": "mobile",
"country": "US",
"click": true,
"cost": 0.5
}