(番外篇) Elasticsearch入門(mén)

ElasticSesrch入門(mén)

標(biāo)簽(空格分隔):ElasticSearch


撐住

安裝

  • elasticsearch

官網(wǎng)下載地址潦匈,選擇你想要的版本下載點(diǎn)擊這里

<!--jdk版本-->
1.8以上
<!--運(yùn)行-->
\elasticsearch-5.5.3\bin\elasticsearch.bat 
  • elasticsearch-head

github 下載 地址

<!--基礎(chǔ)環(huán)境 -->
nodejs 8.0以上版本
<!--跳轉(zhuǎn)路徑下 -->
cnpm install 
cnpm run start

注意皮胡,由于elasticsearch和elasticsearch-head是兩個(gè)產(chǎn)品懊渡,存在跨域操作扛吞,所以需要在elasticsearch的config路徑下修改yml文件锐墙。

\elasticsearch-5.5.3\config

<!--最后一行添加-->
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-methods: OPTIONS,HEAD,GET,POST,PUT,DELETE
http.cors.allow-headers: "X-Requested-With,Content-Type,Content-Length,X-Use"
運(yùn)行結(jié)果

分布式

  • 集群搭建
<!--主節(jié)點(diǎn)-->
cluster.name: xiaojinzi
node.name: master
node.master:true
network.host: 127.0.0.1

<!--集群節(jié)點(diǎn)-->
<!--復(fù)制一份elasticsearch-->
<!--修改yml參數(shù)-->
cluster.name: xiaojinzi
node.name: slave1
<!--端口設(shè)置-->
network.host: 127.0.0.1
http.port: 8200
<!--集群對(duì)接-->
discovery.zen.ping.unicast.hosts: ["127.0.0.1"]

集群

基礎(chǔ)概念(這里引用之前所寫(xiě)python搭建es)

  • 集群:一個(gè)或多個(gè)節(jié)點(diǎn)組織在一起

  • 節(jié)點(diǎn):一個(gè)節(jié)點(diǎn)是一個(gè)集群中的一個(gè)服務(wù)器,有表示华匾,是漫v的名字

  • 分片:將索引劃分為多份的能力,允許水平分割和擴(kuò)展容量皿哨,多個(gè)分片響應(yīng)請(qǐng)求浅侨,提高性能和吞吐量

  • 副本:數(shù)據(jù)的備份,一個(gè)節(jié)點(diǎn)宕機(jī)证膨,另一個(gè)頂上

    elasticsearch mysql
    index (索引) 數(shù)據(jù)庫(kù)
    type(類(lèi)型)
    document(文檔)
    fields
  • 倒排索引源于實(shí)際應(yīng)用中需要根據(jù)屬性的值來(lái)查找記錄如输。這種索引表中的每一項(xiàng)都包含一個(gè)屬性值和具有該屬性值得各記錄的地址。由于不是由記錄來(lái)確定屬性值央勒,而是由屬性值來(lái)確定記錄的位置不见,因而稱(chēng)為倒排索引,帶有倒排索引的文件我們稱(chēng)為倒排索引文件崔步,簡(jiǎn)稱(chēng)倒排文件稳吮。

  • TF-IDF

基本用法

  • 索引創(chuàng)建
API基本格式: http://<ip>:<port>/<索引>/<類(lèi)型>/<文檔id>
常用HTTP動(dòng)詞:GET/PUT/POST/DELETE

  • 結(jié)合postman
<!--結(jié)構(gòu)化索引創(chuàng)建-->
<!--PUT請(qǐng)求-->
127.0.0.1:9200/people
{
    "settings":{
        "number_of_shards":3,       <!-- 分片數(shù) -->
        "number_of_replicas":1      <!-- 備份數(shù) -->
    },
    "mappings":{                    <!-- 映射 -->
        "man":{                     <!-- type -->
            "properties":{          <!-- 文檔 -->
                "name":{            <!-- 列 -->
                    "type":"text"   <!-- 類(lèi)型 -->
                },
                "age":{
                    "type":"integer"
                },
                "countary":{
                    "type":"keyword"
                },
                "date":{
                    "type":"date",
                    "format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
                }
            }
        }
    }
}

  • 插入操作
