5566中文字幕一区二区电影_国产精品亚洲一区二区三区_亚洲精品国产精品乱码不99按摩 _国产精品美女久久久久av爽李琼_久久亚洲综合色一区二区三区_疯狂蹂躏欧美一区二区精品_日韩h在线观看_亚洲欧美日韩中文视频_国产精品日韩欧美综合_中日韩av电影

您的位置:首頁 > 要聞 > 正文

【ES三周年】萬字長文帶你實戰 Elasticsearch 搜索

ES 高級實戰

前言

上篇我們講到了 Elasticsearch 全文檢索的原理《別只會搜日志了,求你懂點原理吧》,通過在本地搭建一套 ES 服務,以多個案例來分析了 ES 的原理以及基礎使用。這次我們來講下 Spring Boot 中如何整合 ES,以及如何在 Spring Cloud 微服務項目中使用 ES 來實現全文檢索,來達到搜索題庫的功能。

而且題庫的數據量是非常大的,題目的答案也是非常長的,通過 ES 正好可以解決 mysql 模糊搜索的低效性。


(相關資料圖)

通過本實戰您可以學到如下知識點:

Spring Boot 如何整合 ES。微服務中 ES 的 API 使用。項目中如何使用 ES 來達到全文檢索。

本篇主要內容如下:

主要內容

本文案例都是基于 PassJava 實戰項目來演示的。

:+1:Github 地址:https://github.com/Jackson0714/PassJava-Platform

一、Elasticsearch 組件庫介紹

在講解之前,我在這里再次提下全文檢索是什么:

全文檢索:指以全部文本信息作為檢索對象的一種信息檢索技術。而我們使用的數據庫,如 Mysql,MongoDB 對文本信息檢索能力特別是中文檢索并沒有 ES 強大。所以我們來看下 ES 在項目中是如何來代替 SQL 來工作的。

我使用的 Elasticsearch 服務是 7.4.2 的版本,然后采用官方提供的 Elastiscsearch-Rest-Client 庫來操作 ES,而且官方庫的 API 上手簡單。

該組件庫的官方文檔地址:

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html

另外這個組件庫是支持多種語言的:

支持多語言

注意:Elasticsearch Clients就是指如何用 API 操作 ES 服務的組件庫。

可能有同學會提問,Elasticsearch 的組件庫中寫著 JavaScript API,是不是可以直接在前端訪問 ES 服務?可以是可以,但是會暴露 ES 服務的端口和 IP 地址,會非常不安全。所以我們還是用后端服務來訪問 ES 服務。

我們這個項目是 Java 項目,自然就是用上面的兩種:Java Rest Client或者 Java API。我們先看下 Java API,但是會發現已經廢棄了。如下圖所示:

Java API 已經廢棄了

所以我們只能用 Java REST Client 了。而它又分成兩種:高級和低級的。高級包含更多的功能,如果把高級比作MyBatis的話,那么低級就相當于JDBC。所以我們用高級的 Client。

高級和低級 Client

二、整合檢索服務

我們把檢索服務單獨作為一個服務。就稱作 passjava-search 模塊吧。

1.1 添加搜索服務模塊

創建 passjava-search 模塊。

首先我們在 PassJava-Platform 模塊創建一個 搜索服務模塊 passjava-search。然后勾選 spring web 服務。如下圖所示。

第一步:選擇 Spring Initializr,然后點擊 Next。

選擇 Spring Initializr

第二步:填寫模塊信息,然后點擊 Next。

passjava-search 服務模塊

第三步:選擇 Web->Spring Web 依賴,然后點擊 Next。

mark

1.2 配置 Maven 依賴

參照 ES 官網配置。

進入到 ES 官方網站,可以看到有低級和高級的 Rest Client,我們選擇高階的(High Level Rest Client)。然后進入到高階 Rest Client 的 Maven 倉庫。官網地址如下所示:

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.9/index.html
Rest Client 官方文檔
加上 Maven 依賴。

