首页 > 技术文章 > ElasticSearch获取文档

wysxr 2021-04-08 09:23 原文

GET一个文档

Elasticsearch是功能非常强大的全文搜索引擎,用它的目的就是为了能快速的查询你想要的数据

  • 基本查询:利用Elasticsearch内置查询条件进行查询

  • 组合查询:把多个基本查询组合在一起的复合性查询

  • 过滤:查询同时,通过filter条件在不影响查询的情况下筛选出想要的数据

根据员工id查询

Es 中提供了 GET API 来查看存储在 es 中的文档。使用方式如下:

GET blog/_doc/RuWrl3UByGJWB5WucKtP

上面这个命令表示获取一个 id 为 RuWrl3UByGJWB5WucKtP 的文档。

如果获取不存在的文档,会返回如下信息:

GET blog/_doc/23423421
{
  "_index" : "blog",
  "_type" : "_doc",
  "_id" : "2",
  "found" : false
}

curl -XGET http://10.135.73.73:9201/test/user/1

如果仅仅只是想探测某一个文档是否存在,可以使用 head 请求:

HEAD blog/_doc/1

如果文档存在,返回HTTP 200

HEAD blog/_doc/1
# 结果
200 - OK

如果文档不存在,返回HTTP 404

HEAD blog/_doc/2
# 结果
{"statusCode":404,"error":"Not Found","message":"404 - Not Found"}

当然也可以批量获取文档。

GET blog/_mget
{
  "ids":["1","2"]  # id为 1 和 2 的文档
}

这里可能有小伙伴有疑问,GET 请求竟然可以携带请求体?

某些特定的语言,例如 JavaScript 的 HTTP 请求库是不允许 GET 请求有请求体的,实际上在 RFC7231 文档中,并没有规定 GET 请求的请求体该如何处理,这样造成了一定程度的混乱,有的 HTTP 服务器支持 GET 请求携带请求体,有的 HTTP 服务器则不支持。虽然 es 工程师倾向于使用 GET 做查询,但是为了保证兼容性,es 同时也支持使用 POST 查询。例如上面的批量查询案例,也可以使用 POST 请求。

POST blog/_mget
{
  "ids":["1","2"]  # id为 1 和 2 的文档
}

在任意的查询字符串中添加pretty参数, es可以得到易于识别的json结果。

检索文档中的一部分, 如果只需要显示指定字段

curl -XGET 'http://master:9200/test/user/1?_source=name&pretty'

查询指定索引库指定类型所有数据

curl -XGET 'http://10.135.73.73:9201/test/user/_search?pretty'

使用kibana的Dev Tools

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

GET _cat/indices?v

GET /test/user/_search?pretty

根据条件进行查询

基本查询

指定index名以及type名的搜索

curl -XGET 'http://master:9200/test/user/_search?q=name:john&pretty=true'
或者
curl -XGET 'http://master:9200/test/user/_search?q=name:john&pretty'

指定index名没有type名的搜索

curl -XGET 'http://10.135.73.73:9201/test/_search?q=name:liqiushui&pretty'

既没有index名也没有type名的搜索

curl -XGET 'http://10.135.73.73:9201/_search?q=name:liqiushui&pretty' 

复杂操作搜索 select(排序、分页、高亮、模糊查询、精准查询)

  • 返回版本号_version
  • prefix前缀匹配查询
  • wildcard通配符查询
  • fuzzy模糊插叙
  • more_like_this & more_like_this_field查询

分页 from,size

from:数据开始位置
size:返回数据条数

GET test/user/_search
{
    "query": {
        "match": {
            "name": "雪中"
        }
    },
    "sort": [
       {
           "age": {
               "order": "desc"
           }
       }
    ],
    "from": 0,
    "size": 20
}

match查询

hits:

  • 索引和文档的信息
  • 查询的结果总数
  • 然后就是查询出来的具体的文档
  • 数据中的东西都可以遍历出来
  • 我们可以通过分数(_score)来判断谁更加符合结果
GET test/user/_search
{
    "query": {
        "match": {
            "name": "雪中"
        }
    },
    "_source": ["name","desc"] #结果的过滤,只显示名字和描述
}

排序

  • 以年龄排序
  • desc 降序
  • asc 升序
GET test/user/_search
{
    "query": {
        "match": {
            "name": "雪中"
        }
    },
    "sort": [
       {
           "age": {
               "order": "desc"
           }
       }
    ]
}

布尔值( bool)查询

多条件查询,must(and),所有的条件都要符合,相当于 where id = 3 and name = "雪中"

