09-02 周一 elasticsearch使用指南

09-02 周一 elasticsearch使用指南
时间版本修改人描述
2024年9月2日14:44:29V0.1宋全恒新建文档

简介

elasticsearch使用流程

 基本使用流程为

  1. 创建索引
  2. 添加文档
  3. 检索分析

1. 创建索引

  • 定义索引结构:在 Elasticsearch 中,索引类似于关系数据库中的表。创建索引时,你可以定义字段的映射(类似于表的列和数据类型),这包括每个字段的数据类型和其他属性(如是否需要全文搜索,是否需要索引等)。
  • 指定分片和副本:创建索引时,还可以指定索引的分片和副本数量,以便优化存储和查询性能。

示例:

bashCopy codePUT /my_index
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 1
  },
  "mappings": {
    "properties": {
      "field1": {
        "type": "text"
      },
      "field2": {
        "type": "keyword"
      }
    }
  }
}
  • number_of_shardsnumber_of_replicas 设置了索引的分片和副本数量。
  • properties 下定义了字段的类型,如 textkeyword 等。

2. 向索引中添加文档

  • 插入文档:一旦索引创建完毕,你可以向索引中插入数据,这些数据被称为文档。每个文档都有一个唯一的ID标识符(可以由用户指定,也可以由 Elasticsearch 自动生成)。
  • 文档结构:文档是以 JSON 格式存储的,字段和数据结构不需要完全一致,Elasticsearch 可以处理不同的字段。

示例:

bashCopy codePOST /my_index/_doc/1
{
  "field1": "This is some text",
  "field2": "some_value"
}
  • 这里,我们将一个文档插入到名为 my_index 的索引中,并且指定了文档 ID 为 1

索引和文档的关系

  • 索引相当于数据库表:在 RDBMS 中,你创建一个表,然后向表中插入行。在 Elasticsearch 中,你首先创建索引(定义字段及其类型),然后向索引中添加文档(类似于向表中插入行)。
  • 文档相当于表中的行:文档是 Elasticsearch 中的基本存储单元,类似于关系数据库中的一行。每个文档由一个 JSON 对象表示,包含一组键值对(字段和值)。

需要注意的事项

  • 动态索引:Elasticsearch 支持动态映射,可以在没有事先定义索引的情况下直接插入数据,Elasticsearch 会根据文档中的字段自动推断类型并创建索引。这种方法虽然方便,但在生产环境中最好是手动创建和管理索引结构,以确保数据的一致性和查询的高效性。
  • 索引管理:定期管理索引,避免索引过多或数据分片不均匀,可能需要设置索引生命周期策略(ILM)来管理索引的存储和归档。

演示

演示场景

 使用elasticsearch,演示新建一个索引,基本的场景是存储一个班级中每个人的成绩,成绩表包含姓名,学号,语文成绩和数学成绩,英语成绩,使用接口演示增删改查。

索引创建

PUT /class_scores
{
  "mappings": {
    "properties": {
      "student_id": {
        "type": "keyword"
      },
      "name": {
        "type": "text"
      },
      "chinese_score": {
        "type": "integer"
      },
      "math_score": {
        "type": "integer"
      },
      "english_score": {
        "type": "integer"
      }
    }
  }
}

 发起请求后,响应如下:

{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "class_scores"
}

文档管理

添加文档

POST /class_scores/_doc/1
{
  "student_id": "202401",
  "name": "Alice",
  "chinese_score": 85,
  "math_score": 90,
  "english_score": 88
}

POST /class_scores/_doc/2
{
  "student_id": "202402",
  "name": "Bob",
  "chinese_score": 78,
  "math_score": 82,
  "english_score": 80
}

POST /class_scores/_doc/3
{
  "student_id": "202403",
  "name": "Charlie",
  "chinese_score": 92,
  "math_score": 95,
  "english_score": 94
}

创建文档3的响应为

{
  "_index": "class_scores",
  "_id": "3",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 2,
  "_primary_term": 1
}

检索数据

GET /class_scores/_doc/1

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

GET /class_scores/_search
{
  "query": {
    "range": {
      "chinese_score": {
        "gte": 80
      }
    }
  }
}

在这里插入图片描述

更新文档

在这里插入图片描述

 更新文档之后,数学成绩更新为95,重新检索,可以得到

{
  "_index": "class_scores",
  "_id": "1",
  "_version": 2,
  "_seq_no": 3,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "student_id": "202401",
    "name": "Alice",
    "chinese_score": 85,
    "math_score": 95,
    "english_score": 88
  }
}

