elasticsearch · 4 6 月, 2021 0

elasticsearch 搜索基本概念与入门操作

elasticsearch 搜索提供了多种查询数据的方式,例如 query string 以及_search方式,方便我们根据不同的需求查询数据,同时在查询参数中,可以指定结果的算分策略,能够的到更加符合需求的结果。本文主要从使用方式出发,介绍查询的基础用法

Search API

  • URI Search

    • 在URL 中使用查询参数

  • Request Body Search

    • 使用ES提供的,基于JSON格式的更加完备的(Query Domain Specific Language DSL)

指定查询索引

语法 范围
/_search 集群上所有的索引
/index1/_search index1索引上的查询
/index1, index2/_search index1和index2上的查询
/index*/_search 以index开头的索引

URI查询

  • 使用”q”,指定查询字符

  • “query string syntax”, KV键值对

  • df: 默认字段,不指定时,会对所有字段进行查询

  • Sort排序

  • fromsize用于分页

  • Profile可以查看查询是如何被执行

http://localhost:9200/index1/_search?q=field:value&def=title&sort=year:desc&from=O&size=10&timeout=1s
{"profile": true}

Query String Syntax

  • 指定字段 VS 泛查询

    • 指定字段查询: q = title:2012

    • 范查询:q=2012

    • 泛查询会查询所有的字段,这时会降低查询的性能。

  • Term VS Phrase

    • Beautifu Mind 等效于Beautiful OR Mind

    • Beautiful Mind“等效于 Beautiful AND Mind, Phrase 查询,还要求前后顺序保持一致

  • 分组与引号

    • 分组使用:title: (Beautiful and Mind), 使用Bool查询

    • 引号: “Beautiful Mind”, 使用Phrase查询

  • 布尔操作

    • AND / OR / NOT 或者 && / || / !

      • 必须大写

      • title: (matrx NOT reloaded)

  • 分组

    • +表示 must

    • -表示 must_not

    • title: (+matrix -reloaded)

  • 范围查询

    • 区间表示:[]闭区间, {}开区间

      • year: {2019 TO 2018}

      • year: [* TO 2018]

  • 算数符号

    • year: > 2010

    • year: (>2010 && <= 2018)

    • year: (+>2010 +<2018)

  • 通配符查询 (通配符查询效率低,占用内存大,不建议使用, 特别放在最前面)

    • ?代表1个字符,*代表0或多个字符

      • title: mi?d

      • title: be*

  • 正则表达式

    • title: [bt]oy

  • 模糊匹配与近似查询

    • title: befutifl~1

    • title: “lord rings” ~ 2 // 中间相隔的字符位置

GET /movies/_search?q=2012&df=title
{
"profile": "true"
}
​
# 发查询,针对_all ,所有字段
GET /movies/_search?q=2012
{
"profile": "true"
}
​
# 指定字段
GET /movies/_search?q=title:2012
{
"profile": "true"
}
​
# 使用引号, Phrase 查询
GET /movies/_search?q=title:"Beautiful Mind"
{
"profile": "true"
}
​
# 使用引号, Mind 为泛查询
GET /movies/_search?q=title:Beautiful Mind
{
"profile": "true"
}
​
# 使用引号, Bool 查询
GET /movies/_search?q=title:(Beautiful Mind)
{
"profile": "true"
}
​
# 查找美丽心灵
GET /movies/_search?q=title:(Beautiful AND Mind)
{
"profile": "true"
}
​
# 查找美丽心灵
GET /movies/_search?q=title:(Beautiful NOT Mind)
{
"profile": "true"
}
​
GET /movies/_search?q=title:(Beautiful %2bMind)
{
"profile": "true"
}
GET /movies/_search?q=year:>=1980
{
"profile": "true"
}
​
​
# 通配符查询
GET /movies/_search?q=title:b*
{
"profile": "true"
}
​
# 模糊匹配&近似度匹配
GET /movies/_search?q=title:beautifl~1
{
"profile": "true"
}
​
# 模糊匹配&近似度匹配
GET /movies/_search?q=title:"Lord Rings"~2
{
"profile": "true"
}