<!--指定文檔id插入-->
<!--PUT操作-->
127.0.0.1:9200/people/man/1
{
    "name":"xiaojinzi",
    "age":23,
    "countary":"China",
    "date":"1994-12-12"
}
<!--es生成id-->
<!--POST操作-->
127.0.0.1:9200/people/man
{
    "name":"bai_xiaojinzi",
    "age":33,
    "countary":"China",
    "date":"1984-12-12"
}

  • 修改操作
<!--直接修改文檔-->
<!--POST請(qǐng)求-->
127.0.0.1:9200/people/man/1/_update
{
    "doc":{
        "name":"xiaojinziya"
    }
}
<!--腳本修改文檔-->
<!--POST請(qǐng)求-->
127.0.0.1:9200/people/man/1/_update
{
    "script":{
        "lang":"painless",                  <!-- 腳本語(yǔ)言 -->
        "inline":"ctx._source.age +=10"     <!-- 修改內(nèi)容 -->
    }
}
<!-- 語(yǔ)言特性 -->
{
    "script":{
        "lang":"painless",                      <!-- 腳本語(yǔ)言 -->
        "inline":"ctx._source.age = params.age" <!-- 修改內(nèi)容 -->
        "params":{
            "age":100
        }
    }
}
  • 刪除操作
<!--刪除索引-->
<!--DELETE請(qǐng)求-->
127.0.0.1:9200/people

<!--刪除文檔-->
<!--DELETE請(qǐng)求-->
127.0.0.1:9200/people/man/1
  • 查詢(xún)
<!--簡(jiǎn)單查詢(xún)-->
<!--GET請(qǐng)求-->
127.0.0.1:9200/people/man/1
<!--條件查詢(xún)-->
<!--POST請(qǐng)求-->
127.0.0.1:9200/people/_search
<!--所有查詢(xún)-->
{
    "query":{
        "match_all":{}
    },
    "from":1,                   <!-- 開(kāi)始 -->
    "size":1                    <!-- 大小 -->
}
<!--條件-->
{
    "query":{
        "match":{
            "name":"xiao"       <!-- 名稱(chēng)含有 -->
        }
    },
    "sort":[
            {
                "age":{
                    "order":"desc"  <!-- 逆向排序-->
                }
            
            }
    ]
}
<!--聚合查詢(xún)-->
<!--POST請(qǐng)求-->
127.0.0.1:9200/people/_search
{
    "aggs":{
        "groud_by_name_count":{
            "terms":{
                "filed":"name"  <!-- 根據(jù)name長(zhǎng)度進(jìn)行聚合排序 -->
            }
        }
    }
}
{
    "aggs":{
        "grads_by_age":{
            "stats":{
                "filed":"age"   <!-- 根據(jù)age進(jìn)行統(tǒng)計(jì)計(jì)算 -->
            }
        }
    }
}

高級(jí)查詢(xún)

子條件查詢(xún)-特定字段查詢(xún)所指特定值,符合條件查詢(xún)-以一定的邏輯組合條件查詢(xún)

  • query

生成一個(gè)_score來(lái)標(biāo)識(shí)字段匹配的程度,用于匹配結(jié)果與查詢(xún)條件匹配的耦合度。