對應文件路徑:\passjava-search\pom.xml

    org.elasticsearch.client    elasticsearch-rest-high-level-client    7.4.2
配置 elasticsearch 的版本為7.4.2

因加上 Maven 依賴后,elasticsearch 版本為 7.6.2,所以遇到這種版本不一致的情況時,需要手動改掉。

對應文件路徑:\passjava-search\pom.xml

7.4.2

刷新 Maven Project 后,可以看到引入的 elasticsearch 都是 7.4.2 版本了,如下圖所示:

設置版本為 7.4.2
引入 PassJava 的 Common 模塊依賴。

Common 模塊是 PassJava 項目獨立的出來的公共模塊,引入了很多公共組件依賴,其他模塊引入 Common 模塊依賴后,就不需要單獨引入這些公共組件了,非常方便。

對應文件路徑:\passjava-search\pom.xml

     com.jackson0714.passjava     passjava-common     0.0.1-SNAPSHOT

添加完依賴后,我們就可以將搜索服務注冊到 Nacos注冊中心了。 Nacos 注冊中心的用法在前面幾篇文章中也詳細講解過,這里需要注意的是要先啟動 Nacos 注冊中心,才能正常注冊 passjava-search 服務。

1.3 注冊搜索服務到注冊中心

修改配置文件:src/main/resources/application.properties。配置應用程序名、注冊中心地址、注冊中心的命名中間。

spring.application.name=passjava-searchspring.cloud.nacos.config.server-addr=127.0.0.1:8848spring.cloud.nacos.config.namespace=passjava-search

啟動類添加服務發現注解:@EnableDiscoveryClient。這樣 passjava-search 服務就可以被注冊中心發現了。

因 Common 模塊依賴數據源,但 search 模塊不依賴數據源,所以 search 模塊需要移除數據源依賴:

exclude = DataSourceAutoConfiguration.class

以上的兩個注解如下所示:

@EnableDiscoveryClient@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)public class PassjavaSearchApplication {    public static void main(String[] args) {        SpringApplication.run(PassjavaSearchApplication.class, args);    }}

接下來我們添加一個 ES 服務的專屬配置類,主要目的是自動加載一個 ES Client 來供后續 ES API 使用,不用每次都 new 一個 ES Client。

1.4 添加 ES 配置類

配置類:PassJavaElasticsearchConfig.java

核心方法就是 RestClient.builder 方法,設置好 ES 服務的 IP 地址、端口號、傳輸協議就可以了。最后自動加載了 RestHighLevelClient。

