1. 程式人生 > 實用技巧 >BeautifulSoup4 print() 輸出中文亂碼解決方法

BeautifulSoup4 print() 輸出中文亂碼解決方法

ElasticSearch

1、概述

​ Elasticsearch 是一個分散式可擴充套件的實時搜尋和分析引擎,一個建立在全文搜尋引擎 Apache Lucene(TM) 基礎上的搜尋引擎.當然 Elasticsearch 並不僅僅是 Lucene 那麼簡單,它不僅包括了全文搜尋功能,還可以進行以下工作:

  • 分散式實時檔案儲存,並將每一個欄位都編入索引,使其可以被搜尋。
  • 實時分析的分散式搜尋引擎。
  • 可以擴充套件到上百臺伺服器,處理PB級別的結構化或非結構化資料。

基本概念

先說Elasticsearch的檔案儲存,Elasticsearch是面向文件型資料庫,一條資料在這裡就是一個文件,用JSON作為文件序列化的格式,比如下面這條使用者資料:

{
    "name" :     "John",
    "sex" :      "Male",
    "age" :      25,
    "birthDate": "1990/05/01",
    "about" :    "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}

用Mysql這樣的資料庫儲存就會容易想到建立一張User表,有balabala的欄位等,在Elasticsearch裡這就是一個文件,當然這個文件會屬於一個User的型別,各種各樣的型別存在於一個索引當中。這裡有一份簡易的將Elasticsearch和關係型資料術語對照表:

關係資料庫       ⇒ 資料庫        ⇒ 表          ⇒ 行              ⇒ 列(Columns)

Elasticsearch  ⇒ 索引(Index)   ⇒ 型別(type)  ⇒ 文件(Docments)  ⇒ 欄位(Fields)  

一個 Elasticsearch 叢集可以包含多個索引(資料庫),也就是說其中包含了很多型別(表)。這些型別中包含了很多的文件(行),然後每個文件中又包含了很多的欄位(列)。Elasticsearch的互動,可以使用Java API,也可以直接使用HTTP的Restful API方式,比如我們打算插入一條記錄,可以簡單傳送一個HTTP的請求:

PUT /megacorp/employee/1  
{
    "name" :     "John",
    "sex" :      "Male",
    "age" :      25,
    "about" :    "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}

更新,查詢也是類似這樣的操作,具體操作手冊可以參見Elasticsearch權威指南

ElasticSearch的搜尋是採用的倒排索引,具體的看倒排索引

2、ik分詞器

什麼是ik分詞器?

分詞:即把一段中文或者別的劃分為一個個關鍵字,我們在搜尋的時候會把自己的資訊進行分詞,會把資料庫中或者索引庫中的資料進行分詞,然後進行一個匹配操作,預設的中文分詞是將每個字看成一個詞,比如“我愛小胖”,就會被分成"我",”愛“,”小“,”胖“,這明顯是不符合要求的,所以我們需要安裝一箇中文分詞器來解決這個問題。

IK提供了兩個分詞演算法:ik_smart和ik_max_word,其中ik_smart為最少劃分,ik_max_word為最細度劃分。

測試:

ik_smart最少劃分

ik_max_word最細度劃分

我們還使用過程中,還可能遇到ik詞中沒有”張錦豪“這個詞,把它劃分成了"張","錦",”豪“。

這時候我們可以在ik分詞器中的配置檔案新增自己所需要的詞。

然後查詢出來的就是”張錦豪“

注意:型別為keyword型別的欄位不能被分詞器解析。

3、Restful風格

一種軟體架構風格,而不是標準,只是提供了一組設計原則和約束條件。它主要用於客戶端和服務端互動的軟體,基於這個風格設計的軟體可以更加簡潔,更有層次,更易於實現快取等機制。

基本的Rest命令說明:

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 查詢所有資料

基礎測試

1、建立索引

資料新增成功,我們在建立的時候沒有標明資料欄位的型別,es會自動幫我們設定

我這也可以自己設定索引的資料型別,在建立的時候。

2、刪除索引

3、修改索引資料

  • 通過put方式在原有的資料上直接修改,把原來的資料覆蓋掉(如果有些欄位沒寫,就會變為了空)

  • 通過post的put方式指定文件id/_update修改資料(推薦使用這種方式,靈活性更高)

4、查詢索引資料

get 索引名

4、文件的花式查詢

1、簡單的查詢

這裡需要注意

複雜查詢

過濾查詢結果 相當於mysql種的select * 跟select 欄位的區別

排序

分頁查詢

bool 布林值查詢

多條件查詢 must就相當於sql中的and,所有條件都必須滿足

should 相當於or,只要滿足了其中一個條件的就可以

must_not 相當於not,非,不滿足

filter 過濾器

匹配多個條件查詢

term 精確查詢

term查詢是直接通過倒排索引指定的詞條程序精確的查詢的。

在使用term精確查詢時,型別為keyword的不會被分詞器解析。

多條件精確查詢

highlight 高亮

5、Spingboot整合

1、匯入依賴

<dependency>
			<groupId>org.elasticsearch.client</groupId>
			<artifactId>elasticsearch-rest-high-level-client</artifactId>
			<version>7.6.1</version>
		</dependency>

注意點:匯入的依賴版本一定要跟自己安裝的版本所對應

2、編寫配置檔案

@Configuration
public class EsConfig {
    @Bean
    public RestHighLevelClient restHighLevelClient(){
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("127.0.0.1", 9200,"http")
                )
        );
        return client;
    }
}