删除文档

DELETE /class_scores/_doc/2

删除的响应为

{
  "_index": "class_scores",
  "_id": "2",
  "_version": 2,
  "result": "deleted",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 4,
  "_primary_term": 1
}

 删除了2号文档之后,全量检索,可以看到2号文档已经不存在了。

{
  "took": 8,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "class_scores",
        "_id": "1",
        "_score": 1,
        "_source": {
          "student_id": "202401",
          "name": "Alice",
          "chinese_score": 85,
          "math_score": 95,
          "english_score": 88
        }
      },
      {
        "_index": "class_scores",
        "_id": "3",
        "_score": 1,
        "_source": {
          "student_id": "202403",
          "name": "Charlie",
          "chinese_score": 92,
          "math_score": 95,
          "english_score": 94
        }
      }
    ]
  }
}

全文检索

索引

PUT /class_scores
{
  "mappings": {
    "properties": {
      "student_id": {
        "type": "keyword"
      },
      "name": {
        "type": "text"
      },
      "chinese_score": {
        "type": "integer"
      },
      "math_score": {
        "type": "integer"
      },
      "english_score": {
        "type": "integer"
      },
      "remarks": {
        "type": "text"
      }
    }
  }
}

 其实相当于添加了一个text字段,remarks表示评价,对于该学生的评价,

插入数据

 插入一些数据

POST /class_scores/_doc/1
{
  "student_id": "202401",
  "name": "Alice",
  "chinese_score": 85,
  "math_score": 90,
  "english_score": 88,
  "remarks": "Excellent performance in mathematics."
}

POST /class_scores/_doc/2
{
  "student_id": "202402",
  "name": "Bob",
  "chinese_score": 78,
  "math_score": 82,
  "english_score": 80,
  "remarks": "Needs improvement in Chinese language."
}

POST /class_scores/_doc/3
{
  "student_id": "202403",
  "name": "Charlie",
  "chinese_score": 92,
  "math_score": 95,
  "english_score": 94,
  "remarks": "Outstanding in all subjects."
}

执行全文检索

现在,假设我们想要搜索 remarks 字段中包含 “improvement” 或 “outstanding” 这些关键词的文档。我们可以使用 match 查询来执行全文搜索。

GET /class_scores/_search
{
  "query": {
    "match": {
      "remarks": "improvement"
    }
  }
}

 Elasticsearch 会根据匹配的相关性对结果进行评分和排序。完全匹配的文档得分更高,排名也会更靠前。

 同时搜索 “Charlie” 和 “outstanding”

GET /class_scores/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "Charlie" }},
        { "match": { "remarks": "outstanding" }}
      ]
    }
  }
}

综合查询:多个学科成绩范围

如果你需要检索语文、数学和英语成绩都在 70 到 90 之间的文档,可以将多个 range 查询条件结合在一起:

bashCopy codeGET /class_scores/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "chinese_score": {
              "gte": 70,
              "lte": 90
            }
          }
        },
        {
          "range": {
            "math_score": {
              "gte": 70,
              "lte": 90
            }
          }
        },
        {
          "range": {
            "english_score": {
              "gte": 70,
              "lte": 90
            }
          }
        }
      ]
    }
  }
}

操作子分类

基本查询

 match: 用于执行全文搜索或关键字匹配。适用于分析过的字段(如 text 类型)

term: 用于精确匹配字段值。适用于未分析的字段(如 keyword 类型)

range:用于查找字段值在指定范围内的文档。

复合查询

bool: 用于组合多个查询条件,允许使用 mustshouldmust_notfilter 子句。

子句

  • must:必须匹配的条件。
  • should:应该匹配的条件(至少一个)。
  • must_not:必须不匹配的条件。
  • filter:用于过滤文档,不影响相关性评分。

 示例

{
  "query": {
    "bool": {
      "must": [
        { "match": { "field1": "value1" }},
        { "range": { "field2": { "gte": 10 }}}
      ],
      "should": [
        { "term": { "field3": "value3" }}
      ],
      "must_not": [
        { "term": { "field4": "value4" }}
      ],
      "filter": [
        { "range": { "field5": { "lte": 100 }}}
      ]
    }
  }
}

constant_score:对查询结果应用固定的评分(分数),可以提高查询性能。

特殊查询

match_phrase:用于查找精确的短语匹配。

wildcard:用于匹配具有通配符(如 *?)的字段值。

fuzzy:用于模糊匹配,允许一定的字符差异(类似拼写错误的容错)。