<!--全文本查詢(xún)-針對(duì)文本類(lèi)型數(shù)據(jù) --> 
<!--模糊匹配-->
<!--POST請(qǐng)求-->
127.0.0.1:9200/people/_search
{
    "query":{
        "match":{
            "name":"xiao"       <!-- 名稱(chēng)含有,對(duì)條件分詞查詢(xún)所有匹配結(jié)果 -->
        }
    }   
}
<!--習(xí)語(yǔ)匹配-->
{
    "query":{
        "match_phrase":{
            "name":"xiao"       <!-- 名稱(chēng)含有,不對(duì)條件分詞查詢(xún)所有匹配結(jié)果 -->
        }
    }   
}
<!--多字段-->
{
    "query":{
        "muilt_match":{
            "query":"xiao"
        },
        "filed":["name","countary"] <!-- 兩個(gè)字段中至少一個(gè)含有匹配結(jié)果 -->
    }
}
<!--語(yǔ)法查詢(xún)-->
{
    "query":{
        "query_string":{
            "query":"(xiao AND jin) OR zi" <!-- 有xiaojin或者zi的匹配結(jié)果 -->
        }
    }
}
<!--字段級(jí)別查詢(xún)-針對(duì)結(jié)構(gòu)化數(shù)據(jù),如數(shù)字刷晋、日期-->
{
    "query":{
        "term":{
            "age":23  <!-- age為23的 -->
        }
    }
}
{
    "query":{
        "range":{
            "age":{  <!-- age大于等于20小于等于25 -->
                "gte":20,
                "lte":25
            }  
        }
    }
}
  • filter

查詢(xún)滿(mǎn)足條件,返回是否盖高。

<!--POST請(qǐng)求-->
127.0.0.1:9200/people/_search
{
    "query":{
        "bool":{
            "filter":{
                "term":{
                    "age":23
                }
            }
        }
    }
}
  • 符合查詢(xún)
<!--固定分?jǐn)?shù)查詢(xún)-->
127.0.0.1:9200/people/_search
{
    "query":{
        "constant_score":{          <!-- 固定分?jǐn)?shù) -->
            "filter":{
                "match":{
                    "name":"xiao"   <!-- 條件 -->
                }
            },
            "boost":2               <!-- 分?jǐn)?shù)值 -->
        }
    }
}
<!--布爾查詢(xún)-->
{
    "query":{
        "bool":{
            "should":[{             <!-- 或者 -->
                "match":{
                    "name":"xiao"
                },
                "match":{
                    "date":"1994-12-12"
                }
            }]
        }
    }
}

{
    "query":{
        "bool":{
            "must":[{               <!-- 同時(shí)滿(mǎn)足 -->
                "match":{
                    "name":"xiao"
                },
                "match":{
                    "date":"1994-12-12"
                }
            }],
            "filter":{
                "age":23
            }
        }
    }
}
{
    "query":{
        "bool":{
            must_not:{             <!-- 非的操作 -->
                "term":{
                    "name":"xiao" 
                }
            }
        }
    }
}

springboot 集成elasticsearch

  • 依賴(lài)
<!--版本信息-->
<properties>
    <elasticsearch.version>5.5.3</elasticsearch.version>
</properties>

<!--搜索引擎-->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>${elasticsearch.version}</version>
</dependency>

<!--日志-->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.7</version>
</dependency>

<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

  • 日志文件配置
appender.console.type = Console
appender.console.name = Console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%t] %-5p $c -%m%n

rootLogger.level = info
rootLogger.appenderRef.console.ref = console
  • 配置類(lèi)
<!--系統(tǒng)參數(shù)配置-->
server:
  port: 8090
  context-path: /esdemo


es:
  url_ip: 127.0.0.1
  url_port: 9300
  node_cluster: cluster.name
  node_name: xiaojinzi
<!--參數(shù)引用-->
@ConfigurationProperties(prefix = "es")
@Data
@Component
public class EsClientConfig {

    /** 鏈接ip .*/
    private String url_ip;

    /** 端口 .*/
    private Integer url_port;

    /** 集群命名 .*/
    private String node_cluster;

    /** 節(jié)點(diǎn)名稱(chēng) .*/
    private String node_name;
}
<!--配置類(lèi)-->
@Configuration
public class EsClientBeanConfig {

