Elastic Stack:es 搜索入门

Posted wwjj4811

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elastic Stack:es 搜索入门相关的知识,希望对你有一定的参考价值。

一.搜索

搜索所有:

GET /index/_search

 返回结果解释:

took:耗时几毫秒

time_out:是否超时,默认不超时,设置超时时间后,当搜索超时后,停止搜索,并返回已经搜索到的数据。

    配置方法:search.default_search_timeout

_shards:到几个分片搜索,成功几个,跳过几个,失败几个。

hits.total:查询结果的数量

hit.max_score:对搜索的相关度的匹配分数,分数越高,就越匹配

hit.hits:包含搜索结果document的所有详细数据。

传参:

GET /book/_search?q=name:java&sort=price:desc

 相当于oracle中:select * from book where name like ‘%java%‘ order by price desc

多索引搜索:一次性搜索多个index和多个type下的数据

GET /index1,index2/_search:同时搜索两个index下的数据
GET /index*/_search:按照通配符去匹配多个索引

 应用场景:生产环境log索引可以按照日期分开。

  log_201911

    log_201912

    log_202001

二.分页搜索

#从第四条数据开始搜索一页,一页两条
GET /book/_search?from=3&size=2

 deep paging:根据相关度评分倒排序,所以分页过深,协调节点会将大量数据聚合分析。

   deep paging性能低,应该较少使用。

三.query string基础语法

  GET /book/_search?q=name:java 搜索name中包含java关键字的

  GET /book/_search?q=+name:java 搜索name中包含java关键字的

  GET /book/_search?q=-name:java 搜索name中不包含java关键字的

_all metadata:

  GET /book/_search?q=java,直接搜索所有的field,任意一个field包含java,都可以搜索出来。

四.query DSL

DSL:domain specified language 特定领域的语言,es特有的搜索语言,可以在请求体重携带搜索条件。

查询全部:

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

 排序

GET /book/_search 
{
    "query" : {
        "match" : {
            "name" : " java"
        }
    },
    "sort": [
        { "price": "desc" }
    ]
}

分页:

GET  /book/_search 
{
  "query": { "match_all": {} },
  "from": 0,
  "size": 1
}

 指定返回字段:

GET /book/_search 
{
  "query": { "match_all": {} },
  "_source": ["name", "studymodel"]
}

DSL语法:

一.
{ QUERY_NAME: { ARGUMENT: VALUE, ARGUMENT: VALUE,... } } 二.
{ QUERY_NAME: { FIELD_NAME: { ARGUMENT: VALUE, ARGUMENT: VALUE,... } } }

搜索需求:title必须包含elasticsearch,content可以包含elasticsearch也可以不包含,author_id必须不为111 

GET /website/_doc/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": "elasticsearch"
          }
        }
      ],
      "should": [
        {
          "match": {
            "content": "elasticsearch"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "author_id": 111
          }
        }
      ]
    }
  }
}

 全文检索: 

match_all查询全部:

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

  match:全文检索

GET /book/_search
{
	"query": { 
		"match": { 
			"description": "java程序员"
		}
	}
}

 multi_match:在多个属性中去查

GET /book/_search
{
  "query": {
    "multi_match": {
      "query": "java程序员",
      "fields": ["name", "description"]
    }
  }
}

 range_query 范围查询

GET /book/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 80,
	"lte": 90
      }
    }
  }
}

 term: 字段为keyword时,存储和搜索都不分词

例子:查询分词为"java程序员"

GET /book/_search
{
  "query": {
    "term": {
      "description": "java程序员"
    }
  }
}

terms:

例子:同个一个字段中,查询同时包含"search","full_text","nosql"三个分词的文档

GET /book/_search
{
    "query": { "terms": { "tag": [ "search", "full_text", "nosql" ] }}
}

exists:含有某些字段的文档

例子:查询包含price字段的文档

GET /_search
{
    "query": {
        "exists": {
            "field": "price"
        }
    }
}

fuzzy:返回包含与搜索词类似的词的文档,该词由Levenshtein编辑距离度量。 

有一下几种情况:

  • 更改角色(box→fox)

  • 删除字符(aple→apple)

  • 插入字符(sick→sic)

  • 调换两个相邻字符(ACT→CAT)