GET test/user/_search
{
    "query": {
        "bool": {
            "must": [
              {
                  "match": {
                      "name": "雪中"
                  }
              },
              {
                  "match": {
                      "age": 3
                  }
              }
            ]
        }
    }
}

should(or),相当于 where id = 3 or name = "雪中"

GET test/user/_search
{
    "query": {
        "bool": {
            "should": [
              {
                  "match": {
                      "name": "雪中"
                  }
              },
              {
                  "match": {
                      "age": 3
                  }
              }
            ]
        }
    }
}

must_not(not):不包含
查询名字不是 "雪中" 的数据

GET test/user/_search
{
    "query": {
        "bool": {
            "must_not": [
              {
                  "match": {
                      "name": "雪中"
                  }
              }
            ]
        }
    }
}

过滤器 filter ;范围查询 range

查询名字带有"雪中",并且小于10岁的信息

  • gt 大于
  • gte 大于等于
  • lt 小于
  • lte 小于等于
GET test/user/_search
{
    "query": {
        "bool": {
            "must": [
              {
                  "match": {
                      "name": "雪中"
                  }
              }
            ],
            "filter": {
                "range": {
                    "age": {
                        "lt": 10
                    }
                }
            }
        }
    }
}

区间查询
大于 10 岁小于 20 岁

GET test/user/_search
{
    "query": {
        "bool": {
            "must": [
              {
                  "match": {
                      "name": "雪中"
                  }
              }
            ],
            "filter": {
                "range": {
                    "age": {
                        "gte": 10,
                        "lte": 20
                    }
                }
            }
        }
    }
}

匹配多个条件

多个条件使用空格隔开,只要满足其中一个结果就可以查出,这个时候可以通过分值(_score)判断

GET test/user/_search
{
    "query": {
       "match": {
           "tags": "男 技术"  # tags 是字段名
       }
    }
}

精确查询

term 查询是直接通过倒排索引指定的词条进行精确查找的

关于分词

  • term:直接查询精确的,精确查询的时候会遇到分词器,分词器有两种情况,一种是会被分词器解析,一种是不会被分词器解析
  • match:会使用分词器解析(先分析文档,然后再通过分析的文档进行查询)

两个类型

  • text:可以被分词器解析
  • keyword:不会被分词器解析
# 创建索引(库)
PUT testdb
{
    "mappings": {
        "properties": {
            "name": {
                "type": "text"
            },
            "desc": {
                "type": "keyword"
            }
        }
    }
}

# 增加数据
PUT testdb/_doc/1
{
    "name": "雪中悍刀行name",
    "desc": "雪中悍刀行desc"
}
PUT testdb/_doc/2
{
    "name": "雪中悍刀行",
    "desc": "雪中悍刀行desc2"
}

# 查出了两条带有"雪中"的数据,因为 text 可以被分词器解析
GET testdb/_search
{
    "query": {
        "term": {
            "name": "雪中"  
        }
    }
}

# 只能查出一条"雪中悍刀行desc",无法查出"雪中悍刀行desc2",因为 keyword 类型的字段不会被分词器解析
GET testdb/_search
{
    "query": {
        "term": {
            "desc": "雪中悍刀行desc"
        }
    }
}

# 没有被拆分,被当作了一个整体
GET _analyze
{
    "analyzer": "keyword",
    "text": "雪中悍刀行name"
}

# 可以查看被拆分了
GET _analyze
{
    "analyzer": "standard",
    "text": "雪中悍刀行name"
}

多个值匹配的精确查询

# 添加数据
PUT testdb/_doc/3
{
    "t1": "22",
    "t2": "2020-12-10"
}
PUT testdb/_doc/4
{
    "t1": "33",
    "t2": "2020-12-11"
}
# 查询
GET testdb/_search
{
    "query": {
        "bool": {
            "should": [
              {
                "term": {
                    "t1": "22"
                }
              },
              {
                "term": {
                    "t1": "33"
                }
              }
            ]
        }
    }
}

高亮查询

name字段高亮
pre_tags 和 post_tags:自定义高亮条件

GET test/user/_search
{
    "query": {
        "match": {
            "name": "雪中"
        }
    },
    "highlight": {
        "pre_tags": "<p class='key' style='color:red'>",
        "post_tags": "</p>",
        "fields": {
            "name": {}
        }
    }
}

使用kibana的Dev Tools

GET /test/user/_search?q=name:liqiushui&pretty=true

HEAD的使用

如果只想检查一下文档是否存在, 你可以使用HEAD来替代GET方法, 这样就只会返回HTTP头文件

curl -i -XHEAD http://10.135.73.73:9201/test/user/1

推荐阅读