24、ElasticSearch

安裝ElasticSearch

  • 安裝1.8及以上的jdk
  • https://www.elastic.co/cn/downloads/elasticsearch 下載對應(yīng)版本
  • 上傳到云服務(wù)器 /usr/local/software/ 目錄下
  • tar -zxvf elasticsearch-7.12.1-linux-x86_64.tar.gz解壓
  • cd /usr/local/software/elasticsearch-7.12.1/bin
  • 執(zhí)行./elasticsearch報錯
    java.lang.RuntimeException: can not run elasticsearch as root
  • 新建es用戶
  • cd /usr/local/software
  • groupadd esgroup
  • useradd esuser -g esgroup -p 123456
  • chown -R esuser:esgroup elasticsearch-7.12.1/
  • su - esuser
  • ./elasticsearch 前臺啟動
  • ./elasticsearch -d 后臺啟動 需要等一段時間
  • 配置跨域訪問 /usr/local/software/elasticsearch-7.12.1/config/elasticsearch.yml 最后添加下面兩行
http.cors.enabled: true
http.cors.allow-origin: "*"
  • curl 127.0.0.1:9200 成功會有相應(yīng)信息

  • 如果出現(xiàn) max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]錯誤 編輯 /etc/sysctl.conf,追加以下內(nèi)容:vm.max_map_count=655360保存后建丧,執(zhí)行:sysctl -p

  • 出現(xiàn) max file descriptors [65535] for elasticsearch process is too low, increase to at least [65536] 切換到root用戶編輯 /etc/security/limits.conf,追加以下內(nèi)容

    soft nofile 65536
    hard nofile 65536
    
  • 默認(rèn)只允許本機訪問 配合Nginx 實現(xiàn)外網(wǎng)訪問

   upstream es_pool{
        server 127.0.0.1:9200;
    }

    upstream es_header_pool{
        server 127.0.0.1:9100;
    }

    server {
        listen       80;
        server_name  localhost;

        location /es/ {
            proxy_pass http://es_pool/;
            proxy_set_header Host $host;
              proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        location /es_header/ {
            proxy_pass http://es_header_pool/;
            proxy_set_header Host $host;
              proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
     }
  • 允許內(nèi)網(wǎng)訪問的 elasticsearch.yml 配置文件
cluster.name: my-application
node.name: node-1
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["127.0.0.1", "[::1]"]
cluster.initial_master_nodes: ["node-1"]

http.cors.allow-origin: "*"
http.cors.enabled: true
http.cors.allow-headers : X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization
http.cors.allow-credentials: true

安裝ElasticSearch-Head

  • 通過https://nodejs.org/en/download/ 下載nodejs版本

  • 上傳到/usr/local/software下面

  • tar -xvf node-v14.17.0-linux-x64.tar.xz 解壓

  • export PATH=$PATH:/usr/local/software/node-v14.17.0-linux-x64/bin

  • ln -s /usr/local/software/node-v14.17.0-linux-x64/bin/npm /usr/local/bin/
    ln -s /usr/local/software/node-v14.17.0-linux-x64/bin/node /usr/local/bin/

  • 執(zhí)行node -v 打印版本 成功

  • 通過 https://github.com/mobz/elasticsearch-head 下載最新版本

  • yum install -y unzip zip 安裝unzip解壓

  • 上傳到/usr/local/software/ unzip elasticsearch-head-master.zip

  • npm install -g grunt-cli 安裝依賴

  • yum install bzip2 //可能會報解壓錯誤 沒有忽略即可

  • npm install cnpm -g --registry=https://registry.npm.taobao.org 使用npm因為網(wǎng)絡(luò)原因總是報錯

  • cd elasticsearch-head-master/ 執(zhí)行 cnpm install

  • 修改Gruntfile.js

connect: {
    server: {
        options: {
            hostname: '*', # 添加這一行
            port: 9100,
            base: '.',
            keepalive: true
        }
    }
}
  • 修改_site下面的app.js 4388行左右將localhost替換成ElasticSearch的服務(wù)器地址
this.base_uri = this.config.base_uri || this.prefs.get("app-base_uri") || "http://192.168.0.199:9200";
  • npm run start 啟動
  • nohup npm run start & 后臺啟動

安裝 Kibana

server.host: "192.168.0.199"
elasticsearch.hosts: ["http://192.168.0.199:9200"]
i18n.locale: "zh-CN"
  • 執(zhí)行bin目錄下的kibana ./kibana --allow-root
  • 訪問 http://192.168.0.199:5601/

ElasticSearch 術(shù)語

  • 索引index —— 擁有相似文檔的集合
  • 類型type —— 一個索引中可以定義多個類型
  • 字段field —— 相當(dāng)于數(shù)據(jù)庫表中的字段
  • 映射mapping —— 處理數(shù)據(jù)方式和規(guī)格方面做一些限制
  • 文檔document —— 一個文檔是一個可被索引的基礎(chǔ)單元
  • 分片 —— 由于單臺機器無法存儲大量數(shù)據(jù)波势,ES 可以將一個索引中的數(shù)據(jù)切分為多個分片(Shard)翎朱,分布在多臺服務(wù)器上存儲。
  • 復(fù)制 —— 備份

操作

{
    "mappings": {
        "properties": {
            "id": {
                "type": "long",
                "store": true
            },
            "title": {
                "type": "text",
                "store": true,
                "analyzer": "standard"
            },
            "content": {
                "type": "text",
                "store": true,
                "analyzer": "standard"
            }
        }
    }
}
  • 查看索引對應(yīng)的映射 類型默認(rèn)都是_doc
{
  "mappings": {
    "_doc": {
      "properties": {
        "content": {
          "type": "text",
          "store": true,
          "analyzer": "standard"
        },
        "id": {
          "type": "long",
          "store": true
        },
        "title": {
          "type": "text",
          "store": true,
          "analyzer": "standard"
        }
      }
    }
  }
}
{
  "mappings": {
    "db1": {
      "properties": {
        "content": {
          "type": "text",
          "store": true,
          "analyzer": "standard"
        },
        "id": {
          "type": "long",
          "store": true
        },
        "title": {
          "type": "text",
          "store": true,
          "analyzer": "standard"
        }
      }
    }
  }
}
  • DELETE請求刪除索引庫 http://192.168.0.199/es/test1
  • 添加文檔(一條數(shù)據(jù)就是一個文檔)http://192.168.0.199/es/test/db1/1 在db1類型下設(shè)置id為1的數(shù)據(jù) 下面是請求體 保持和映射一致就行 如果db1后面不加/1 會自動生成一個隨機字符串id 操作時一般保持id字段和請求體里面的id字段保持一致
{
    "id":1,
    "title":"文檔標(biāo)題",
    "content":"文檔內(nèi)容"
}
  • id設(shè)置相同數(shù)據(jù)會被覆蓋 用來實現(xiàn)修改文檔

  • DELETE方法刪除文檔 http://192.168.0.199/es/test/db1/1

  • 查詢

        {
            "query_string":{
                "term":{
                    "default_field":"title",
                    "query":"文檔"                
                }
            }
        }
    
    {
      "analyzer" : "standard",
      "text": ["文檔標(biāo)題2"]
    }
    
    • 關(guān)鍵詞查詢 like query_string 先對查詢內(nèi)容分詞
     {
            "query":{
                "query_string":{ 
                    "query":"title:(\"題2\")",
                    "default_operator": "and"
                }
            }
        }
    

    or

    {
        "query": {
            "match_phrase": {
                "title": "題2"
            }
        }
    }
    

安裝中文分詞器IK

ElasticSearch內(nèi)置分詞器

  1. standard分詞器:(默認(rèn)分詞器)它會將詞匯單元轉(zhuǎn)換成小寫形式尺铣,并除去停用詞(a拴曲、an、the等)和標(biāo)點符號凛忿,支持中文采用的方法為單字切分澈灼。
  2. simple分詞器:首先會通過非字母字符來分割文本信息,然后將詞匯單元統(tǒng)一成小寫形式店溢,該分詞器會去掉數(shù)據(jù)類型的字符叁熔。
  3. Whitespace分詞器:僅僅是去掉空格,對字符沒有l(wèi)owcase化床牧,不支持中文荣回;并且不對生成的詞匯單元進(jìn)行其他的標(biāo)準(zhǔn)化處理。
  4. language分詞器:特定語言的分詞器戈咳,不支持中文

中文分詞器的安裝

  • https://github.com/medcl/elasticsearch-analysis-ik/releases 下載最新版本的zip包
  • cd /usr/local/software/elasticsearch-7.12.1/plugins/
  • mkdir ik
  • 把文件移動到ik目錄下
  • cd ik/
  • unzip elasticsearch-analysis-ik-7.12.1.zip
  • 切換用戶重啟 elasticsearch
  • 新建映射的時候就需使用ik分析器
  • ik_smart(最行娜怼) 和 ik_max_word(最細(xì))的區(qū)別 舉例分析程序員 ik_smart 會解析成程序員 ik_max_word 會解析成三個分別是 程序員 程序 員
{
  "mappings": {
    "db1": {
      "properties": {
        "content": {
          "type": "text",
          "store": true,
          "analyzer": "ik_smart"
        },
        "id": {
          "type": "long",
          "store": true
        },
        "title": {
          "type": "text",
          "store": true,
          "analyzer": "ik_max_word"
        }
      }
    }
  }
}

集群

修改config\elasticsearch.yml文件添加

#集群名稱壕吹,保證唯一
cluster.name: my‐elasticsearch
#節(jié)點名稱,必須不一樣
node.name: node‐1 # node‐2 node‐3
#必須為本機的ip地址
network.host: 192.168.0.199 # 0.200  0.201
#服務(wù)端口號
http.port: 9200
#服務(wù)TCP端口號
transport.tcp.port: 9300
#設(shè)置集群自動發(fā)現(xiàn)機器ip集合
discovery.zen.ping.unicast.hosts:["192.168.0.199:9300","192.168.0.200:9300","192.168.0.201:9302"]

SpringBoot 整合

  • 創(chuàng)建工程 并引入依賴 內(nèi)部引用的es版本必須要和服務(wù)器安裝的匹配
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    <version>2.3.10.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  • application.yml配置
spring:
  elasticsearch:
    rest:
      uris: 192.168.0.199:9200
      username: my-application
  #   uris:192.168.0.199:9200,192.168.0.200:9200,192.168.0.201:9200,
  • 實體與document對應(yīng)類
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;

@Document(indexName = "stu") //索引名稱
@Data
public class Stu {
    @Id
    private Long stuId; //會創(chuàng)建相同的文檔id 否則自動生成

    @Field(store = true)
    private String name;

    @Field(store = true)
    private Integer age;
}
  • 實體類中新加四個字段 會自動添加到索引里面
@Field(store = true)
private Float money;

@Field(store = true, type = FieldType.Keyword)
private String sign;

@Field(store = true)
private String description;

@Field(type = FieldType.Date, format = DateFormat.date_time)
private Date recordTime;
  • 關(guān)于常用方法 2.3.10 版本中的
@RunWith(SpringRunner.class)
@SpringBootTest
public class ESTest {
    /**
     * 一般不建議用Spring來創(chuàng)建/更新 刪除索引
     * 一般針對文檔進(jìn)行CRUD操作
     */
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 創(chuàng)建/更新索引 如果存在 就更新 不會再創(chuàng)建 一般不使用
     */
    @Test
    public void createIndexStu() {
        Stu stu = new Stu();
        stu.setStuId(1006L);
        stu.setAge(33);
        stu.setName("李七");
        stu.setRecordTime(new Date());
        IndexQuery indexQuery = new IndexQueryBuilder().withObject(stu).build();
        IndexCoordinates indexCoordinates = elasticsearchRestTemplate.getIndexCoordinatesFor(Stu.class);
        elasticsearchRestTemplate.index(indexQuery, indexCoordinates);
    }

    /**
     * 更新文檔
     */
    @Test
    public void updateStuDoc() {
        Document document = Document.create();
        document.put("name", "李四");
        document.put("age", 20);
        UpdateQuery updateQuery = UpdateQuery.builder("1000").withDocument(document).build();
        elasticsearchRestTemplate.update(updateQuery, elasticsearchRestTemplate.getIndexCoordinatesFor(Stu.class));
    }

    /**
     * 查詢 + 高亮顯示
     */
    @Test
    public void queryStuDoc() {
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        //必須滿足的條件 加keyword不會拆分 不加會拆分成李和四
//        boolQueryBuilder.must().add(new TermQueryBuilder("name.keyword", "李四"));
//        boolQueryBuilder.must().add(new TermQueryBuilder("name", "四"));
        // 查詢3天內(nèi)數(shù)的數(shù)據(jù)
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("recordTime");
        rangeQueryBuilder.gte(LocalDateTime.now().minusDays(3));
//        或者下面的
//        rangeQueryBuilder
//                .from("2021-05-16T00:00:00.000Z")
//                .to("2021-05-19T23:59:59.000Z");
//        boolQueryBuilder.must().add(rangeQueryBuilder);


        // 分頁查詢20條
        PageRequest pageRequest = PageRequest.of(0, 20, Sort.by("stuId").descending());

        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
        searchQueryBuilder
                .withQuery(boolQueryBuilder)
                // 親測使用.keyword有值但是高亮數(shù)據(jù)size = 0
                .withHighlightBuilder(new HighlightBuilder().field("name")
                        .preTags("<font color='red'>")
                        .postTags("</font>"))
                .withPageable(pageRequest);


        Query searchQuery = searchQueryBuilder.build();

        SearchHits<Stu> result = elasticsearchRestTemplate.search(searchQuery, Stu.class);
        List<SearchHit<Stu>> hitList = result.getSearchHits();
        System.out.println("hit size -> {}" + hitList.size());
        hitList.forEach(hit -> {
            Map<String, List<String>> highlightFields = hit.getHighlightFields();
            List<String> nameHighlight = highlightFields.get("name");
            if (nameHighlight != null) {
                for (String text : nameHighlight) {
                    hit.getContent().setName(text);
                }
            }
            System.out.println("返回數(shù)據(jù):" + hit.getContent().toString());
        });
    }

    /**
     * 刪除文檔
     */
    @Test
    public void delIndexDoc() {
        elasticsearchRestTemplate.delete("1000", elasticsearchRestTemplate.getIndexCoordinatesFor(Stu.class));
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末删铃,一起剝皮案震驚了整個濱河市耳贬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌猎唁,老刑警劉巖效拭,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異胖秒,居然都是意外死亡缎患,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門阎肝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挤渔,“玉大人,你說我怎么就攤上這事风题∨械迹” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵沛硅,是天一觀的道長眼刃。 經(jīng)常有香客問我,道長摇肌,這世上最難降的妖魔是什么擂红? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮围小,結(jié)果婚禮上昵骤,老公的妹妹穿的比我還像新娘。我一直安慰自己肯适,他們只是感情好变秦,可當(dāng)我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著框舔,像睡著了一般蹦玫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刘绣,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天樱溉,我揣著相機與錄音,去河邊找鬼额港。 笑死饺窿,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的移斩。 我是一名探鬼主播肚医,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼绢馍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了肠套?” 一聲冷哼從身側(cè)響起舰涌,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎你稚,沒想到半個月后瓷耙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡刁赖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年搁痛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宇弛。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡鸡典,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出枪芒,到底是詐尸還是另有隱情彻况,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布舅踪,位于F島的核電站纽甘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏抽碌。R本人自食惡果不足惜悍赢,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望咬展。 院中可真熱鬧泽裳,春花似錦瞒斩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至裳扯,卻和暖如春饰豺,著一層夾襖步出監(jiān)牢的瞬間冤吨,已是汗流浹背漩蟆。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工怠李, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留圾叼,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓捺癞,卻偏偏與公主長得像夷蚊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子髓介,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,925評論 2 344

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