ES 查询

2022-09-19 15:50:48 浏览数 (1)

1、构造运行环境

打开kibana进入Dev tools,创建索引,并插入测试数据,代码如下:

代码语言:javascript复制
PUT /logs/_doc/1
{
  "Name":"燕麦",
  "Desc":"燕麦商品描述",
  "Price":111,
  "Tags":["Breakfast","Carbon","Cheap"]
}

PUT /logs/_doc/2
{
  "Name":"牛奶",
  "Desc":"牛奶商品描述",
  "Price":222,
  "Tags":["Breakfast","Nutrition","Expensive"]
}

PUT /logs/_doc/3
{
  "Name":"面包",
  "Desc":"牛奶商品描述",
  "Price":333,
  "Tags":["Breakfast","Barley","Cheap","Carbon"]
}

PUT /logs/_doc/4
{
  "Name":"玉米",
  "Desc":"玉米商品描述",
  "Price":444,
  "Tags":["Breakfast","Vegetables","Cheap","Carbon"]
}

PUT /logs/_doc/5
{
  "Name":"葡萄",
  "Desc":"葡萄商品描述",
  "Price":555,
  "Tags":["Breakfast","Fruits","Expensive","Carbon"]
}

执行以上代码,并执行搜索,查看数据是否插入,简单搜索代码如下:

代码语言:javascript复制
GET /logs/_search

或者

代码语言:javascript复制
GET /logs/_search
{
  "query": {
    "match_all": {}
  }
}

注:这里相当于select * from 表名 where 1=1,match_all相当于匹配所有.

查询结果集如下:

代码语言:javascript复制
{
  "took": 2,//当前请求花费的时间
  "timed_out": false,//当前请求是否超时
  //当前请求的分片情况
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 5,//当前请求查询到5条结果
      "relation": "eq" //当前查询的关系是等于
    },
    "max_score": 1, //当前查询的评分,最大是1.0
    "hits": [
      {
        "_index": "logs",
        "_id": "1",
        "_score": 1,
        "_source": {
          "Name": "燕麦",
          "Desc": "燕麦商品描述",
          "Price": 111,
          "Tags": [
            "Breakfast",
            "Carbon",
            "Cheap"
          ]
        }
      },
      {
        "_index": "logs",
        "_id": "2",
        "_score": 1,
        "_source": {
          "Name": "牛奶",
          "Desc": "牛奶商品描述",
          "Price": 222,
          "Tags": [
            "Breakfast",
            "Nutrition",
            "Expensive"
          ]
        }
      },
      {
        "_index": "logs",
        "_id": "3",
        "_score": 1,
        "_source": {
          "Name": "面包",
          "Desc": "牛奶商品描述",
          "Price": 333,
          "Tags": [
            "Breakfast",
            "Barley",
            "Cheap",
            "Carbon"
          ]
        }
      },
      {
        "_index": "logs",
        "_id": "4",
        "_score": 1,
        "_source": {
          "Name": "玉米",
          "Desc": "玉米商品描述",
          "Price": 444,
          "Tags": [
            "Breakfast",
            "Vegetables",
            "Cheap",
            "Carbon"
          ]
        }
      },
     
        "_index": "logs",
        "_id": "5",
        "_score": 1,
        "_source": {
          "Name": "葡萄",
          "Desc": "葡萄商品描述",
          "Price": 555,
          "Tags": [
            "Breakfast",
            "Fruits",
            "Expensive",
            "Carbon"
          ]
        }
      }
    ]
  }
}

这里插入成功了.

2、相关度评分

1中的demo查询结果集中有一个max_score字段就是相关度评分,当使用查询接口时没有指定排序字段,那么ES就会按照每条记录的评分进行排序.相关度评分中涉及到两种算法,会在后续的文章中进行介绍.

3、元数据

1中的demo查询结果集有一个source字段就是元数据,其大致结构如下

代码语言:javascript复制
"_source": {
          "Name": "燕麦",
          "Desc": "燕麦商品描述",
          "Price": 111,
          "Tags": [
            "Breakfast",
            "Carbon",
            "Cheap"
          ]
        }

结果类似与关系型数据库中的表字段和相关的值.

3.1、禁用元数据(source)

3.1.1 优缺点

优点:节省存储开销

缺点:不支持update、update_by_query、reindex_api、不支持高亮、不支持reindex,更改mapping分析器以及版本升级、通过索引时查看原文档进行聚合查询会失效、导致自动修复索引的功能实现.