GET /book/_search
{
    "query": {
        "fuzzy": {
            "description": {
                "value": "jave"
            }
        }
    }
}

ids:根据文档id进行查询

GET /book/_search
{
    "query": {
        "ids" : {
            "values" : ["1", "4", "100"]
        }
    }
}

prefix:前缀查询

GET /book/_search
{
    "query": {
        "prefix": {
            "description": {
                "value": "spring"
            }
        }
    }
}

regexp:正则查询

GET /book/_search
{
    "query": {
        "regexp": {
            "description": {
                "value": "j.*a",
                "flags" : "ALL",
                "max_determinized_states": 10000,
                "rewrite": "constant_score"
            }
        }
    }
}

 五.filter

需求:用户查询description中有"java程序员",并且价格大于80小于90的数据。

filter:对全文检索的结果进行过滤

GET /book/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "description": "java程序员"
          }
        }
      ],
      "filter": {
        "range": {
          "price": {
            "gte": 80,
		     "lte": 90
          }
        }
      }
    }
  }
}

filter与query对比:

  filter,仅仅只是按照搜索条件过滤出需要的数据而已,不计算任何相关度分数,对相关度没有任何影响。

  query,会去计算每个document相对于搜索条件的相关度,并按照相关度进行排序。

  filter,不需要计算相关度分数,不需要按照相关度分数进行排序,同时还有内置的自动cache最常使用filter的数据

  query,相反,要计算相关度分数,按照分数进行排序,而且无法cache结果

当只写"filter",不写" must",就会报错,只过滤的正确写法如下,加上constant_score。

GET /book/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "description": "java"
        }
      }
    }
  }
}
定制排序规则:
GET /book/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "description": "java"
        }
      }
    }
  },
  "sort": [
    {
      "price": {
        "order": "desc"
      }
    }
  ]
}

text field排序问题:

如果对一个text field进行排序,结果往往不准确,因为分词后是多个单词,再排序就不是我们想要的结果了。

通常解决方案是,将一个text field建立两次索引,一个分词,用来进行搜索;一个不分词,用来进行排序。

在创建索引的时候设置:fielddate:true

六.执行计划

一般用在那种特别复杂庞大的搜索下,比如你一下子写了上百行的搜索,这个时候可以先用validate api去验证一下,搜索是否合法。

合法以后,explain就像mysql的执行计划,可以看到搜索的目标等信息。

GET /book/_validate/query?explain
{
    "query": {
        "fuzzy": {
            "description": {
                "value": "jave"
            }
        }
    }
}

技术图片 

七.srcoll分批查询

场景:下载某一个索引中1亿条数据,到文件或是数据库。不能一下全查出来,系统内存溢出。所以使用scoll滚动搜索技术,一批一批查询。

scoll搜索会在第一次搜索的时候,保存一个当时的视图快照,之后只会基于该旧的视图快照提供数据搜索,如果这个期间数据变更,是不会让用户看到的

每次发送scroll请求,我们还需要指定一个scoll参数,指定一个时间窗口,每次搜索请求只要在这个时间窗口内能完成就可以了。

第一次搜索:

GET /book/_search?scroll=1m
{
  "query": {
    "match_all": {}
  },
  "size": 3
}

 返回:

{
  "_scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAMOkWTURBNDUtcjZTVUdKMFp5cXloVElOQQ==",
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
     
    ]
  }
}

 获得的结果会有一个scoll_id,下一次再发送scoll请求的时候,必须带上这个scoll_id

GET /_search/scroll
{
    "scroll": "1m", 
    "scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAMOkWTURBNDUtcjZTVUdKMFp5cXloVElOQQ=="
}

以上是关于Elastic Stack:es 搜索入门的主要内容,如果未能解决你的问题,请参考以下文章

Elastic Stack:es 索引index入门

Elastic Stack:es Mapping映射入门

Elastic Stack:es快速入门&&索引的简单CRUD

Elastic Stack:es快速入门&&索引的简单CRUD

Elastic Stack 入门

ES 集中式日志分析平台 Elastic Stack(介绍)