Request Body查询

  • 支持POSTGET

  • 需要指定操作索引名

  • 需要执行的操作类型

  • 指定操作类型

  • 分页

    • From从0开始,默认返回10个结果

    • 获取靠后的翻页成本较高

  • 排序

    • 最好在数字型日期型字段上排序

    • 因为对于多值类型或分析过的字段排序,系统会选定一个,无法的值该值

  • _source filtering

    • 如果_source没有存储,那就只返回匹配的文档的元数据

    • _source支持使用通配符

      • _source[“name*“, “desc*“]

  • 脚本字段

    • 通过自定义执行脚本,返回需要的值

  • Match 表达式

    • 根据字段查询 : "comment": "Last Christmas"

    • 执行AND查询操作

    • 短语搜索 – Match Phrase

curl -XGET
"http://localhost:9200/movies/_search" -H
'Content-type:application/json' -d
'{
"form": 10, // 分页参数
"size": 20,
"sort": [{"order_date":"desc"}],
"_source": ["order_date", "order_date", "category.keyword"]
   "query": {
       "match_all": {} // 匹配所有
       "match": {
      "comment": "Last Christmas"
      },
       "match": {
      "comment": {
      "query": "Last Christmas",
      "operator": "AND"
      }
      },
       "match_phrase": { // 短语搜索
      "comment": {
      "query": "Song Last Christmas",
      "slop": "1" // 中间可以有其他的字符
      }
      }
  },
   "script_fields":{
       "new_field": {
       "script": {
           "lang": "painless",
           "source": "doc['order_date'].value + 'hello'"
          }
      }
  }
}'

 

执行实例

# 对日期排序
POST kibana_sample_data_ecommerce/_search
{
"sort": [{"order_date": "desc"}],
"query": {
  "match_all": {}
}
}
​
# source filtering
POST kibana_sample_data_ecommerce/_search
{
"sort": [{"order_date": "desc"}],
"_source": ["order_date"],
"query": {
  "match_all": {}
}
}
​
# source filtering
POST kibana_sample_data_ecommerce/_search
{
"sort": [{"order_date": "desc"}],
"_source": ["order_date"],
"query": {
  "match_all": {}
}
}
​
# 脚本字段
POST kibana_sample_data_ecommerce/_search
{
"sort": [{"order_date": "desc"}],
"_source": ["order_date"],
"query": {
  "match_all": {}
},
"script_fields":{
  "new_field": {
  "script": {
  "lang": "painless",
  "source": "doc['order_date'].value + '_hello'"
  }
  }
  }
}
​
# 匹配Or关系
POST movies/_search
{
"query": {
  "match": {
    "title": "Last Christmas"
  }
}
}
​
# 匹配AND关系
POST movies/_search
{
"query": {
  "match": {
    "title": {
      "query": "Last Christmas",
      "operator": "and"
    }
  }
}
}
​
POST movies/_search
{
"query": {
  "match_phrase": {
    "title": {
      "query": "one love"
      }
    }
}
}
​
POST movies/_search
{
"query": {
  "match_phrase": {
    "title": {
      "query": "one love",
      "slop": 1
      }
    }
}
}

响应对象