package com.jackson0714.passjava.search.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;/** * @Author: 公眾號 | 悟空聊架構 * @Date: 2020/10/8 17:02 * @Site: www.passjava.cn * @Github: https://github.com/Jackson0714/PassJava-Platform */@Configurationpublic class PassJavaElasticsearchConfig {    @Bean    // 給容器注冊一個 RestHighLevelClient,用來操作 ES    // 參考官方文檔:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.9/java-rest-high-getting-started-initialization.html    public RestHighLevelClient restHighLevelClient() {        return new RestHighLevelClient(                RestClient.builder(                        new HttpHost("192.168.56.10", 9200, "http")));    }}

接下來我們測試下 ES Client 是否自動加載成功。

1.5 測試 ES Client 自動加載

在測試類 PassjavaSearchApplicationTests 中編寫測試方法,打印出自動加載的 ES Client。期望結果是一個 RestHighLevelClient 對象。

package com.jackson0714.passjava.search;import org.elasticsearch.client.RestHighLevelClient;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTestclass PassjavaSearchApplicationTests {    @Qualifier("restHighLevelClient")    @Autowired    private RestHighLevelClient client;    @Test    public void contextLoads() {        System.out.println(client);    }}

運行結果如下所示,打印出了 RestHighLevelClient。說明自定義的 ES Client 自動裝載成功。

ES 測試結果

1.6 測試 ES 簡單插入數據

測試方法 testIndexData,省略 User 類。users 索引在我的 ES 中是沒有記錄的,所以期望結果是 ES 中新增了一條 users 數據。

/** * 測試存儲數據到 ES。 * */@Testpublic void testIndexData() throws IOException {    IndexRequest request = new IndexRequest("users");    request.id("1"); // 文檔的 id        //構造 User 對象    User user = new User();    user.setUserName("PassJava");    user.setAge("18");    user.setGender("Man");        //User 對象轉為 JSON 數據    String jsonString = JSON.toJSONString(user);        // JSON 數據放入 request 中    request.source(jsonString, XContentType.JSON);    // 執行插入操作    IndexResponse response = client.index(request, RequestOptions.DEFAULT);    System.out.println(response);}

執行 test 方法,我們可以看到控制臺輸出以下結果,說明數據插入到 ES 成功。另外需要注意的是結果中的 result 字段為 updated,是因為我本地為了截圖,多執行了幾次插入操作,但因為 id = 1,所以做的都是 updated 操作,而不是 created 操作。

控制臺輸出結果

我們再來到 ES 中看下 users 索引中數據。查詢 users 索引:

GET users/_search

結果如下所示:

查詢 users 索引結果

可以從圖中看到有一條記錄被查詢出來,查詢出來的數據的 _id = 1,和插入的文檔 id 一致。另外幾個字段的值也是一致的。說明插入的數據沒有問題。

"age" : "18","gender" : "Man","userName" : "PassJava"

1.7 測試 ES 查詢復雜語句

示例:搜索 bank 索引,address 字段中包含 big 的所有人的年齡分布 ( 前 10 條 ) 以及平均年齡,以及平均薪資。

1.7.1 構造檢索條件

我們可以參照官方文檔給出的示例來創建一個 SearchRequest 對象,指定要查詢的索引為 bank,然后創建一個 SearchSourceBuilder 來組裝查詢條件。總共有三種條件需要組裝:

address 中包含 road 的所有人。按照年齡分布進行聚合。計算平均薪資。

代碼如下所示,需要源碼請到我的 Github/PassJava 上下載。

查詢復雜語句示例

將打印出來的檢索參數復制出來,然后放到 JSON 格式化工具中格式化一下,再粘貼到 ES 控制臺執行,發現執行結果是正確的。

打印出檢索參數

用在線工具格式化 JSON 字符串,結果如下所示:

格式化 JSON 字符串

然后我們去掉其中的一些默認參數,最后簡化后的檢索參數放到 Kibana 中執行。

Kibana Dev Tools 控制臺中執行檢索語句如下圖所示,檢索結果如下圖所示:

控制臺中執行檢索語句

找到總記錄數:29 條。

第一條命中記錄的詳情如下:

平均 balance:13136。

平均年齡:26。

地址中包含 Road 的:263 Aviation Road。

和 IDEA 中執行的測試結果一致,說明復雜檢索的功能已經成功實現。

17.2 獲取命中記錄的詳情

而獲取命中記錄的詳情數據,則需要通過兩次 getHists() 方法拿到,如下所示:

// 3.1)獲取查到的數據。SearchHits hits = response.getHits();// 3.2)獲取真正命中的結果SearchHit[] searchHits = hits.getHits();

我們可以通過遍歷 searchHits 的方式打印出所有命中結果的詳情。

// 3.3)、遍歷命中結果for (SearchHit hit: searchHits) {    String hitStr = hit.getSourceAsString();    BankMember bankMember = JSON.parseObject(hitStr, BankMember.class);}

拿到每條記錄的 hitStr 是個 JSON 數據,如下所示:

{"account_number": 431,"balance": 13136,"firstname": "Laurie","lastname": "Shaw","age": 26,"gender": "F","address": "263 Aviation Road","employer": "Zillanet","email": "laurieshaw@zillanet.com","city": "Harmon","state": "WV"}

而 BankMember 是根據返回的結果詳情定義的的 JavaBean。可以通過工具自動生成。在線生成 JavaBean 的網站如下:

https://www.bejson.com/json2javapojo/new/

把這個 JavaBean 加到 PassjavaSearchApplicationTests 類中:

@ToString@Datastatic class BankMember {    private int account_number;    private int balance;    private String firstname;    private String lastname;    private int age;    private String gender;    private String address;    private String employer;    private String email;    private String city;    private String state;}

然后將 bankMember 打印出來:

System.out.println(bankMember);
bankMember

得到的結果確實是我們封裝的 BankMember 對象,而且里面的屬性值也都拿到了。

1.7.3 獲取年齡分布聚合信息

ES 返回的 response 中,年齡分布的數據是按照 ES 的格式返回的,如果想按照我們自己的格式來返回,就需要將 response 進行處理。

如下圖所示,這個是查詢到的年齡分布結果,我們需要將其中某些字段取出來,比如 buckets,它代表了分布在 21 歲的有 4 個。

ES 返回的年齡分布信息

下面是代碼實現:

Aggregations aggregations = response.getAggregations();Terms ageAgg1 = aggregations.get("ageAgg");for (Terms.Bucket bucket : ageAgg1.getBuckets()) {    String keyAsString = bucket.getKeyAsString();    System.out.println("用戶年齡: " + keyAsString + " 人數:" + bucket.getDocCount());}

最后打印的結果如下,21 歲的有 4 人,26 歲的有 4 人,等等。

打印結果:用戶年齡分布

1.7.4 獲取平均薪資聚合信息

現在來看看平均薪資如何按照所需的格式返回,ES 返回的結果如下圖所示,我們需要獲取 balanceAvg 字段的 value 值。

ES 返回的平均薪資信息

代碼實現:

Avg balanceAvg1 = aggregations.get("balanceAvg");System.out.println("平均薪資:" + balanceAvg1.getValue());

打印結果如下,平均薪資 28578 元。

打印結果:平均薪資

三、實戰:同步 ES 數據

3.1 定義檢索模型

PassJava 這個項目可以用來配置題庫,如果我們想通過關鍵字來搜索題庫,該怎么做呢?

類似于百度搜索,輸入幾個關鍵字就可以搜到關聯的結果,我們這個功能也是類似,通過 Elasticsearch 做檢索引擎,后臺管理界面和小程序作為搜索入口,只需要在小程序上輸入關鍵字,就可以檢索相關的題目和答案。

首先我們需要把題目和答案保存到 ES 中,在存之前,第一步是定義索引的模型,如下所示,模型中有 titleanswer字段,表示題目和答案。

"id": {    "type": "long"},"title": {    "type": "text",    "analyzer": "ik_smart"},"answer": {    "type": "text",    "analyzer": "ik_smart"},"typeName": {    "type": "keyword"}

3.2 在 ES 中創建索引

上面我們已經定義了索引結構,接著就是在 ES 中創建索引。

在 Kibana 控制臺中執行以下語句:

PUT question{"mappings" : {    "properties": {  "id": {  "type": "long"  },  "title": {  "type": "text",  "analyzer": "ik_smart"  },  "answer": {  "type": "text",  "analyzer": "ik_smart"  },  "typeName": {  "type": "keyword"  }}  }}

執行結果如下所示:

創建 question 索引

我們可以通過以下命令來查看 question 索引是否在 ES 中:

GET _cat/indices

執行結果如下圖所示:

查看 ES 中所有的索引

3.3 定義 ES model

上面我們定義 ES 的索引,接著就是定義索引對應的模型,將數據存到這個模型中,然后再存到 ES 中。

ES 模型如下,共四個字段:id、title、answer、typeName。和 ES 索引是相互對應的。

@Datapublic class QuestionEsModel {    private Long id;    private String title;    private String answer;    private String typeName;}

3.4 觸發保存的時機

當我們在后臺創建題目或保存題目時,先將數據保存到 mysql 數據庫,然后再保存到 ES 中。

如下圖所示,在管理后臺創建題目時,觸發保存數據到 ES 。

mark

第一步,保存數據到 mysql 中,項目中已經包含此功能,就不再講解了,直接進入第二步:保存數據到 ES 中。

而保存數據到 ES 中,需要將數據組裝成 ES 索引對應的數據,所以我用了一個 ES model,先將數據保存到 ES model 中。

3.5 用 model 來組裝數據

這里的關鍵代碼時 copyProperties,可以將 question對象的數據取出,然后賦值到 ES model 中。不過 ES model 中還有些字段是 question 中沒有的,所以需要單獨拎出來賦值,比如 typeName 字段,question 對象中沒有這個字段,它對應的字段是 question.type,所以我們把 type 取出來賦值到 ES model 的 typeName 字段上。如下圖所示:

用 model 來組裝數據

3.6 保存數據到 ES

我在 passjava-search 微服務中寫了一個保存題目的 api 用來保存數據到 ES 中。

保存數據到 ES

然后在 passjava-question 微服務中調用 search 微服務的保存 ES 的方法就可以了。

// 調用 passjava-search 服務,將數據發送到 ES 中保存。searchFeignService.saveQuestion(esModel);

3.7 檢驗 ES 中是否創建成功

我們可以通過 kibana 的控制臺來查看 question 索引中的文檔。通過以下命令來查看:

GET question/_search

執行結果如下圖所示,有一條記錄:

mark

另外大家有沒有疑問:可以重復更新題目嗎?

答案是可以的,保存到 ES 的數據是冪等的,因為保存的時候帶了一個類似數據庫主鍵的 id。

四、實戰:查詢 ES 數據

我們已經將數據同步到了 ES 中,現在就是前端怎么去查詢 ES 數據中,這里我們還是使用 Postman 來模擬前端查詢請求。

4.1 定義請求參數

請求參數我定義了三個:

keyword:用來匹配問題或者答案。id:用來匹配題目 id。pageNum:用來分頁查詢數據。

這里我將這三個參數定義為一個類:

@Datapublic class SearchParam {    private String keyword; // 全文匹配的關鍵字    private String id; // 題目 id    private Integer pageNum; // 查詢第幾頁數據}

4.2 定義返回參數

返回的 response 我也定義了四個字段:

questionList:查詢到的題目列表。pageNum:第幾頁數據。total:查詢到的總條數。totalPages:總頁數。

定義的類如下所示:

@Datapublic class SearchQuestionResponse {    private List questionList; // 題目列表    private Integer pageNum; // 查詢第幾頁數據    private Long total; // 總條數    private Integer totalPages; // 總頁數}

4.3 組裝 ES 查詢參數

調用 ES 的查詢 API 時,需要構建查詢參數。

組裝查詢參數的核心代碼如下所示:

組裝查詢參數
第一步:創建檢索請求。第二步:設置哪些字段需要模糊匹配。這里有三個字段:title,answer,typeName。第三步:設置如何分頁。這里分頁大小是 5 個。第四步:調用查詢 api。

4.4 格式化 ES 返回結果

ES 返回的數據是 ES 定義的格式,真正的數據被嵌套在 ES 的 response 中,所以需要格式化返回的數據。

核心代碼如下圖所示:

格式化 ES 返回結果
第一步:獲取查到的數據。第二步:獲取真正命中的結果。第三步:格式化返回的數據。第四步:組裝分頁參數。

4.5 測試 ES 查詢

4.5.1 實驗一:測試 title 匹配

我們現在想要驗證 title 字段是否能匹配到,傳的請求參數 keyword = 111,匹配到了 title = 111 的數據,且只有一條。頁碼 pageNum 我傳的 1,表示返回第一頁數據。如下圖所示:

測試匹配 title

4.5.2 實驗二:測試 answer 匹配

我們現在想要驗證 answer 字段是否能匹配到,傳的請求參數 keyword = 測試答案,匹配到了 title = 測試答案的數據,且只有一條,說明查詢成功。如下圖所示:

測試匹配 answer

4.5.2 實驗三:測試 id 匹配

我們現在想要匹配題目 id 的話,需要傳請求參數 id,而且 id 是精確匹配。另外 id 和 keyword 是取并集,所以不能傳 keyword 字段。

請求參數 id = 5,返回結果也是 id =5 的數據,說明查詢成功。如下圖所示:

測試 id 匹配

五、總結

本文通過我的開源項目 passjava 來講解 ES 的整合,ES 的 API 使用以及測試。非常詳細地講解了每一步該如何做,相信通過閱讀本篇后,再加上自己的實踐,一定能掌握前后端該如何使用 ES 來達到高效搜索的目的。

當然,ES API 還有很多功能未在本文實踐,有興趣的同學可以到 ES 官網進行查閱和學習。

關鍵詞: Java ElasticsearchService

5566中文字幕一区二区电影_国产精品亚洲一区二区三区_亚洲精品国产精品乱码不99按摩 _国产精品美女久久久久av爽李琼_久久亚洲综合色一区二区三区_疯狂蹂躏欧美一区二区精品_日韩h在线观看_亚洲欧美日韩中文视频_国产精品日韩欧美综合_中日韩av电影
盗摄精品av一区二区三区| 99这里都是精品| 国产suv精品一区二区三区| 91精品在线麻豆| 亚洲视频在线观看三级| 国产一二三精品| 日韩欧美一区在线观看| 日日夜夜免费精品| 欧美二区乱c少妇| 欧美高清dvd| 亚洲三级小视频| 成人毛片视频在线观看| 国产午夜精品一区二区 | 国产精品资源在线看| 精品理论电影在线| 成熟亚洲日本毛茸茸凸凹| 欧美日韩一区在线| 午夜精品福利一区二区三区蜜桃| 欧美日韩激情一区二区| 青青草成人在线观看| 26uuu久久天堂性欧美| 精品免费99久久| 亚洲伦在线观看| 欧美精品自拍偷拍| 国产福利精品导航| 亚洲一级电影视频| 亚洲黄色录像片| 欧美一区二区三区视频| 国产在线播精品第三| 中文字幕一区二区不卡| 欧美日本国产一区| 国内精品第一页| 成人欧美一区二区三区视频网页| 一本久道久久综合中文字幕| 亚洲国产精品久久久久婷婷884| 日韩一区有码在线| 99热精品一区二区| 美女国产一区二区三区| 久久久久久久精| 日本高清不卡aⅴ免费网站| 日韩二区在线观看| 国产精品污网站| 欧美二区三区91| 成人在线综合网站| 欧美一区二区在线观看| 日本不卡中文字幕| 国产精品网站在线观看| 欧美一区二区三区婷婷月色| 成人午夜av影视| 日韩av电影免费观看高清完整版在线观看 | 欧美日韩亚洲综合在线 欧美亚洲特黄一级| 亚洲卡通动漫在线| 欧美日韩国产美| 成人综合婷婷国产精品久久蜜臀| 婷婷夜色潮精品综合在线| 日本一区二区免费在线观看视频| 欧美日韩国产首页在线观看| 不卡的av在线播放| 麻豆精品视频在线观看视频| 一区二区三区中文字幕精品精品 | 午夜精品一区二区三区免费视频| 久久免费午夜影院| 欧美日韩视频在线一区二区| 成人网页在线观看| 国产一区二区三区蝌蚪| 日韩精品一级二级 | 国产成人综合亚洲网站| 国产偷v国产偷v亚洲高清| 日韩欧美久久久| 欧美精品精品一区| 欧美日韩国产首页| 色综合久久综合网97色综合| 免费观看30秒视频久久| 美女性感视频久久| 一区二区三区精品在线观看| 精品国产网站在线观看| 欧美刺激脚交jootjob| 日韩av一级电影| 亚洲国产中文字幕在线视频综合| 亚洲精品乱码久久久久久黑人| 日韩毛片高清在线播放| 亚洲日本丝袜连裤袜办公室| 26uuu色噜噜精品一区| 6080yy午夜一二三区久久| 欧美精品色综合| 欧美一区二区三区人| 精品国产伦理网| 欧美少妇bbb| 精品毛片乱码1区2区3区| 欧美一级黄色录像| 国产日韩综合av| 国产精品国产三级国产a | 国产日韩欧美一区二区三区综合| 国产拍揄自揄精品视频麻豆| 亚洲天堂成人网| 免费亚洲电影在线| 国产精品中文字幕欧美| 日韩欧美综合一区| 2024国产精品| 有码一区二区三区| 麻豆91免费观看| 99久久精品免费精品国产| 久久久激情视频| 久久久久久久久久久电影| 亚洲精品大片www| 亚洲欧美日韩系列| 国产精品一区免费在线观看| 激情另类小说区图片区视频区| 91在线免费视频观看| 日韩一区二区三区视频| 亚洲人成网站在线| 久久99国产精品尤物| 色婷婷激情一区二区三区| 日韩手机在线导航| 一区二区三区高清在线| 国产一区二区伦理| 色激情天天射综合网| 亚洲欧美日韩一区二区三区在线观看| 国产91在线观看丝袜| 成人黄色av电影| 精品99久久久久久| 午夜精品一区二区三区三上悠亚 | 欧美精品在线观看播放| 国产丝袜在线精品| 韩国av一区二区三区| 91精品国产欧美日韩| 亚洲精品视频在线看| 天堂av在线一区| 欧美午夜一区二区| 一二三区精品视频| 成人爽a毛片一区二区免费| 26uuu国产日韩综合| 国产在线观看一区二区| 色狠狠桃花综合| 亚洲免费av观看| 91国产免费观看| 一区二区三区在线看| 暴力调教一区二区三区| 中文字幕精品一区| 中文一区一区三区高中清不卡| 精品一区二区三区在线观看| 日韩精品一区二区三区在线播放| 日本午夜精品视频在线观看| 555夜色666亚洲国产免| 日产欧产美韩系列久久99| 日韩精品一区二区三区蜜臀| 亚洲人成网站色在线观看| 日韩电影在线一区二区| 日韩免费高清av| 国产成人日日夜夜| 91精品免费在线| 国产呦萝稀缺另类资源| 中文字幕国产一区| 成人app在线观看| 亚洲啪啪综合av一区二区三区| 色8久久人人97超碰香蕉987| 亚洲成av人片| 欧美一级黄色大片| 国产.欧美.日韩| 亚洲欧美日韩电影| 欧美大尺度电影在线| 国产成人综合亚洲91猫咪| av一区二区久久| 综合欧美一区二区三区| 在线播放中文字幕一区| 国产精品99久久久久久宅男| 免费成人在线观看| 日韩欧美国产一区二区三区| 岛国一区二区在线观看| 亚洲第一成年网| 久久精品网站免费观看| 一本到不卡精品视频在线观看 | 欧美色图一区二区三区| 六月丁香综合在线视频| 亚洲欧美一区二区三区孕妇| 色94色欧美sute亚洲线路一ni| 久久er精品视频| 亚洲影视在线观看| 国产精品卡一卡二| 日韩一区二区在线看| 色综合久久中文字幕| 欧美日韩大陆在线| 一区二区三区精品在线观看| 26uuu国产一区二区三区| 综合自拍亚洲综合图不卡区| 在线不卡免费欧美| 一本到一区二区三区| 成人亚洲一区二区一| 韩日欧美一区二区三区| 午夜精品久久久久久久99水蜜桃 | 欧美国产国产综合| 日韩视频在线永久播放| 欧美日韩精品三区| 一本大道综合伊人精品热热 | 亚洲女人的天堂| 国产成人在线视频播放| 国产日韩欧美电影| 久久久精品综合| 久久久久久久久免费| 久久亚洲一级片|