    @Autowired
    private EsClientConfig esClientConfig;

    @Bean
    public TransportClient client() throws UnknownHostException{
         /** 節(jié)點(diǎn)設(shè)置 .*/
        InetSocketTransportAddress node = new InetSocketTransportAddress(
                InetAddress.getByName(esClientConfig.getUrl_ip()),
                esClientConfig.getUrl_port()
        );

        /** 參數(shù)設(shè)置 .*/
        Settings settings = Settings.builder().put(esClientConfig.getNode_cluster(),esClientConfig.getNode_name()).build();
        TransportClient client = new PreBuiltTransportClient(settings);
        /** 節(jié)點(diǎn)導(dǎo)入 .*/
        client.addTransportAddress(node);
        return client;
    }
}
  • 查詢(xún)接口編寫(xiě)
@RestController
@RequestMapping("/es")
public class EsApiController {

    @Autowired
    private TransportClient client;

    /**
     * 查詢(xún)
     * @param id
     * @return
     */
    @GetMapping("/get")
    public ResponseEntity get(@RequestParam("id")String id){
        if(id.isEmpty()){
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
        GetResponse result = this.client.prepareGet("people","man",id).get();
        if(result.getSource().isEmpty()){
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }
        return new ResponseEntity(result.getSource(),HttpStatus.OK);
    }
}
ID查詢(xún)
  • 增加接口
@Data
public class ManForm {

    /** 主鍵 .*/
    private String id;

    /** 名字 .*/
    private String name;

    /** 國(guó)家 .*/
    private String countary;

    /** 出生日期 .*/
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date date;

