<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      ElasticSearch基礎學習(SpringBoot集成ES)

      一、概述

      什么是ElasticSearch?

      ElasticSearch,簡稱為ES, ES是一個開源的高擴展的分布式全文搜索引擎

      它可以近乎實時的存儲、檢索數據;本身擴展性很好,可以擴展到上百臺服務器,處理PB級別的數據。

      ES也使用Java開發并使用Lucene作為其核心來實現所有索引和搜索的功能,但是它的目的是通過簡單的RESTful API來隱藏Lucene的復雜性,從而讓全文搜索變得簡單。

      ES核心概念

      知道了ES是什么后,接下來還需要知道ES是如何存儲數據,數據結構是什么,又是如何實現搜索的呢?

      學習這些之前需要先了解一些ElasticSearch的相關概念。

      ElasticSearch是面向文檔型數據庫

      相信學習過MySql的同學都知道,MySql是關系型數據庫,那么ES與關系型數據庫有什么區別呢?

      下面做一下簡單的對比:

      關系型數據庫(MySql、Oracle等) ElasticSearch
      數據庫(database) 索引(indices)
      表(tables) 類型(types)
      行(rows) 文檔(documents)
      列(columns) 字段(fields)

      說明:ElasticSearch(集群)中可以包含多個索引(數據庫),每個索引中可以包含多個類型(表),每個類型下又包含多 個文檔(行),每個文檔中又包含多個字段(列)。

      物理設計

      ElasticSearch 在后臺把每個索引劃分成多個分片,每份分片可以在集群中的不同服務器間遷移。

      邏輯設計

      一個索引類型中,包含多個文檔,比如說文檔1,文檔2,文檔3。

      當我們索引一篇文檔時,可以通過這樣的一個順序找到它: 索引 ? 類型 ? 文檔ID ,通過這個組合我們就能索引到某個具體的文檔。 注意:ID不必是整數,實際上它是個字符串

      索引

      索引是映射類型的容器,elasticsearch中的索引是一個非常大的文檔集合。索引存儲了映射類型的字段和其他設置。 然后它們被存儲到了各個分片上了。 我們來研究下分片是如何工作的。

      物理設計 :節點和分片 如何工作

      一個集群至少有一個節點,而一個節點就是一個elasricsearch進程,節點可以有多個索引默認的,如果你創建索引,那么索引將會有個5個分片 ( primary shard ,又稱主分片 ) 構成的,每一個主分片會有一個副本 ( replica shard ,又稱復制分片 )

      上圖是一個有3個節點的集群,可以看到主分片和對應的復制分片都不會在同一個節點內,這樣有利于某個節點掛掉 了,數據也不至于丟失。 實際上,一個分片是一個Lucene索引,一個包含倒排索引的文件目錄,倒排索引的結構使得elasticsearch在不掃描全部文檔的情況下,就能告訴你哪些文檔包含特定的關鍵字。 其中,倒排索引又是什么呢?

      倒排索引

      elasticsearch使用的是一種稱為倒排索引的結構,采用Lucene倒排索作為底層。這種結構適用于快速的全文搜索, 一個索引由文檔中所有不重復的列表構成,對于每一個詞,都有一個包含它的文檔列表。 例如,現在有兩個文檔, 每個文檔包含如下內容:

      Study every day, good good up to forever # 文檔1包含的內容
      To forever, study every day, good good up # 文檔2包含的內容
      

      為了創建倒排索引,我們首先要將每個文檔拆分成獨立的詞(或稱為詞條或者tokens),然后創建一個包含所有不重復的詞條的排序列表,然后列出每個詞條出現在哪個文檔 :

      term doc_1 doc_2
      Study x
      To x x
      every
      forever
      day
      study x
      good
      every
      to x
      up

      現在,我們試圖搜索 to forever,只需要查看包含每個詞條的文檔

      term doc_1 doc_2
      to ×
      forever
      total 2 1

      兩個文檔都匹配,但是第一個文檔比第二個匹配程度更高。如果沒有別的條件,現在,這兩個包含關鍵字的文檔都將返回。

      再來看一個示例,比如我們通過博客標簽來搜索博客文章。那么倒排索引列表就是這樣的一個結構 :

      如果要搜索含有 python 標簽的文章,那相對于查找所有原始數據而言,查找倒排索引后的數據將會快的多。只需要 查看標簽這一欄,然后獲取相關的文章ID即可。

      ElasticSearch的索引和Lucene的索引對比

      在elasticsearch中, 索引這個詞被頻繁使用,這就是術語的使用。 在elasticsearch中,索引被分為多個分片,每份分片是一個Lucene的索引。所以一個elasticsearch索引是由多個Lucene索引組成的

      類型

      類型是文檔的邏輯容器,就像關系型數據庫一樣,表格是行的容器。 類型中對于字段的定義稱為映射,比如 name 映射為字符串類型。

      我們說文檔是無模式的,它們不需要擁有映射中所定義的所有字段,比如新增一個字段,那么elasticsearch是怎么做的呢?elasticsearch會自動的將新字段加入映射,但是這個字段的不確定它是什么類型,elasticsearch就開始猜,如果這個值是18,那么elasticsearch會認為它是整形。 但是elasticsearch也可能猜不對, 所以最安全的方式就是提前定義好所需要的映射,這點跟關系型數據庫殊途同歸了,先定義好字段,然后再使用。

      文檔

      之前說elasticsearch是面向文檔的,那么就意味著索引和搜索數據的最小單位是文檔。

      elasticsearch中,文檔有幾個重要屬性 :

      • 自我包含,一篇文檔同時包含字段和對應的值,也就是同時包含 key:value!
      • 可以是層次型的,一個文檔中包含自文檔,復雜的邏輯實體就是這么來的!
      • 靈活的結構,文檔不依賴預先定義的模式,我們知道關系型數據庫中,要提前定義字段才能使用,在elasticsearch中,對于字段是非常靈活的,有時候,我們可以忽略該字段,或者動態的添加一個新的字段。

      盡管我們可以隨意的新增或者忽略某個字段,但是,每個字段的類型非常重要,比如一個年齡字段類型,可以是字符串也可以是整形。因為elasticsearch會保存字段和類型之間的映射及其他的設置。這種映射具體到每個映射的每種類型,這也是為什么在elasticsearch中,類型有時候也稱為映射類型。

      二、ES基礎操作

      IK分詞器插件

      什么是IK分詞器?

      分詞:即把一段中文或者別的劃分成一個個的關鍵字,我們在搜索時候會把自己的信息進行分詞,會把數據庫中或者索引庫中的數據進行分詞,然后進行一個匹配操作。

      默認的中文分詞是將每個字看成一個詞,比如 “我愛學習” 會被分為"我","愛","學","習",這顯然是不符合要求的,所以我們需要安裝中文分詞器ik來解決這個問題。

      IK分詞器安裝步驟

      1、下載ik分詞器的包,Github地址:https://github.com/medcl/elasticsearch-analysis-ik/ (版本要對應)

      2、下載后解壓,并將目錄拷貝到ElasticSearch根目錄下的 plugins 目錄中。

      3、重新啟動 ElasticSearch 服務,在啟動過程中,你可以看到正在加載"analysis-ik"插件的提示信息,服務啟動后,在命令行運行elasticsearch-plugin list 命令,確認 ik 插件安裝成功。

      IK提供了兩個分詞算法:ik_smartik_max_word,其中 ik_smart為最少切分,ik_max_word為最細粒度劃分!

      • ik_max_word : 細粒度分詞,會窮盡一個語句中所有分詞可能。
      • ik_smart : 粗粒度分詞,優先匹配最長詞,只有1個詞!

      如果某些詞語,在默認的詞庫中不存在,比如我們想讓“我愛學習”被識別是一個詞,這時就需要我們編輯自定義詞庫

      步驟:

      (1)進入elasticsearch/plugins/ik/config目錄

      (2)新建一個my.dic文件,編輯內容:

      我愛學習
      

      (3)修改IKAnalyzer.cfg.xml(在ik/config目錄下)

      <properties>
      <comment>IK Analyzer 擴展配置</comment>
      <!-- 用戶可以在這里配置自己的擴展字典 -->
      <entry key="ext_dict">my.dic</entry>
      <!-- 用戶可以在這里配置自己的擴展停止詞字典 -->
      <entry key="ext_stopwords"></entry>
      </properties>
      

      注意:修改完配置后,需要重新啟動elasticsearch。

      增刪改查基本命令

      Rest風格說明

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

      基本Rest命令說明(增、刪、改、查命令):

      method ur地址 描述
      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 查詢所有數據

      三、SpringBoot集成ES

      1、新建項目

      新建一個springboot(2.2.5版)項目 elasticsearch-demo ,導入web依賴即可。

      2、配置依賴

      配置elasticsearch的依賴:

      <properties>
      <java.version>1.8</java.version>
      <!-- 這里SpringBoot默認配置的版本不匹配,我們需要自己配置版本! -->
      <elasticsearch.version>7.6.1</elasticsearch.version>
      </properties>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
      </dependency>
      

      3、編寫配置類

      編寫elasticsearch的配置類,提供RestHighLevelClient這個bean來進行操作。

      package com.hzx.config;
      
      import org.apache.http.HttpHost;
      import org.elasticsearch.client.RestClient;
      import org.elasticsearch.client.RestHighLevelClient;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      
      @Configuration
      public class ElasticsearchClientConfig {
        
        @Bean
        public RestHighLevelClient restHighLevelClient() {
          RestHighLevelClient client = new RestHighLevelClient(
            RestClient.builder(new HttpHost("127.0.0.1", 9200, "http")));
          return client;
        }
        
      }
      

      4、配置工具類

      封裝ES常用方法工具類

      package com.hzx.utils;
      
      import com.alibaba.fastjson.JSON;
      import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
      import org.elasticsearch.action.bulk.BulkRequest;
      import org.elasticsearch.action.bulk.BulkResponse;
      import org.elasticsearch.action.delete.DeleteRequest;
      import org.elasticsearch.action.delete.DeleteResponse;
      import org.elasticsearch.action.get.GetRequest;
      import org.elasticsearch.action.get.GetResponse;
      import org.elasticsearch.action.index.IndexRequest;
      import org.elasticsearch.action.index.IndexResponse;
      import org.elasticsearch.action.search.SearchRequest;
      import org.elasticsearch.action.search.SearchResponse;
      import org.elasticsearch.action.support.master.AcknowledgedResponse;
      import org.elasticsearch.action.update.UpdateRequest;
      import org.elasticsearch.action.update.UpdateResponse;
      import org.elasticsearch.client.RequestOptions;
      import org.elasticsearch.client.RestHighLevelClient;
      import org.elasticsearch.client.indices.CreateIndexRequest;
      import org.elasticsearch.client.indices.CreateIndexResponse;
      import org.elasticsearch.client.indices.GetIndexRequest;
      import org.elasticsearch.common.unit.TimeValue;
      import org.elasticsearch.common.xcontent.XContentType;
      import org.elasticsearch.index.query.QueryBuilders;
      import org.elasticsearch.rest.RestStatus;
      import org.elasticsearch.search.builder.SearchSourceBuilder;
      import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.beans.factory.annotation.Qualifier;
      import org.springframework.stereotype.Component;
      
      import java.io.IOException;
      import java.util.List;
      import java.util.concurrent.TimeUnit;
      
      @Component
      public class EsUtils<T> {
          @Autowired
          @Qualifier("restHighLevelClient")
          private RestHighLevelClient client;
      
          /**
           * 判斷索引是否存在
           *
           * @param index
           * @return
           * @throws IOException
           */
          public boolean existsIndex(String index) throws IOException {
              GetIndexRequest request = new GetIndexRequest(index);
              boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
              return exists;
          }
      
          /**
           * 創建索引
           *
           * @param index
           * @throws IOException
           */
          public boolean createIndex(String index) throws IOException {
              CreateIndexRequest request = new CreateIndexRequest(index);
              CreateIndexResponse createIndexResponse = client.indices()
                      .create(request, RequestOptions.DEFAULT);
              return createIndexResponse.isAcknowledged();
          }
      
          /**
           * 刪除索引
           *
           * @param index
           * @return
           * @throws IOException
           */
          public boolean deleteIndex(String index) throws IOException {
              DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(index);
              AcknowledgedResponse response = client.indices()
                      .delete(deleteIndexRequest, RequestOptions.DEFAULT);
              return response.isAcknowledged();
          }
      
          /**
           * 判斷某索引下文檔id是否存在
           *
           * @param index
           * @param id
           * @return
           * @throws IOException
           */
          public boolean docExists(String index, String id) throws IOException {
              GetRequest getRequest = new GetRequest(index, id);
              //只判斷索引是否存在不需要獲取_source
              getRequest.fetchSourceContext(new FetchSourceContext(false));
              getRequest.storedFields("_none_");
              boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
              return exists;
          }
      
          /**
           * 添加文檔記錄
           *
           * @param index
           * @param id
           * @param t 要添加的數據實體類
           * @return
           * @throws IOException
           */
          public boolean addDoc(String index, String id, T t) throws IOException {
              IndexRequest request = new IndexRequest(index);
              request.id(id);
              //timeout
              request.timeout(TimeValue.timeValueSeconds(1));
              request.timeout("1s");
              request.source(JSON.toJSONString(t), XContentType.JSON);
              IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
              RestStatus Status = indexResponse.status();
              return Status == RestStatus.OK || Status == RestStatus.CREATED;
          }
      
          /**
           * 根據id來獲取記錄
           *
           * @param index
           * @param id
           * @return
           * @throws IOException
           */
          public GetResponse getDoc(String index, String id) throws IOException {
              GetRequest request = new GetRequest(index, id);
              GetResponse getResponse = client.get(request,RequestOptions.DEFAULT);
              return getResponse;
          }
      
          /**
           * 批量添加文檔記錄
           * 沒有設置id ES會自動生成一個,如果要設置 IndexRequest的對象.id()即可
           *
           * @param index
           * @param list
           * @return
           * @throws IOException
           */
          public boolean bulkAdd(String index, List<T> list) throws IOException {
              BulkRequest bulkRequest = new BulkRequest();
              //timeout
              bulkRequest.timeout(TimeValue.timeValueMinutes(2));
              bulkRequest.timeout("2m");
              for (int i = 0; i < list.size(); i++) {
                  bulkRequest.add(new IndexRequest(index).source(JSON.toJSONString(list.get(i))));
              }
              BulkResponse bulkResponse = client.bulk(bulkRequest,RequestOptions.DEFAULT);
              return !bulkResponse.hasFailures();
          }
      
          /**
           * 更新文檔記錄
           * @param index
           * @param id
           * @param t
           * @return
           * @throws IOException
           */
          public boolean updateDoc(String index, String id, T t) throws IOException {
              UpdateRequest request = new UpdateRequest(index, id);
              request.doc(JSON.toJSONString(t));
              request.timeout(TimeValue.timeValueSeconds(1));
              request.timeout("1s");
              UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);
              return updateResponse.status() == RestStatus.OK;
          }
      
          /**
           * 刪除文檔記錄
           *
           * @param index
           * @param id
           * @return
           * @throws IOException
           */
          public boolean deleteDoc(String index, String id) throws IOException {
              DeleteRequest request = new DeleteRequest(index, id);
              //timeout
              request.timeout(TimeValue.timeValueSeconds(1));
              request.timeout("1s");
              DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT);
              return deleteResponse.status() == RestStatus.OK;
          }
      
          /**
           * 根據某字段來搜索
           *
           * @param index
           * @param field
           * @param key   要收搜的關鍵字
           * @throws IOException
           */
          public void search(String index, String field, String key, Integer
                  from, Integer size) throws IOException {
              SearchRequest searchRequest = new SearchRequest(index);
              SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
              sourceBuilder.query(QueryBuilders.termQuery(field, key));
              //控制搜素
              sourceBuilder.from(from);
              sourceBuilder.size(size);
              //最大搜索時間。
              sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
              searchRequest.source(sourceBuilder);
              SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
              System.out.println(JSON.toJSONString(searchResponse.getHits()));
          }
      
      }
      

      5、工具類API測試

      測試創建索引:

      @Test
      void testCreateIndex() throws IOException {
        CreateIndexRequest request = new CreateIndexRequest("test_index");
        CreateIndexResponse createIndexResponse=restHighLevelClient.indices()
          .create(request,RequestOptions.DEFAULT);
        System.out.println(createIndexResponse);
      }
      

      測試獲取索引:

      @Test
      void testExistsIndex() throws IOException {
        GetIndexRequest request = new GetIndexRequest("test_index");
        boolean exists = restHighLevelClient.indices()
          .exists(request,RequestOptions.DEFAULT);
        System.out.println(exists);
      }
      

      測試刪除索引:

      @Test
      void testDeleteIndexRequest() throws IOException {
        DeleteIndexRequest deleteIndexRequest = new
        DeleteIndexRequest("test_index");
        AcknowledgedResponse response = restHighLevelClient.indices()
          .delete(deleteIndexRequest,
        RequestOptions.DEFAULT);
        System.out.println(response.isAcknowledged());
      }
      

      測試添加文檔記錄:

      創建一個實體類User

      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      @Component
      public class User {
        private String name;
        private int age;
      }
      

      測試添加文檔記錄

      @Test
      void testAddDocument() throws IOException {
        // 創建對象
        User user = new User("zhangsan", 3);
        // 創建請求
        IndexRequest request = new IndexRequest("test_index");
        // 規則
        request.id("1");
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        request.source(JSON.toJSONString(user), XContentType.JSON);
        // 發送請求
        IndexResponse indexResponse = restHighLevelClient.index(request,
        RequestOptions.DEFAULT);
        System.out.println(indexResponse.toString());
        RestStatus Status = indexResponse.status();
        System.out.println(Status == RestStatus.OK || Status ==
        RestStatus.CREATED);
      }
      

      測試:判斷某索引下文檔id是否存在

      @Test
      void testIsExists() throws IOException {
        GetRequest getRequest = new GetRequest("test_index","1");
        // 不獲取_source上下文 storedFields
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        getRequest.storedFields("_none_");
        // 判斷此id是否存在!
        boolean exists = restHighLevelClient.exists(getRequest,
        RequestOptions.DEFAULT);
        System.out.println(exists);
      }
      

      測試:根據id獲取文檔記錄

      @Test
      void testGetDocument() throws IOException {
        GetRequest getRequest = new GetRequest("test_index","3");
        GetResponse getResponse = restHighLevelClient.get(getRequest,RequestOptions.DEFAULT);
        // 打印文檔內容
        System.out.println(getResponse.getSourceAsString()); 
        System.out.println(getResponse);
      }
      

      測試:更新文檔記錄

      @Test
      void testUpdateDocument() throws IOException {
        UpdateRequest request = new UpdateRequest("test_index","1");
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        User user = new User("zhangsan", 18);
        request.doc(JSON.toJSONString(user), XContentType.JSON);
        UpdateResponse updateResponse = restHighLevelClient.update(request, RequestOptions.DEFAULT);
        System.out.println(updateResponse.status() == RestStatus.OK);
      }
      

      測試:刪除文檔記錄

      @Test
      void testDelete() throws IOException {
      DeleteRequest request = new DeleteRequest("test_index","3");
        //timeout
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        DeleteResponse deleteResponse = restHighLevelClient.delete(
        request, RequestOptions.DEFAULT);
        System.out.println(deleteResponse.status() == RestStatus.OK);
      }
      

      測試:批量添加文檔

      @Test
      void testBulkRequest() throws IOException {
        
      	BulkRequest bulkRequest = new BulkRequest();
        //timeout
        bulkRequest.timeout(TimeValue.timeValueMinutes(2));
        bulkRequest.timeout("2m");
        
        ArrayList<User> userList = new ArrayList<>();
        userList.add(new User("zhangsan1",3));
        userList.add(new User("zhangsan2",3));
        userList.add(new User("zhangsan3",3));
        userList.add(new User("lisi1",3));
        userList.add(new User("lisi2",3));
        userList.add(new User("lisi3",3));
        
        for (int i =0;i<userList.size();i++){
        	bulkRequest.add(new IndexRequest("test_index").id(""+(i+1))
                          .source(JSON.toJSONString(userList.get(i)),XContentType.JSON));
        } 
        // bulk
        BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
        System.out.println(!bulkResponse.hasFailures());
      }
      

      查詢測試:

      /**
      * 使用QueryBuilder
      * termQuery("key", obj) 完全匹配
      * termsQuery("key", obj1, obj2..) 一次匹配多個值
      * matchQuery("key", Obj) 單個匹配, field不支持通配符, 前綴具高級特性
      * multiMatchQuery("text", "field1", "field2"..); 匹配多個字段, field有通配符忒行
      * matchAllQuery(); 匹配所有文件
      */
      @Test
      void testSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("test_index");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name","zhangsan1");
        MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
        sourceBuilder.query(matchAllQueryBuilder);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(sourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
        System.out.println(JSON.toJSONString(response.getHits()));
        
        System.out.println("================查詢高亮顯示==================");
        for (SearchHit documentFields : response.getHits().getHits()) {
        	System.out.println(documentFields.getSourceAsMap());
        }
      }
      
      posted @ 2022-05-19 16:06  HZX↑  閱讀(490)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 不卡高清AV手机在线观看| 澳门永久av免费网站| 久女女热精品视频在线观看| 99精品国产中文字幕| 水蜜桃视频在线观看免费18| 草裙社区精品视频播放| 99中文字幕精品国产| 一个色的导航| 国产又黄又爽又不遮挡视频 | 国产精品白嫩极品在线看| 国产精品入口麻豆| 国产成人精品18| 日韩在线观看 一区二区| 亚洲精品国产自在现线最新| 精品 无码 国产观看| 亚洲成av一区二区三区| 国产精品欧美一区二区三区不卡| 免费观看成人毛片a片| 精品国产中文字幕av| 亚洲成aⅴ人在线观看| 无码中文字幕人妻在线一区| 国产肥妇一区二区熟女精品| 亚洲乱码中文字幕小综合| 久久这里有精品国产电影网| 精品人妻少妇嫩草av系列| 国产精品揄拍100视频| 91老肥熟女九色老女人| 亚洲国产天堂久久综合226114| 77777亚洲午夜久久多人| 久久热这里只有精品66| 3d无码纯肉动漫在线观看| 少妇做爰免费视看片| 亚洲第一香蕉视频啪啪爽| 爱情岛亚洲论坛成人网站| 国产片AV国语在线观看手机版| 精品久久人人妻人人做精品| 欧美日韩一区二区三区视频播放| 婷婷久久综合九色综合88| 好看的国产精品自拍视频| 国产小受被做到哭咬床单GV| 国产成人欧美日本在线观看|