注:如果单纯为了介绍存储开销,可以使用压缩索引,比禁用source更好.

3.1.2 通过创建索引时指定mapping配置来控制source

缺点:通过创建索引时指定mapping配置,来强制限制souce的字段查询的方式或者在mapping中禁用source,设置之后将无法修改.

(1)、完全禁用source

代码语言:javascript复制
PUT /logs
{
  "mappings": {
    "_source": {
      "enabled": false
    }
  }
}

(2)、禁用source中的部分字段

代码语言:javascript复制
PUT /logs
{
  "mappings": {
    "_source": {
      "includes": [
        "Name",
        "Tags"
      ],
      "excludes": [
        "Price",
        "Desc"
      ]
    }
  }
}

通过指定includes和excludes来展示和禁用source中的字段

注:不推荐使用mapping的方式来控制source!!!!!!!

3.1.3 通过在查询条件来控制source

(1)、查询时禁用mapping

代码语言:javascript复制
GET /logs/_search
{
  "_source":false,
  "query": {
    "match_all": {}
  }
}

这时结果集中不会包含mapping等相关信息,只包含index、id、score等相关信息.

(2)、常规搜索

代码语言:javascript复制
GET /logs/_search
{
  "_source": ["Name","Tags"], 
  "query": {
    "match_all": {}
  }
}

通过在api中指定_source来控制查询结果返回的字段,类似与关系型数据库中的 select Name,Tags from logs;

(3)、通配符查找

删除1demo中的索引,新建以下索引

代码语言:javascript复制
PUT /logs/_doc/1
{
  "Name":"燕麦",
  "Desc":"燕麦商品描述",
  "Price":111,
  "Items":{
    "Name":"子名称",
    "Price":222
  },
  "Tags":["Breakfast","Carbon","Cheap"]
}

logs索引中包含一个Items的对象属性,如果此时搜索只希望查Items的相关信息,可以执行以下操作

代码语言:javascript复制
GET /logs/_search
{
  "_source":["Items.*"],
  "query": {
    "match_all": {}
  }
}

返回的结果如下:

代码语言:javascript复制
   "hits": [
      {
        "_index": "logs",
        "_id": "1",
        "_score": 1,
        "_source": {
          "Items": {
            "Price": 222,
            "Name": "子名称"
          }
        }
      }
    ]

(4)、includes查看和exincludes查找

代码语言:javascript复制
GET /logs/_search
{
  "_source":{
    "includes": ["Items.*","Price","Desc"],
    "excludes": ["Name"]
  },
  "query": {
    "match_all": {}
  }
}

这里可以指定查询包含哪些字段和不包含哪些字段

4、QueryString 查询

4.1 查询所有

代码语言:javascript复制
GET /logs/_search

4.2 分页搜索

代码语言:javascript复制
GET /logs/_search?from=0&size=3&sort=Price:desc

查询从第from条开始,一共查size条数据,排序条件时Price按desc排序.

4.3 精准匹配

代码语言:javascript复制
GET /logs/_search?q=Name:牛奶

这里查询的就是log中Name索引集合中值为牛奶的document.        

注:ES默认会为所有的字段创建倒排索引,如果通过q=字段:字段值的形式进行搜索,ES会去指定字段的索引集合查找相关的值并返回.

4.4 all搜索

代码语言:javascript复制
GET /logs/_search?q=111

重点注意:ES默认会为所有的字段创建倒排索引,所以如4.3中一样,查询条件没有以q=字段:字段值的形式进行搜索,ES扫描所有建立了倒排索引的字段.所以这里的结果集如下:

代码语言:javascript复制
    "hits": [
      {
        "_index": "logs",
        "_id": "2",
        "_score": 1.3167865,
        "_source": {
          "Name": "牛奶",
          "Desc": "牛奶商品描述111",
          "Price": 222,
          "Tags": [
            "Breakfast",
            "Nutrition",
            "Expensive"
          ]
        }
      },
      {
        "_index": "logs",
        "_id": "1",
        "_score": 1,
        "_source": {
          "Name": "燕麦",
          "Desc": "燕麦商品描述",
          "Price": 111,
          "Tags": [
            "Breakfast",
            "Carbon",
            "Cheap"
          ]
        }
      }
    ]

Price和Desc中包含111的记录都被检索出来了.

注:这里需要注意精准匹配的问题.demo中Desc字段会被分词,在进行匹配,但是Price并不会.!!!

0 人点赞