3測試

3.1、建立索引

   @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    //測試建立索引請求 相當於一個put請求
    @Test
    void contextLoads() throws IOException {
        //建立索引請求
        CreateIndexRequest request = new CreateIndexRequest("xiaopang_index");
        //客戶端執行請求
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(response);

    }

3.2、查詢索引是否存在

//測試查詢索引
 @Test
 void contextLoads2() throws IOException {
     //查詢索引請求
     GetIndexRequest request = new GetIndexRequest("xiaopang_index");
     //客戶端執行請求
     boolean response = client.indices().exists(request,RequestOptions.DEFAULT);
     System.out.println(response);

 }
//結果返回true

3.3、刪除索引

//測試刪除索引
@Test
void contextLoads3() throws IOException {
    //刪除索引請求
    DeleteIndexRequest request = new DeleteIndexRequest("xiaopang_index");
    //客戶端執行請求
    AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
    System.out.println(delete.isAcknowledged());

}
//結果返回true

6、springboot整合之文件型操作

1、新增文件

 //測試新增文件
    @Test
    public void addDocumentTest() throws IOException {
        //建立物件
        User user = new User("小胖", 13);
        //建立請求
        IndexRequest request = new IndexRequest("xiaopang");
        //建立規則 相當於 put  /xiaopang/_doc/1
        //設定文件id
        request.id("1");
        //設定請求實踐
        request.timeout("1s");
        //將我們的user類封裝成json,放入請求中
        request.source(JSON.toJSONString(user), XContentType.JSON);

        //客戶端傳送請求,返回響應結果
        IndexResponse index = client.index(request, RequestOptions.DEFAULT);
        System.out.println(index.toString());
        System.out.println(index.status());

    }
//返回結果
IndexResponse[index=xiaopang,type=_doc,id=1,version=1,result=created,seqNo=0,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]  //具體的資訊
CREATED  //執行的狀態  新增

2、查詢文件資訊

//測試查詢文件資訊
@Test
public void selectDocumentTest() throws IOException {
    //建立查詢請求
    GetRequest request = new GetRequest("xiaopang", "1");

    //判斷文件是否存在
    boolean exists = client.exists(request, RequestOptions.DEFAULT);
    System.out.println(exists);
    GetResponse response = client.get(request, RequestOptions.DEFAULT);
    System.out.println(response.getSource()); //獲取文件內容資訊
    System.out.println(response);  //獲取文件全部資訊

}
//返回結果
true
{name=小胖, age=13}
{"_index":"xiaopang","_type":"_doc","_id":"1","_version":1,"_seq_no":0,"_primary_term":1,"found":true,"_source":{"age":13,"name":"小胖"}}

3、修改文件資訊

 //測試修改文件資訊
    @Test
    public void updateDocumentTest() throws IOException {
        //建立修改請求
        UpdateRequest request = new UpdateRequest("xiaopang", "1");
        //設定響應時間
        request.timeout("1s");
        //建立新的user類,這裡相當於使用了put命令去修改文件資訊,直接覆蓋資訊
        User user = new User("張錦豪", 18);
        //將新的user放入請求
       request.doc(JSON.toJSONString(user),XContentType.JSON);
       //客戶端執行請求
        UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
        System.out.println(update.status());
    }
//返回結果
OK

4、刪除文件資訊

//測試刪除文件資訊
@Test
public void deleteDocumentTest() throws IOException {
    DeleteRequest request = new DeleteRequest("xiaopang", "1");
    request.timeout("1s");
    DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
    System.out.println(delete.status());
}
//返回結果
ok

5、資料批量插入

//資料批量插入
    @Test
    public void test1() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("xiaopang1",1));
        users.add(new User("xiaopang2",1));
        users.add(new User("xiaopang3",1));
        users.add(new User("jinhao1",3));
        users.add(new User("jinhao2",3));
        users.add(new User("jinhao3",3));

        for (int i = 0; i <users.size() ; i++) {
            bulkRequest.add(
                    new IndexRequest("xiaopang")
                    .id(""+(i+1))
                    .source(JSON.toJSONString(users.get(i)),XContentType.JSON)
            );
        }
        BulkResponse responses = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(responses.hasFailures());//是否失敗,false代表成功了
    }

6、複雜查詢處理

  @Test
    public void test() throws IOException {
        SearchRequest request = new SearchRequest("xiaopang");
        //構建條件搜尋
        SearchSourceBuilder builder = new SearchSourceBuilder();
        TermQueryBuilder matchQuery = QueryBuilders.termQuery("name", "jinhao1");
        builder.query(matchQuery);
        request.source(builder);
        builder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        System.out.println(JSON.toJSONString(search));
        System.out.println("============================================");
        for (SearchHit hit : search.getHits().getHits()) {
            System.out.println(hit.getSourceAsMap());
        }

    }