    /** 年齡 .*/
    private Integer age;
}
@PostMapping("/add")
public ResponseEntity add(@Valid ManForm manForm, BindingResult bindingResult){
    if (bindingResult.hasErrors()){
        return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
    }
    try {
        /** json 封裝 .*/
        XContentBuilder content = XContentFactory.jsonBuilder().startObject().
                field("name", manForm.getName()).
                field("age", manForm.getAge()).
                field("date", manForm.getDate().getTime()).
                field("countary", manForm.getCountary()).
                endObject();
        /** 添加文檔 .*/
        IndexResponse result = client.prepareIndex("people","man").setSource(content).get();
        return new ResponseEntity(result.getId(),HttpStatus.OK);
    }catch (IOException e){
        e.printStackTrace();
        return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
增加
  • 刪除操作
/**
* 根據(jù)id刪除
* @param id
* @return
*/
@DeleteMapping("/delete")
public ResponseEntity delete(@RequestParam("id")String id){
    DeleteResponse result = client.prepareDelete("people","man",id).get();
    return new ResponseEntity(result.getResult().toString(),HttpStatus.OK);
}
刪除
  • 更新操作
@PutMapping("/update")
public ResponseEntity update(@Valid ManForm manForm,BindingResult bindingResult){
    if(bindingResult.hasErrors()){
        return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
    }
    /** 構(gòu)建更新 .*/
    UpdateRequest request = new UpdateRequest("people","man",manForm.getId());
    try {
        /** json .*/
        XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
        if(manForm.getName()!= null){
            builder.field("name",manForm.getName());
        }
        if(manForm.getAge()>0){
            builder.field("age",manForm.getAge());
        }
        if(manForm.getCountary()!=null){
            builder.field("countary",manForm.getCountary());
        }
        if(manForm.getDate()!=null){
            builder.field("date",manForm.getDate().getTime());
        }
        builder.endObject();
        request.doc(builder);
    }catch (IOException e){
        e.printStackTrace();
        return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
    }
    try {
        /** 更新操作 .*/
        UpdateResponse result = client.update(request).get();
        return new ResponseEntity(result.getResult().toString(),HttpStatus.OK);
    }catch (Exception e){
        e.printStackTrace();
        return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
更新
  • 復(fù)合查詢(xún)
@PostMapping("/query")
public ResponseEntity query(@RequestParam(name="name",required = false)String name,
                            @RequestParam(name = "countary",required = false)String countary,
                            @RequestParam(name = "age_lte",required = false)Integer lte,
                            @RequestParam(name = "age_gte",defaultValue = "0")int gte){
    /** bool查詢(xún)構(gòu)建 .*/
    BoolQueryBuilder boolQuery =  QueryBuilders.boolQuery();
    if(name!=null){
        /** 條件匹配 .*/
        boolQuery.must(QueryBuilders.matchQuery("name",name));
    }
    if(countary!=null){
        boolQuery.must(QueryBuilders.matchQuery("countary",countary));
    }
    /** 范圍構(gòu)建 .*/
    RangeQueryBuilder range = QueryBuilders.rangeQuery("age").from(gte);
    if(lte!= null && lte>0 ){
        range.to(lte);
    }
    /** filter條件添加 .*/
    boolQuery.filter(range);

    /** 搜索條件構(gòu)建 .*/
    SearchRequestBuilder builder = client.prepareSearch("people").
            setTypes("man").
            setSearchType(SearchType.DFS_QUERY_THEN_FETCH).
            serQuery(boolQuery).
            setFrom(0).
            setSize(10);
    System.out.println(builder.get());

    /** 結(jié)果返回 .*/
    SearchResponse response = builder.get();

    /** 遍歷hits .*/
    List<Map<String,Object>> result = new ArrayList<>();
    for(SearchHit hit:response.getHits()){
        result.add(hit.getSource());
    }

    /** 結(jié)果返回 .*/
    return new ResponseEntity(result,HttpStatus.OK);
}
復(fù)合查詢(xún)

復(fù)合查詢(xún)

  • 原視頻UP主慕課網(wǎng)(ElasticSearch入門(mén))
  • 項(xiàng)目代碼上傳Git 期待你的star
  • 本篇博客撰寫(xiě)人: XiaoJinZi 轉(zhuǎn)載請(qǐng)注明出處
  • 學(xué)生能力有限 附上郵箱: 986209501@qq.com 不足以及誤處請(qǐng)大佬指責(zé)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市眼虱,隨后出現(xiàn)的幾起案子喻奥,更是在濱河造成了極大的恐慌哭当,老刑警劉巖捷犹,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叭喜,死亡現(xiàn)場(chǎng)離奇詭異污朽,居然都是意外死亡弛说,警方通過(guò)查閱死者的電腦和手機(jī)愕宋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)出牧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)悴了,“玉大人寇钉,你說(shuō)我怎么就攤上這事刀疙。” “怎么了扫倡?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵谦秧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)疚鲤,這世上最難降的妖魔是什么锥累? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮集歇,結(jié)果婚禮上桶略,老公的妹妹穿的比我還像新娘。我一直安慰自己诲宇,他們只是感情好际歼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著焕窝,像睡著了一般蹬挺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上它掂,一...
    開(kāi)封第一講書(shū)人閱讀 51,708評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音溯泣,去河邊找鬼虐秋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛垃沦,可吹牛的內(nèi)容都是我干的客给。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼肢簿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼靶剑!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起池充,我...
    開(kāi)封第一講書(shū)人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤桩引,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后收夸,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體坑匠,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年卧惜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了厘灼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咽瓷,死狀恐怖设凹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情茅姜,我是刑警寧澤闪朱,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響监透,放射性物質(zhì)發(fā)生泄漏桶错。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一胀蛮、第九天 我趴在偏房一處隱蔽的房頂上張望院刁。 院中可真熱鬧,春花似錦粪狼、人聲如沸退腥。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)狡刘。三九已至,卻和暖如春困鸥,著一層夾襖步出監(jiān)牢的瞬間嗅蔬,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工疾就, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留澜术,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓猬腰,卻偏偏與公主長(zhǎng)得像鸟废,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子姑荷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容