Elasticsearch
参考文档
启动elasticsearch
运行 elasticsearch/bin/elasticsearch.sh
(windows环境)
浏览器访问 http://127.0.0.1:9200/ 可以看到如下响应
{
"name" : "DESKTOP-31RVD33",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "gYdR1ZuyQ5WXtJHZdGKuOA",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
安装head插件
elasticsearch-head下载
git clone https://github.com/mobz/elasticsearch-head.git
安装
cnpm install
运行
npm run start
浏览器访问 http://localhost:9100/
elasticsearch跨域问题
在 elasticsearch/config/elasticsearch.yml
中添加
http.cors.enabled: true
http.cors.allow-origin: "*"
kibana修改为中文
在 kibana/config/kibana.yml
中修改
i18n.locale: "zh-CN"
启动kibana
运行 kibana/bin/kibana.bat
IK分词器
IK提供两种分词算法 ik_smart
和 ik_max_word
ik_smart
最少切分
ik_max_word
最细粒度划分
GET _analyze
{
"analyzer": "ik_smart",
"text": "我喜欢使用elasticsearch做搜索引擎"
}
{
"tokens" : [
{
"token" : "我",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "喜欢",
"start_offset" : 1,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "使用",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "elasticsearch",
"start_offset" : 5,
"end_offset" : 18,
"type" : "ENGLISH",
"position" : 3
},
{
"token" : "做",
"start_offset" : 18,
"end_offset" : 19,
"type" : "CN_CHAR",
"position" : 4
},
{
"token" : "搜索引擎",
"start_offset" : 19,
"end_offset" : 23,
"type" : "CN_WORD",
"position" : 5
}
]
}
GET _analyze
{
"analyzer": "ik_max_word",
"text": "我喜欢使用elasticsearch做搜索引擎"
}
{
"tokens" : [
{
"token" : "我",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "喜欢",
"start_offset" : 1,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "使用",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "elasticsearch",
"start_offset" : 5,
"end_offset" : 18,
"type" : "ENGLISH",
"position" : 3
},
{
"token" : "做",
"start_offset" : 18,
"end_offset" : 19,
"type" : "CN_CHAR",
"position" : 4
},
{
"token" : "搜索引擎",
"start_offset" : 19,
"end_offset" : 23,
"type" : "CN_WORD",
"position" : 5
},
{
"token" : "搜索",
"start_offset" : 19,
"end_offset" : 21,
"type" : "CN_WORD",
"position" : 6
},
{
"token" : "索引",
"start_offset" : 20,
"end_offset" : 22,
"type" : "CN_WORD",
"position" : 7
},
{
"token" : "引擎",
"start_offset" : 21,
"end_offset" : 23,
"type" : "CN_WORD",
"position" : 8
}
]
}
创建自己的词
编辑 elasticsearch-7.6.2\plugins\ik\config\IKAnalyzer.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">my.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
新建my.dic, 里面配置自己的词
my.dic
王哈哈
奥利给
重启 es
GET _analyze
{
"analyzer": "ik_smart",
"text": "王哈哈说了句奥利给"
}
{
"tokens" : [
{
"token" : "王哈哈",
"start_offset" : 0,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "说了",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "句",
"start_offset" : 5,
"end_offset" : 6,
"type" : "CN_CHAR",
"position" : 2
},
{
"token" : "奥利给",
"start_offset" : 6,
"end_offset" : 9,
"type" : "CN_WORD",
"position" : 3
}
]
}
GET _analyze
{
"analyzer": "ik_max_word",
"text": "王哈哈说了句奥利给"
}
{
"tokens" : [
{
"token" : "王哈哈",
"start_offset" : 0,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "哈哈",
"start_offset" : 1,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "说了",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "句",
"start_offset" : 5,
"end_offset" : 6,
"type" : "CN_CHAR",
"position" : 3
},
{
"token" : "奥利给",
"start_offset" : 6,
"end_offset" : 9,
"type" : "CN_WORD",
"position" : 4
}
]
}
Restful风格
Method | URL | 描述 |
---|---|---|
PUT | localhost:9200/索引名称/类型名称/文档id | 创建文档(指定文档id) |
POST | localhost:9200/索引名称/类型名称 | 创建文档(随机文档id) |
POST | localhost:9200/索引名称/类型名称/文档id/_update | 修改文档 |
DELETE | localhost:9200/索引名称/类型名称/文档id | 删除文档 |
GET | localhost:9200/索引名称/类型名称/文档id | 查询文档通过文档id |
POST | localhost:9200/索引名称/类型名称/_search | 查询所有数据 |
基本操作
GET _search
{
"query": {
"match_all": {}
}
}
# 使用ik分词器
GET _analyze
{
"analyzer": "ik_smart",
"text": "王哈哈说了句奥利给"
}
GET _analyze
{
"analyzer": "ik_max_word",
"text": "王哈哈说了句奥利给"
}
# 添加数据
PUT /test/test1/1
{
"name": "王哈哈",
"age": 25,
"height": 182,
"weight": 150
}
# 指定类型
PUT /test2
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "long"
},
"birthday": {
"type": "date"
}
}
}
}
# 获取索引信息
GET /test2
# 添加文档
PUT /test3/_doc/1
{
"name": "王哈哈",
"age": 25,
"birthday": "1996-08-15"
}
# 更新数据,如果少写字段的话数据那么那个字段就莫得了
PUT /test3/_doc/1
{
"name": "王哈哈",
"age": 25,
"birthday": "1996-08-15"
}
# 使用POST更新字段
POST /test3/_doc/1/_update
{
"doc": {
"age": 24
}
}
# 获取健康信息
GET _cat/health
GET _cat/indices?v
# 删除索引
DELETE test
DELETE test2
# 删除数据
DELETE /test3/_doc/3
模糊查询(类似sql里面的like)
GET /al_work/_search
{
"query": {
"wildcard": {
"subject_codes": "*0243*"
}
},
"_source": ["subject_codes"],
"size": 200
}
文档的复杂查询
GET _search
{
"query": {
"match_all": {}
}
}
PUT /userinfo/_doc/2
{
"name": "王大炮",
"age": 24
}
POST /userinfo/_doc/1/_update
{
"doc": {
"age": 23
}
}
GET /userinfo
GET /userinfo/_doc/1
GET /userinfo/_doc/_search?q=name:"王哈哈"
GET /userinfo/_doc/_search
{
"query": {
"match": {
"name": "王"
}
}
}
# 只显示某字段(这里只显示name字段)
GET /userinfo/_doc/_search
{
"query": {
"match": {
"name": "王"
}
},
"_source": ["name"]
}
# 排序
GET /userinfo/_doc/_search
{
"query": {
"match": {
"name": "王"
}
},
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
# 分页
GET /userinfo/_doc/_search
{
"query": {
"match": {
"name": "王"
}
},
"sort": [
{
"age": {
"order": "desc"
}
}
],
"from": 0,
"size": 2
}
# 多条件查询(must相当于mysql里面的and)
GET /userinfo/_doc/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "王哈哈"
}
},
{
"match": {
"age": 23
}
}
]
}
}
}
# 多条件查询
GET /al_work/_count
{
"query": {
"bool": {
"must": [
{
"term": {
"publish_flag": "1"
}
}
],
"filter": {
"range": {
"create_date": {
"lt": "2022-02-03"
}
}
}
}
}
}
# 或 should(or)
GET /userinfo/_doc/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"name": "哈哈"
}
},
{
"match": {
"age": 24
}
}
]
}
}
}
# 否定条件
GET /userinfo/_doc/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"age": 24
}
}
]
}
}
}
# 过滤条件 gt大于 lt小于 gte大于等于 lte 小于等于
GET /userinfo/_doc/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "王"
}
}
],
"filter": {
"range": {
"age": {
"lt": 24
}
}
}
}
}
}
# 大于等于1岁小于等于100岁
GET /userinfo/_doc/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "王"
}
}
],
"filter": {
"range": {
"age": {
"gte": 1,
"lte": 100
}
}
}
}
}
}
# 列表数据查询多个条件空格隔开
# 比如 tags ["音乐", "旅游", "学习"]
GET /userinfo/_doc/_serach
{
"query": {
"match": {
"tags": "旅游 学习"
}
}
}
# 精确查询
# term查询是直接经过倒排索引指定的词条进行精确查找的
# 关于分词
# term - 精确查询
# match - 使用分词器解析查询
# 两个类型 text(分词器会解析), keyword(不会解析)
PUT /testdb
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"desc": {
"type": "keyword"
}
}
}
}
PUT /testdb/_doc/1
{
"name": "王哈哈",
"desc": "王哈哈的描述信息"
}
PUT /testdb/_doc/2
{
"name": "迪丽热巴",
"desc": "迪丽热巴的描述信息"
}
GET /testdb/_search
{
"query": {
"term": {
"name": "王"
}
}
}
GET /testdb/_search
{
"query": {
"term": {
"desc": "迪丽热巴的描述信息"
}
}
}
# 精确查询多个值
GET /testdb/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"desc": "王哈哈的描述信息"
}
},
{
"term": {
"desc": "迪丽热巴的描述信息"
}
}
]
}
}
}
高亮查询
# 高亮显示
GET /userinfo/_search
{
"query": {
"match": {
"name": "王"
}
},
"highlight": {
"fields": {
"name": {}
}
}
}
# 自定义高亮标签
GET /userinfo/_search
{
"query": {
"match": {
"name": "王"
}
},
"highlight": {
"pre_tags": "<p class='key' style='color:red'>",
"post_tags": "</p>",
"fields": {
"name": {}
}
}
}
设置最大索引值
PUT /al_work/_settings?pretty
{
"index":{
"max_result_window":1000000000
}
}
golang操作elasticsearch
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"reflect"
"time"
"github.com/olivere/elastic/v7"
)
type Tweet struct {
User string `json:"user"`
Message string `json:"message"`
Retweets int `json:"retweets"`
Image string `json:"image,omitempty"`
Created time.Time `json:"created,omitempty"`
Tags []string `json:"tags,omitempty"`
Location string `json:"location,omitempty"`
Suggest *elastic.SuggestField `json:"suggest_field,omitempty"`
}
func main() {
errorlog := log.New(os.Stdout, "APP ", log.LstdFlags)
// Obtain a client. You can also provide your own HTTP client here.
client, err := elastic.NewClient(elastic.SetErrorLog(errorlog))
// Trace request and response details like this
// client, err := elastic.NewClient(elastic.SetTraceLog(log.New(os.Stdout, "", 0)))
if err != nil {
// Handle error
panic(err)
}
// Ping the Elasticsearch server to get e.g. the version number
info, code, err := client.Ping("http://127.0.0.1:9200").Do(context.Background())
if err != nil {
// Handle error
panic(err)
}
fmt.Printf("Elasticsearch returned with code %d and version %s\n", code, info.Version.Number)
// Getting the ES version number is quite common, so there's a shortcut
esversion, err := client.ElasticsearchVersion("http://127.0.0.1:9200")
if err != nil {
// Handle error
panic(err)
}
fmt.Printf("Elasticsearch version %s\n", esversion)
// Use the IndexExists service to check if a specified index exists.
exists, err := client.IndexExists("twitter").Do(context.Background())
if err != nil {
// Handle error
panic(err)
}
if !exists {
// Create a new index.
mapping := `
{
"settings":{
"number_of_shards":1,
"number_of_replicas":0
},
"mappings":{
"doc":{
"properties":{
"user":{
"type":"keyword"
},
"message":{
"type":"text",
"store": true,
"fielddata": true
},
"retweets":{
"type":"long"
},
"tags":{
"type":"keyword"
},
"location":{
"type":"geo_point"
},
"suggest_field":{
"type":"completion"
}
}
}
}
}
`
createIndex, err := client.CreateIndex("twitter").Body(mapping).IncludeTypeName(true).Do(context.Background())
if err != nil {
// Handle error
panic(err)
}
if !createIndex.Acknowledged {
// Not acknowledged
}
}
// Index a tweet (using JSON serialization)
tweet1 := Tweet{User: "olivere", Message: "Take Five", Retweets: 0}
put1, err := client.Index().
Index("twitter").
Type("doc").
Id("1").
BodyJson(tweet1).
Do(context.Background())
if err != nil {
// Handle error
panic(err)
}
fmt.Printf("Indexed tweet %s to index %s, type %s\n", put1.Id, put1.Index, put1.Type)
// Index a second tweet (by string)
tweet2 := `{"user" : "olivere", "message" : "It's a Raggy Waltz"}`
put2, err := client.Index().
Index("twitter").
Type("doc").
Id("2").
BodyString(tweet2).
Do(context.Background())
if err != nil {
// Handle error
panic(err)
}
fmt.Printf("Indexed tweet %s to index %s, type %s\n", put2.Id, put2.Index, put2.Type)
// Get tweet with specified ID
get1, err := client.Get().
Index("twitter").
Type("doc").
Id("1").
Do(context.Background())
if err != nil {
switch {
case elastic.IsNotFound(err):
panic(fmt.Sprintf("Document not found: %v", err))
case elastic.IsTimeout(err):
panic(fmt.Sprintf("Timeout retrieving document: %v", err))
case elastic.IsConnErr(err):
panic(fmt.Sprintf("Connection problem: %v", err))
default:
// Some other kind of error
panic(err)
}
}
fmt.Printf("Got document %s in version %d from index %s, type %s\n", get1.Id, get1.Version, get1.Index, get1.Type)
// Flush to make sure the documents got written.
_, err = client.Flush().Index("twitter").Do(context.Background())
if err != nil {
panic(err)
}
// Search with a term query
termQuery := elastic.NewTermQuery("user", "olivere")
searchResult, err := client.Search().
Index("twitter"). // search in index "twitter"
Query(termQuery). // specify the query
Sort("user", true). // sort by "user" field, ascending
From(0).Size(10). // take documents 0-9
Pretty(true). // pretty print request and response JSON
Do(context.Background()) // execute
if err != nil {
// Handle error
panic(err)
}
// searchResult is of type SearchResult and returns hits, suggestions,
// and all kinds of other information from Elasticsearch.
fmt.Printf("Query took %d milliseconds\n", searchResult.TookInMillis)
// Each is a convenience function that iterates over hits in a search result.
// It makes sure you don't need to check for nil values in the response.
// However, it ignores errors in serialization. If you want full control
// over iterating the hits, see below.
var ttyp Tweet
for _, item := range searchResult.Each(reflect.TypeOf(ttyp)) {
t := item.(Tweet)
fmt.Printf("Tweet by %s: %s\n", t.User, t.Message)
}
// TotalHits is another convenience function that works even when something goes wrong.
fmt.Printf("Found a total of %d tweets\n", searchResult.TotalHits())
// Here's how you iterate through results with full control over each step.
if searchResult.Hits.TotalHits > 0 {
fmt.Printf("Found a total of %d tweets\n", searchResult.Hits.TotalHits)
// Iterate through results
for _, hit := range searchResult.Hits.Hits {
// hit.Index contains the name of the index
// Deserialize hit.Source into a Tweet (could also be just a map[string]interface{}).
var t Tweet
err := json.Unmarshal(*hit.Source, &t)
if err != nil {
// Deserialization failed
}
// Work with tweet
fmt.Printf("Tweet by %s: %s\n", t.User, t.Message)
}
} else {
// No hits
fmt.Print("Found no tweets\n")
}
// Update a tweet by the update API of Elasticsearch.
// We just increment the number of retweets.
script := elastic.NewScript("ctx._source.retweets += params.num").Param("num", 1)
update, err := client.Update().Index("twitter").Type("doc").Id("1").
Script(script).
Upsert(map[string]interface{}{"retweets": 0}).
Do(context.Background())
if err != nil {
// Handle error
panic(err)
}
fmt.Printf("New version of tweet %q is now %d", update.Id, update.Version)
// ...
// Delete an index.
deleteIndex, err := client.DeleteIndex("twitter").Do(context.Background())
if err != nil {
// Handle error
panic(err)
}
if !deleteIndex.Acknowledged {
// Not acknowledged
}
}
新版
创建索引
创建一个索引名为
shopping
PUT /shopping
返回结果
{ "acknowledged" : true, "shards_acknowledged" : true, "index" : "shopping" }
再次发送创建请求则会报错
{ "error" : { "root_cause" : [ { "type" : "resource_already_exists_exception", "reason" : "index [shopping/aE96nccCSmOXYZG9aUnmyA] already exists", "index_uuid" : "aE96nccCSmOXYZG9aUnmyA", "index" : "shopping" } ], "type" : "resource_already_exists_exception", "reason" : "index [shopping/aE96nccCSmOXYZG9aUnmyA] already exists", "index_uuid" : "aE96nccCSmOXYZG9aUnmyA", "index" : "shopping" }, "status" : 400 }
获取索引信息
GET /shopping
返回结果
{ "shopping" : { "aliases" : { }, "mappings" : { }, "settings" : { "index" : { "routing" : { "allocation" : { "include" : { "_tier_preference" : "data_content" } } }, "number_of_shards" : "1", "provided_name" : "shopping", "creation_date" : "1638604381990", "number_of_replicas" : "1", "uuid" : "aE96nccCSmOXYZG9aUnmyA", "version" : { "created" : "7150299" } } } } }
获取所有索引
GET /_cat/indices
// 查看详细信息可以加 ?v 参数
GET /_cat/indices?v
返回结果
green open .geoip_databases cWErzuSJTe2z4x-SYRy4Aw 1 0 43 38 43.6mb 43.6mb green open .apm-custom-link 0BoeKbRhRCCKFpR7ordtYQ 1 0 0 0 208b 208b green open .apm-agent-configuration B_mZp-gCSXa2EVJbjfj0hQ 1 0 0 0 208b 208b green open .kibana-event-log-7.15.2-000001 iwXccJQCSlyEm5o0fwzu_g 1 0 5 0 23.8kb 23.8kb green open .kibana_7.15.2_001 kCAw_wl8Tkm0tkCtZmXC_g 1 0 34 9 9.3mb 9.3mb yellow open shopping aE96nccCSmOXYZG9aUnmyA 1 1 0 0 208b 208b green open .tasks rsMEEgDXRC61HqKD3yU5qA 1 0 8 0 36.4kb 36.4kb green open .kibana_task_manager_7.15.2_001 sMrOZuqzSwK6Wr6S-LJ58w 1 0 15 2571 431.4kb 431.4kb
删除索引
DELETE /shopping
返回结果
{ "acknowledged" : true }
向索引中添加数据
POST /shopping/_doc
{
"title": "小米手机",
"category": "小米",
"images": "http://xxxxx/xm.jpg",
"price": 3999.00
}
返回结果
{ "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 0, "_primary_term" : 1 }
向索引中添加数据-自定义ID
POST /shopping/_doc/1001
{
"title": "小米手机",
"category": "小米",
"images": "http://xxxxx/xm.jpg",
"price": 3999.00
}
返回结果
{ "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 1, "_primary_term" : 1 }
查询指定ID文档
GET /shopping/_doc/1001
返回结果
{ "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_version" : 2, "_seq_no" : 2, "_primary_term" : 1, "found" : true, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 } }
找不到返回
{ "_index" : "shopping", "_type" : "_doc", "_id" : "1005", "found" : false }
查询指定索引下的全部文档
GET /shopping/_search
返回结果
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_score" : 1.0, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 } }, { "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_score" : 1.0, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 } } ] } }
took
耗费时间(单位毫秒)
timed_out
是否超时
hits
命中的结果
覆盖数据
PUT /shopping/_doc/1001
{
"title" : "黑鲨4Pro",
"category" : "小米",
"price" : 5999.0
}
返回结果
{ "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_version" : 3, "result" : "updated", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 3, "_primary_term" : 1 }
修改数据
POST /shopping/_update/1001
{
"doc": {
"price": 8565.00
}
}
返回结果
{ "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_version" : 4, "result" : "updated", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 4, "_primary_term" : 1 }
删除数据
DELETE /shopping/_doc/1001
返回结果
{ "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_version" : 5, "result" : "deleted", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 5, "_primary_term" : 1 }
条件查询-请求路径的方式
查询
category
字段值为小米
的数据
GET /shopping/_search?q=category:小米
返回结果
{ "took" : 828, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 0.21072102, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_score" : 0.21072102, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 } }, { "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_score" : 0.21072102, "_source" : { "title" : "黑鲨4Pro", "category" : "小米", "price" : 5999.0 } } ] } }
条件查询-请求体的方式
GET /shopping/_search
{
"query": {
"match": {
"category": "小米"
}
}
}
返回结果
{ "took" : 1, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 0.36464313, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_score" : 0.36464313, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 } }, { "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_score" : 0.36464313, "_source" : { "title" : "黑鲨4Pro", "category" : "小米", "price" : 5999.0 } } ] } }
查询全部数据
GET /shopping/_search
{
"query": {
"match_all": {}
}
}
返回结果
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_score" : 1.0, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 } }, { "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_score" : 1.0, "_source" : { "title" : "黑鲨4Pro", "category" : "小米", "price" : 5999.0 } } ] } }
分页查询
GET /shopping/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size":1
}
from
当前页起始位置
size
每页数据条数返回结果
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_score" : 1.0, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 } } ] } }
from
计算方式(页码-1)*size
from = (页码-1) * size
查询结果字段过滤
GET /shopping/_search
{
"query": {
"match_all": {}
},
"_source": ["title"]
}
返回结果
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_score" : 1.0, "_source" : { "title" : "小米手机" } }, { "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_score" : 1.0, "_source" : { "title" : "黑鲨4Pro" } } ] } }
排序
GET /shopping/_search
{
"query": {
"match_all": {}
},
"sort": {
"price": {
"order": "asc"
}
}
}
order
取值asc
升序,desc
降序返回结果
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : null, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_score" : null, "_source" : { "title" : "黑鲨4Pro", "category" : "小米", "price" : 5999.0 }, "sort" : [ 5999.0 ] }, { "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_score" : null, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 }, "sort" : [ 3999.0 ] } ] } }
多条件查询-多个条件同时满足(must)
GET /shopping/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"category": "小米"
}
},
{
"match": {
"price": 5999.00
}
}
]
}
}
}
返回结果
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.3646431, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_score" : 1.3646431, "_source" : { "title" : "黑鲨4Pro", "category" : "小米", "price" : 5999.0 } } ] } }
多条件查询-should(类似or)
GET /shopping/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"category": "小米"
}
},
{
"match": {
"category": "黑鲨4Pro"
}
}
]
}
}
}
返回结果
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 0.36464313, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_score" : 0.36464313, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 } }, { "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_score" : 0.36464313, "_source" : { "title" : "黑鲨4Pro", "category" : "小米", "price" : 5999.0 } } ] } }
范围查询-大于小于-大于等于...
GET /shopping/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"category": "小米"
}
},
{
"match": {
"category": "黑鲨4Pro"
}
}
],
"filter": {
"range": {
"price": {
"gt": 5000
}
}
}
}
}
}
返回结果
{ "took" : 1, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 0.36464313, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_score" : 0.36464313, "_source" : { "title" : "黑鲨4Pro", "category" : "小米", "price" : 5999.0 } } ] } }
精确查询-精确匹配-完全匹配(match_phrase)
这里我们查询小黑,由于分词后可以匹配到"小米","黑鲨",所以是可以查到值的
GET /shopping/_search
{
"query": {
"match": {
"title": "小黑"
}
}
}
返回结果
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 0.7361701, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_score" : 0.7361701, "_source" : { "title" : "黑鲨4Pro", "category" : "小米", "price" : 5999.0 } }, { "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_score" : 0.6548753, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 } } ] } }
改用 match_phrase
GET /shopping/_search
{
"query": {
"match_phrase": {
"title": "小米"
}
}
}
返回结果
{ "took" : 2, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.3097506, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_score" : 1.3097506, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 } } ] } }
高亮显示
GET /shopping/_search
{
"query": {
"match_phrase": {
"title": "小米"
}
},
"highlight": {
"fields": {
"title": {}
}
}
}
返回结果
{ "took" : 33, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.3097506, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_score" : 1.3097506, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 }, "highlight" : { "title" : [ "<em>小</em><em>米</em>手机" ] } } ] } }
聚合查询-分组
# 聚合查询
GET /shopping/_search
{
"aggs": {
"price_group": {
"terms": {
"field": "price"
}
}
}
}
返回结果
{ "took" : 6, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "shopping", "_type" : "_doc", "_id" : "s1B-hH0Bkifry_7pwzKn", "_score" : 1.0, "_source" : { "title" : "小米手机", "category" : "小米", "images" : "http://xxxxx/xm.jpg", "price" : 3999.0 } }, { "_index" : "shopping", "_type" : "_doc", "_id" : "1001", "_score" : 1.0, "_source" : { "title" : "黑鲨4Pro", "category" : "小米", "price" : 5999.0 } } ] }, "aggregations" : { "price_group" : { "doc_count_error_upper_bound" : 0, "sum_other_doc_count" : 0, "buckets" : [ { "key" : 3999.0, "doc_count" : 1 }, { "key" : 5999.0, "doc_count" : 1 } ] } } }
聚合查询-分组-不显示原始数据
GET /shopping/_search
{
"aggs": {
"price_group": {
"terms": {
"field": "price"
}
}
},
"size": 0
}
返回结果
{ "took" : 7, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : null, "hits" : [ ] }, "aggregations" : { "price_group" : { "doc_count_error_upper_bound" : 0, "sum_other_doc_count" : 0, "buckets" : [ { "key" : 3999.0, "doc_count" : 1 }, { "key" : 5999.0, "doc_count" : 1 } ] } } }
聚合查询-平均值
{
"aggs": {
"price_avg": {
"avg": {
"field": "price"
}
}
},
"size": 0
}
返回结果
{ "took" : 1, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : null, "hits" : [ ] }, "aggregations" : { "price_avg" : { "value" : 4999.0 } } }
聚合查询-最大值
GET /shopping/_search
{
"aggs": {
"price_avg": {
"max": {
"field": "price"
}
}
},
"size": 0
}
返回值
{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : null, "hits" : [ ] }, "aggregations" : { "price_avg" : { "value" : 5999.0 } } }
映射
// 创建一个索引
PUT /user
// 映射 mapping
PUT /user/_mapping
{
"properties": {
"name": {
"type": "text",
"index": true
},
"sex": {
"type": "keyword",
"index": true
},
"tel": {
"type": "keyword",
"index": false
}
}
}
type
-
text
可以分词
-
keyword
不能分词,只能完整匹配
-
index
是否可以被索引
返回结果
{ "acknowledged" : true }
查看
mapping
GET /user/_mapping
返回结果
{ "user" : { "mappings" : { "properties" : { "name" : { "type" : "text" }, "sex" : { "type" : "keyword" }, "tel" : { "type" : "keyword", "index" : false } } } } }
操作
// 添加两条数据
POST /user/_doc
{
"name": "张三",
"sex": "男",
"tel": "18300005588"
}
POST /user/_doc
{
"name": "张飞",
"sex": "男的",
"tel": "15800008899"
}
// 查询数据, mapping 是text类型
GET /user/_search
{
"query": {
"match": {
"name": "飞"
}
}
}
GET /user/_search
{
"query": {
"match": {
"name": "张"
}
}
}
// 查询数据, mapping 是keyword类型
GET /user/_search
{
"query": {
"match": {
"sex": "男的"
}
}
}
// index是false 不可被索引, 查询会报错
GET /user/_search
{
"query": {
"match": {
"tel": "18300005588"
}
}
}
查询指定索引数据总量
GET /al_artist/_count
返回结果
{ "count" : 12979, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 } }
Elasticsearch集群部署
节点一
vim elasticsearch.yml
# 集群名称,集群中的每个节点名称必须一样
cluster.name: es
# 该节点有机会成为master节点
node.master: true
# 该节点可以存储数据
node.data: true
# 节点名称,不能重复
node.name: node-1
# 允许所有节点访问
network.host: 0.0.0.0
# http端口
http.port: 9201
# TCP的默认监听端口,默认 9300
transport.tcp.port: 9301
# 候选主节点的设备地址,在开启服务后可以被选为主节点
discovery.seed_hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]
# 初始化一个新的集群时需要此配置来选举master
cluster.initial_master_nodes: ["node-1", "node-2","node-3"]
# 最大集群节点数
node.max_local_storage_nodes: 3
# 跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"
节点二
vim elsticsearch.yml
# 集群名称,集群中的每个节点名称必须一样
cluster.name: es
# 该节点有机会成为master节点
node.master: true
# 该节点可以存储数据
node.data: true
# 节点名称,不能重复
node.name: node-2
# 允许所有节点访问
network.host: 0.0.0.0
# http端口
http.port: 9202
# TCP的默认监听端口,默认 9300
transport.tcp.port: 9302
# 候选主节点的设备地址,在开启服务后可以被选为主节点
discovery.seed_hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]
# 初始化一个新的集群时需要此配置来选举master
cluster.initial_master_nodes: ["node-1", "node-2","node-3"]
# 最大集群节点数
node.max_local_storage_nodes: 3
# 跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"
节点三
vim elsticsearch.yml
# 集群名称,集群中的每个节点名称必须一样
cluster.name: es
# 该节点有机会成为master节点
node.master: true
# 该节点可以存储数据
node.data: true
# 节点名称,不能重复
node.name: node-3
# 允许所有节点访问
network.host: 0.0.0.0
# http端口
http.port: 9203
# TCP的默认监听端口,默认 9300
transport.tcp.port: 9303
# 候选主节点的设备地址,在开启服务后可以被选为主节点
discovery.seed_hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]
# 初始化一个新的集群时需要此配置来选举master
cluster.initial_master_nodes: ["node-1", "node-2","node-3"]
# 最大集群节点数
node.max_local_storage_nodes: 3
# 跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"
查看集群的状态
http://ip:9201/_cluster/health