{
 "took" : 4, // 花费时间
 "timed_out" : false,
 "_shards" : {
   "total" : 1,
   "successful" : 1,
   "skipped" : 0,
   "failed" : 0
},
 "hits" : {
   "total" : {
     "value" : 10000, // 符合条件的文档总数
     "relation" : "gte"
  },
   "max_score" : 1.0,
   "hits" : [ // 结果集
    {
       "_index" : "movies", // 索引名
       "_type" : "_doc",
       "_id" : "2716", // 文档ID
       "_score" : 1.0, //相关度评分
       "_source" : { // 原始文档信息
         "title" : "Ghostbusters",
         "id" : "2716",
         "@version" : "1",
         "genre" : [
           "Action",
           "Comedy",
           "Sci-Fi"
        ],
         "year" : 0
      }
    },
    {
       "_index" : "movies",
       "_type" : "_doc",
       "_id" : "2717",
       "_score" : 1.0,
       "_source" : {
         "title" : "Ghostbusters II",
         "id" : "2717",
         "@version" : "1",
         "genre" : [
           "Comedy",
           "Fantasy",
           "Sci-Fi"
        ],
         "year" : 1989
      }
    },
    {
       "_index" : "movies",
       "_type" : "_doc",
       "_id" : "2718",
       "_score" : 1.0,
       "_source" : {
         "title" : "Drop Dead Gorgeous",
         "id" : "2718",
         "@version" : "1",
         "genre" : [
           "Comedy"
        ],
         "year" : 1999
      }
    },
    {
       "_index" : "movies",
       "_type" : "_doc",
       "_id" : "2719",
       "_score" : 1.0,
       "_source" : {
         "title" : "Haunting, The",
         "id" : "2719",
         "@version" : "1",
         "genre" : [
           "Horror",
           "Thriller"
        ],
         "year" : 1999
      }
    },
    {
       "_index" : "movies",
       "_type" : "_doc",
       "_id" : "2720",
       "_score" : 1.0,
       "_source" : {
         "title" : "Inspector Gadget",
         "id" : "2720",
         "@version" : "1",
         "genre" : [
           "Action",
           "Adventure",
           "Children",
           "Comedy"
        ],
         "year" : 1999
      }
    },
    {
       "_index" : "movies",
       "_type" : "_doc",
       "_id" : "2721",
       "_score" : 1.0,
       "_source" : {
         "title" : "Trick",
         "id" : "2721",
         "@version" : "1",
         "genre" : [
           "Comedy",
           "Romance"
        ],
         "year" : 1999
      }
    },
    {
       "_index" : "movies",
       "_type" : "_doc",
       "_id" : "2722",
       "_score" : 1.0,
       "_source" : {
         "title" : "Deep Blue Sea",
         "id" : "2722",
         "@version" : "1",
         "genre" : [
           "Action",
           "Horror",
           "Sci-Fi",
           "Thriller"
        ],
         "year" : 1999
      }
    },
    {
       "_index" : "movies",
       "_type" : "_doc",
       "_id" : "2723",
       "_score" : 1.0,
       "_source" : {
         "title" : "Mystery Men",
         "id" : "2723",
         "@version" : "1",
         "genre" : [
           "Action",
           "Comedy",
           "Fantasy"
        ],
         "year" : 1999
      }
    },
    {
       "_index" : "movies",
       "_type" : "_doc",
       "_id" : "2724",
       "_score" : 1.0,
       "_source" : {
         "title" : "Runaway Bride",
         "id" : "2724",
         "@version" : "1",
         "genre" : [
           "Comedy",
           "Romance"
        ],
         "year" : 1999
      }
    },
    {
       "_index" : "movies",
       "_type" : "_doc",
       "_id" : "2725",
       "_score" : 1.0,
       "_source" : {
         "title" : "Twin Falls Idaho",
         "id" : "2725",
         "@version" : "1",
         "genre" : [
           "Drama"
        ],
         "year" : 1999
      }
    }
  ]
}
}
​

Query String Query

  • 类似Query String, 但是会忽略错误的语法,同事支持部分查询语法

  • Simple Query

    • 不支持 AND, OR, NOT , 会当做字符串处理

    • Term 之间默认关系是OR, 可以指定Operator

    • 支持部分逻辑

      • +替代AND

      • |替代OR

      • -替代NOT

POST movies/_search
{
"query": {
  "query_string": {
    "default_field": "name",
    "query":"Bob And Liu"
    }
}
}
​
POST movies/_search
{
"query": {
  "query_string": {
    "fields": ["name", "about"],
    "query":"(Bob And Liu) OR (Java AND Elasticsearch)"
    }
}
}
​
PUT /users/_doc/2
{
"name": "Bob Liu",
"about": "Hadoop"
}
​
POST /users/_search
{
"query": {
  "query_string": {
    "default_field": "name",
    "query": "Bob AND Liu"
  }
}
}
​
POST /users/_search
{
"query": {
  "query_string": {
    "default_field": "name",
    "query": "(Bob AND Liu) OR (Java AND Elasticsearch)"
  }
}
}
​
# Simple Query 默认的operator 是 Or
POST /users/_search
{
"query": {
  "simple_query_string": {
    "fields": ["name"],
    "query": "Bob AND Liu"
  }
}
}
​
POST /users/_search
{
"query": {
  "simple_query_string": { // simple 处理方式不一行
    "fields": ["name"],
    "query": "Bob Liu",
    "default_operator": "AND"
  }
}
}

搜索相关性

  • 搜索是用户和搜索引擎的对话

  • 用户关心的是搜索结果的相关性

    • 是否可以找到相关所有的内容

    • 返回不相关内容的数量

    • 文档打分是否合理

    • 结合业务需求,平衡结果排名