Elasticsearch DSL基本使用:详细教程和最佳实践

silverwq
2024-01-21 / 0 评论 / 123 阅读 / 正在检测是否收录...

查询

使用 from 和 size 分页查询,需要注意的是:from+size 要小于 10000,不然会报错

// 从第9条开始,查询100条
GET index_test/_search?from=9&size=100


// 这个也行
GET index_test/_search
{
  "from":9,
  "size":100
}

查询某个 id: DE7BEo0BngUdM_im08lv

GET index_test/_doc/DE7BEo0BngUdM_im08lv

查询结果不要元字段,只查询 _source,使用 _source api 加上 id

GET index_test/_source/2

一次性查询多个 id 值

GET index_test/_mget
{
  "ids":[1,2]
}

GET index_test/_search
{
  "query":{
    "ids": {
        "values":[1,2,4]
    }
  }
}

match

match 搜索需要注意以下几点:

  1. 被查询字段必须是可以分词的,比如 name 字段必须是可以分词的,例如 text 类型。
  2. 搜索过程是:首先对搜索词进行分词,然后只要一个某个分词和被搜索字段的分词匹配上了,就满足。、
  3. es 分词的时候,首先会对分词统一改成小写,所以不区分大小写了。

例如下例子中,name 字段必须是可以分词的字段,然后搜索词 小米手机,会被分词

GET index_test/_search
{
  "query":{
    "match": {
      "name": "小米手机" 
    }
  }
}

搜索词分词的时候,本身也会作为分词结果之一,例如 HuaWei Mate 9000 会作为一个特殊项,作为整体去匹配

GET index_test/_search
{
  "query":{
    "match": {
      "name.keyword": "HuaWei Mate 9000"
    }
  }
}

match_phrase

这个查询和 match 查询一样,不同点在于所有分词要按顺序都匹配上

  1. 会对搜索词进行分词
  2. 搜索词的分词必须全部匹配上,并且顺序也要相同,中间不能有其他词。
  3. 中间不能有其它词,不过这个可以通过 slop 配置允许多少个其他词,默认是 0 个。

例如下例中:搜索词 xiao mi 会被分词成 xiaomi 两个单词。这两个单词去 name 的分词中搜索,如果 name 中有个 xiao mi 既可以被匹配上,如果 name 是 xiao x mi 就不能匹配上,因为中间有其他干扰词语。

GET index_test/_search
{
  "query":{
    "match_phrase": {
      "name": "xiao mi"    
    }
  }
}

可以通过 slop 参数配置干扰词的数量,例如下例中,slop=1,这样 name 是 xiao x mi 就能匹配上了

GET index_test/_search
{
  "query":{
    "match_phrase": {
      "name": {
        "query": "小米手机",
        "slop": 1
      }
    }
  }
}

term

一般用于精确查询

  1. 不会对搜索词进行分词,会保留搜索词的所有属性,包括大小写,标点符号等。
  2. 被搜索字段一般是子字段 keyword(text 类型一般都有子字段,叫做 keyword,记录着原始信息,不过文本内容如果太长的话,就会忽略,导致搜索不到),或者其他不分词的字段
  3. 被搜索是可以分词的字段也是可以,需要和分词结果匹配上就行

下面例子中,Xiao mi shou ji 会作为整体去匹配,name 必须也是 Xiao mi shou ji 才可以被匹配上

GET index_test/_search
{
  "query":{
    "term": {
      "name.keyword": {
        "value": "Xiao mi shou ji"
      }
    }
  }
}

如果想要一次搜索多个词,可以用 terms

GET index_test/_search
{
  "query":{
    "terms": {
      "name.keyword": ["xiao mi shou ji","hua wei shou ji"]
    }
  }
}

range

只支持大于,大于等于,小于,小于等于

GET index_test/_search
{
  "query":{
    "range": {
        "age":{
            "gte":10,
            "lte":20
        }
    }
  }
}

bool 组合

组合查询,就是多条件查询,bool 里的每个条件自己是 and 关系。

must

must 查询,定义多个必须同时满足的条件

GET index_test/_search
{
 "_source":fase, // 关掉
  "query":{
    "bool": {
      "must": [
        // 多个条件必须同时满足
        {
          "match": {
            "FIELD": "TEXT"
          },
          "match_phrase": {
            "FIELD": "PHRASE"
          }
        }
      ]
    }
  }
}

filter

filter 和 must 是一样的,只是会缓存,没有计算评分排序,如果不需要排序,用这个会快一点

GET index_test/_search
{
  "query":{
    "bool": {
      "filter": [
        {
          "match": {
            "name": "小米"
          },
          "range": {
            "price": {
              "lte": 20
            }
          }
        }
      ]
    }
  }
}

should

should 子句,和 or 有点类型,但是不等价

GET index_test/_search
{
  "query":{
    "bool": {
      "should": [
        {
          "match": {
            "name": "小米"
          },
          "range": {
            "price": {
              "lte": 20
            }
          }
        }
      ],
      "minimum_should_match": 1 // should 条件应该满足的个数,默认就是1
    }
  }
}

must not

must not,子条件都不能满足,但凡满足一个都不行