聚合查询

 这些查询用于对文档进行分组、汇总或统计分析。

terms 聚合:用于统计字段的不同值及其出现次数。

range 聚合:用于将字段值划分为多个范围,并统计每个范围的文档数量。

示例:

{
  "aggs": {
    "range_agg": {
      "range": {
        "field": "field_name",
        "ranges": [
          { "to": 10 },
          { "from": 10, "to": 20 },
          { "from": 20 }
        ]
      }
    }
  }
}

histogram 聚合:用于将字段值按固定的区间进行分组,并统计每个区间的文档数量。

过滤器

 用于在查询中应用条件过滤,通常用于 bool 查询的 filter 子句。

term 过滤器:精确匹配字段值。

range 过滤器:根据字段值范围过滤文档。

正排和倒排

 在 Elasticsearch 中,排序功能允许你控制文档的检索顺序,这对于根据某些字段(如日期、分数等)对搜索结果进行排序非常重要。排序有两种基本方式:正排序(升序)和倒排序(降序)。

排序的基本概念

  • 正排序(升序):将文档按照某个字段的值从小到大进行排列。例如,从最小的日期到最新的日期,或从最低的分数到最高的分数。
  • 倒排序(降序):将文档按照某个字段的值从大到小进行排列。例如,从最新的日期到最早的日期,或从最高的分数到最低的分数。

2. 排序的基本语法

在 Elasticsearch 中,你可以通过 sort 参数来指定排序规则。sort 参数支持对一个或多个字段进行排序,并可以指定升序(asc)或降序(desc)排序方式。

GET /my_index/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "field1": {
        "order": "desc"  // 首先按 field1 降序排序
      }
    },
    {
      "field2": {
        "order": "asc"  // 其次按 field2 升序排序
      }
    }
  ]
}

正排索引和倒排索引

 倒排索引(Inverted Index)和正排索引(Forward Index)是文本检索系统中的两种基本索引结构,用于高效地存储和查询数据。

正排索引:快速获取文档内容,但在进行全文检索时效率较低。

倒排索引:适合全文检索,能够快速定位包含特定词项的文档,但需要额外的存储空间来维护词项和文档 ID 列表。

正排索引

定义: 正排索引是一种传统的数据结构,其中每个文档的 ID 映射到该文档的具体内容。也就是说,它从文档 ID 到文档内容的映射。

结构

  • 文档 ID文档内容(字段及其值)

用途: 正排索引主要用于存储和检索文档的原始内容。它的优点是可以快速获取文档的完整内容,但在处理全文检索时不够高效。

示例: 假设有两个文档:

  • 文档 1:{"title": "Introduction to Elasticsearch", "content": "Elasticsearch is a search engine."}
  • 文档 2:{"title": "Advanced Elasticsearch", "content": "Learn advanced features of Elasticsearch."}

正排索引可能看起来像这样:

Document ID 1: {"title": "Introduction to Elasticsearch", "content": "Elasticsearch is a search engine."}
Document ID 2: {"title": "Advanced Elasticsearch", "content": "Learn advanced features of El

倒排索引

定义: 倒排索引是一种用于全文搜索的索引结构,它将词项(单词)映射到包含这些词项的文档 ID 列表。它的结构使得对文档的关键词进行快速检索成为可能。

结构

  • 词项文档 ID 列表(包含该词项的所有文档)

用途: 倒排索引非常适合处理全文检索任务,特别是在需要根据词项查找相关文档时。它的主要优点是可以快速查找包含某个词项的文档。

示例: 对于上述文档,倒排索引可能看起来像这样:

"Elasticsearch" → [1, 2]
"is" → [1]
"a" → [1]
"search" → [1]
"engine" → [1]
"Learn" → [2]
"advanced" → [2]
"features" → [2]
"of" → [2]

工作原理

  1. 建立词典:首先构建一个词项词典,列出所有在文档中出现的词项。
  2. 记录文档 ID:对于每个词项,记录包含该词项的所有文档 ID。

总结

 通过以上操作,我们创建了一个存储学生成绩的索引,演示了增删改查的基本操作。这些步骤可以通过 Kibana 的 Dev Tools 或者直接使用命令行中的 curl 命令来执行。如果您有更多需求或问题,可以进一步探索 Elasticsearch 的其他功能,如聚合查询、全文搜索等。

 同时,本文也描述了全文检索,es非常擅长全文检索,本文也描述了es常用的操作子,并且对于elasticsearc中正排索引和倒排索引进行了描述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值