GET index_test/_search
{
  "query":{
    "bool": {
      "must_not": [
        {
          "match": {
            "name": "小米"
          },
          "range": {
            "price": {
              "lte": 20
            }
          }
        }
      ]
    }
  }
}

嵌套子查询

嵌套子查询,需要再加上 bool。

下例中:name != iphone AND ((name = phone AND price <= 20) OR (type = phone AND brand IN ("苹果","华为")))

{
    "query": {
        "bool": {
            "must_not": [
                {
                    "match": {
                        "name": "iphone"
                    }
                }
            ],
            "should": [
                {
                    "bool": {
                        "must": [
                            {
                                "match": {
                                    "name": "phone"
                                }
                            },
                            {
                                "range": {
                                    "price": {
                                        "lte": 20
                                    }
                                }
                            }
                        ]
                    }
                },
                {
                    "bool": {
                        "must": [
                            {
                                "match": {
                                    "type": "phone"
                                }
                            },
                            {
                                "terms": {
                                    "brand.keywords": [
                                        "华为",
                                        "苹果"
                                    ]
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
}

索引操作

因为,新增文档的时候,如果索引不存在也会自动创建,没有必要特意创建,了解就行

创建索引 index_test,请求体 body 可以没有。

PUT index_test
{
  "settings":{
    "number_of_shards":1,// 主分片数量
    "number_of_replicas":1 // 每个主分片的副本分片数量
  }
}

修改索引 index_test

PUT index_test/_settings
{
  "number_of_shards":1
}

删除索引,这个操作要小心

DELETE index_test

新增文档

创建数据,1 是文档 id,如果已经存在就会报错

PUT index_test/_doc/1?op_type=create
{
  "name":"手机",
  "content":"小米"
}

等效 _create api


PUT index_test/_create/2
{
  "name":"手机",
  "content":"小米"
}

如果 id 已经存在,希望更新的话,可以使用 index,这个更新是覆盖掉原来的内容

PUT index_test/_doc/1?op_type=index
{
  "name":"手机1",
  "content":"小米"
}

// 不加op_type=index 也一样
PUT index_test/_doc/1
{
  "name":"手机1",
  "content":"小米"
}

创建文档的时候,不指定 id,系统自动生成 uuid

POST index_test/_doc/
{
  "name":"手机1",
  "content":"小米"
}

批量创建,使用 bulk 接口,批量创建,注意不能格式化,必须一行是命令,下一行是数据,中间不能有换行和空格。

POST /_bulk
{"create":{"_index":"index_test","_id":5}} // 命令
{"name":"手机5","content":"123"} // 数据
{"create":{"_index":"index_test","_id":6}}
{"name":"手机6","content":"123"}
{"create":{"_index":"index_test","_id":7}}
{"name":"手机7","content":"123"}

// 已经存在的不报错
POST /_bulk
{"index":{"_index":"index_test","_id":5}}
{"name":"手机5","content":"123"}
{"index":{"_index":"index_test","_id":6}}
{"name":"手机6","content":"123"}
{"index":{"_index":"index_test","_id":7}}
{"name":"手机7","content":"123"}

删除文档

删除的时候,要加上文档 id

DELETE index_test/_doc/DE7BEo0BngUdM_im08lv

批量删除

POST /_bulk
{"delete":{"_index":"index_test","_id":5}}
{"delete":{"_index":"index_test","_id":6}}

通过条件删除

POST /index_test/_delete_by_query
{
  "query":{
    "term": {
      "price": 500
    }
  }
}

更新文档

更新 name 字段,这个时候要加上 doc 属性,如果有多个字段,就把相应的字段新增上去就很

POST index_test/_update/1
{
  "doc":{
    "name":"手机1"
  }
}

批量更新

POST /_bulk
{"update":{"_index":"index_test","_id":5}}
{"doc":{"name":"手机55"}}
{"update":{"_index":"index_test","_id":6}}
{"doc":{"name":"手机66"}}

mapping 操作

mapping 相当于 mysql 的表结构,定义索引的了 es 的数据结构等信息

GET index_test/_mapping

es 的字段可以有多个类型,如果是文本类型,系统默认会创建一个 keword 类型,字段名称就叫做 keword

  1. text 类型,字段内容会被分词,不会区服大小写
  2. keword 类型,不会被分词,用于精确查询,会区分大小写,字段太长的时候会被忽略会搜索不到
  3. nested 类型,字段是个 json 对象,或者是个数组里嵌套对象,这种比较复杂的类型
{
  "index_test": {
    "mappings": {
      "properties": {
        "content": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "name": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "price": {
          "type": "long"
        }
      }
    }
  }
}

不像 mysql 使用表之前,需要先定义好表结构,es 添加数据的时候,可以新增字段,会自动传教 mapping,es 会更加值类型,创建相应的字段类型

PUT index_test/_create/10
{
  "name":"手机",
  "content":"小米2",
  "price":500 // 例如此时没有price字段
}

虽然 mapping 可以自动创建,不过最好手动创建,只能创建索引的时候设置好,后面很多参数都不允许修改

PUT index_test1
{
  "mappings":{
    "properties":{
      "long_field":{
        "type":"long"
      }
    }
  }
}

测试分词

查看分词结果

GET index_test/_analyze
{
  "text":["华为mate"]
}
0

评论 (0)

取消