深入淺出 autocomplete
Kewang, Funliday
Kewang
●
王慕羣 Kewang
●
JavaScript / Java
●
PostgreSQL / MongoDB / Elasticsearch / HBase
●
Git / DevOps
●
熱愛開源
Linkedin
Linkedin kewangtw
kewangtw
SlideShare
SlideShare kewang
kewang
Gmail
Gmail cpckewang
cpckewang
Facebook
Facebook Kewang 的資訊進化論
Kewang 的資訊進化論
devopsday taipei
devopsday taipei '17
'17
hadoopcon
hadoopcon '14 '15
'14 '15
jcconf
jcconf '16 '17 '18
'16 '17 '18
GitHub
GitHub kewang
kewang
Funliday
Funliday kewang
kewang
mopcon
mopcon '14 '20
'14 '20
modernweb
modernweb '18 '19 '20 '21
'18 '19 '20 '21
coscup
coscup '20 '21
'20 '21
4
分享的內容
5
分享的內容
6
分享的內容
1.一點點的前端 autocomplete Live DEMO
7
分享的內容
1.一點點的前端 autocomplete Live DEMO
2.在後端使用 Redis 實作 autocomplete
8
分享的內容
1.一點點的前端 autocomplete Live DEMO
2.在後端使用 Redis 實作 autocomplete
3.在後端使用 Elasticsearch 實作 autocomplete
9
分享的內容
1.一點點的前端 autocomplete Live DEMO
2.在後端使用 Redis 實作 autocomplete
3.在後端使用 Elasticsearch 實作 autocomplete
4.各種使用情境
10
開始
11
什麼是 autocomplete ?
12
什麼是 autocomplete ?
●
將使用者輸入的文字,使用前綴比對 (prefix
match) 資料庫,成功回傳對應的待選詞
(candidates)
13
什麼是 autocomplete ?
●
將使用者輸入的文字,使用前綴比對 (prefix
match) 資料庫,成功回傳對應的待選詞
(candidates)
●
從使用者輸入文字到回傳待選詞的速度要夠快
14
以往的 autocomplete 分享
15
以往的 autocomplete 分享
16
以往的 autocomplete 分享
●
debounce :同樣 function 連續觸發時只執行一次
17
以往的 autocomplete 分享
●
debounce :同樣 function 連續觸發時只執行一次
●
throttle :同樣 function 連續觸發時降低執行頻率
18
以往的 autocomplete 分享
●
debounce :同樣 function 連續觸發時只執行一次
●
throttle :同樣 function 連續觸發時降低執行頻率
●
Live DEMO
19
以往的 autocomplete 分享
●
debounce :同樣 function 連續觸發時只執行一次
●
throttle :同樣 function 連續觸發時降低執行頻率
●
Live DEMO
後端內容好少 ...
20
本次分享以後端為主
21
先來看看 autocomplete 的基礎
22
autocomplete 的基礎在於資料完整性
23
autocomplete 的基礎在於資料完整性
●
資料量小且定量
24
autocomplete 的基礎在於資料完整性
●
資料量小且定量
– 前端處理更快速
25
autocomplete 的基礎在於資料完整性
●
資料量小且定量
– 前端處理更快速
●
資料量大且不定量
26
autocomplete 的基礎在於資料完整性
●
資料量小且定量
– 前端處理更快速
●
資料量大且不定量
– 後端使用資料庫
27
最直覺的開發方式
28
直接使用 RDBMS
29
直接使用 RDBMS
30
直接使用 RDBMS 使用 LIKE 比對資料庫內容
31
直接使用 RDBMS 使用 LIKE 比對資料庫內容
依照字典升序排序取出前 10 個
32
問題點
33
問題點
●
資料量大時,需要對 name 建立 index
34
問題點
●
資料量大時,需要對 name 建立 index
●
並非一定會使用 index ,需視 query plan 而定
35
改用 Redis 試試
36
Redis
37
Redis
●
所有資料都存放在記憶體
38
Redis
●
所有資料都存放在記憶體
●
低延遲和高輸送量
39
Redis
●
所有資料都存放在記憶體
●
低延遲和高輸送量
●
讀寫操作時間低於 1ms
40
Redis
●
所有資料都存放在記憶體
●
低延遲和高輸送量
●
讀寫操作時間低於 1ms
●
支援每秒百萬個操作
41
先介紹 Sorted Set
42
先介紹 Sorted Set
●
Redis 的一種資料型態
43
先介紹 Sorted Set
●
Redis 的一種資料型態
●
使用分數 (score) 做為排序的順序
44
先介紹 Sorted Set
●
Redis 的一種資料型態
●
使用分數 (score) 做為排序的順序
●
若分數相同,則使用字典排序做為順序
45
索引階段 - 正規化文字 ( 以 Taïwan 為例 )
46
索引階段 - 正規化文字 ( 以 Taïwan 為例 )
47
索引階段 - 正規化文字 ( 以 Taïwan 為例 )
1. 先標準化拆解
48
索引階段 - 正規化文字 ( 以 Taïwan 為例 )
1. 先標準化拆解
2. 再移除附加符號
49
索引階段 - 正規化文字 ( 以 Taïwan 為例 )
1. 先標準化拆解
2. 再移除附加符號 3. 最後全部轉為小寫
50
索引階段 - 使用 ZADD 儲存
51
索引階段 - 使用 ZADD 儲存
t
ta
tai
taip
taipe
taipei
taipei*
52
索引階段 - 使用 ZADD 儲存
表示為完整的 candidate
t
ta
tai
taip
taipe
taipei
taipei*
53
索引階段 - 使用 ZADD 儲存
t
ta
tai
taip
taipe
taipei
taipei*
表示為完整的 candidate
ZADD 儲存到 Redis
t
ta
tai
taip
taipe
taipei
taipei*
54
索引階段 - 使用 ZADD 儲存
t
ta
tai
taip
taipe
taipei
taipei*
表示為完整的 candidate
ZADD 儲存到 Redis
t
ta
tai
taip
taipe
taipei
taipei*
t
ta
tai
taiw
taiwa
taiwan
taiwan*
55
索引階段 - 使用 ZADD 儲存
t
ta
tai
taip
taipe
taipei
taipei*
taiw
taiwa
taiwan
taiwan*
表示為完整的 candidate
ZADD 儲存到 Redis
t
ta
tai
taip
taipe
taipei
taipei*
t
ta
tai
taiw
taiwa
taiwan
taiwan*
ZADD 儲存到 Redis
56
索引階段 - 使用 ZADD 儲存
57
索引階段 - 使用 ZADD 儲存
58
索引階段 - 使用 ZADD 儲存
score
59
索引階段 - 使用 ZADD 儲存
score
candidate
60
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
61
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
ta
62
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
使用者輸入
ta
63
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
ta
使用者輸入
ta
64
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
ZRANK 定位
ta
使用者輸入
ta
65
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
t
ta
tai
taip
taipe
taipei
taipei*
taiw
taiwa
taiwan
taiwan*
ZRANK 定位
ta
使用者輸入
ta
66
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
t
ta
tai
taip
taipe
taipei
taipei*
taiw
taiwa
taiwan
taiwan*
ZRANK 定位
ta
回傳
使用者輸入
ta
67
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
t
ta
tai
taip
taipe
taipei
taipei*
taiw
taiwa
taiwan
taiwan*
ZRANK 定位
ta
回傳
2
使用者輸入
ta
68
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
t
ta
tai
taip
taipe
taipei
taipei*
taiw
taiwa
taiwan
taiwan*
ZRANK 定位
ta
ZRANGE 取得 2 後面 n 個
回傳
2
使用者輸入
ta
69
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
t
ta
tai
taip
taipe
taipei
taipei*
taiw
taiwa
taiwan
taiwan*
ZRANK 定位
ta
ZRANGE 取得 2 後面 n 個
回傳
2
回傳
使用者輸入
ta
70
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
t
ta
tai
taip
taipe
taipei
taipei*
taiw
taiwa
taiwan
taiwan*
ZRANK 定位
ta
ZRANGE 取得 2 後面 n 個
回傳
2
回傳
ta
tai
taip
taipe
taipei
taipei*
taiw
taiwa
taiwan
taiwan*
使用者輸入
ta
71
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
t
ta
tai
taip
taipe
taipei
taipei*
taiw
taiwa
taiwan
taiwan*
ZRANK 定位
ta
ZRANGE 取得 2 後面 n 個
回傳
2
回傳
ta
tai
taip
taipe
taipei
taipei*
taiw
taiwa
taiwan
taiwan*
整理後回傳使用者
使用者輸入
ta
72
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
t
ta
tai
taip
taipe
taipei
taipei*
taiw
taiwa
taiwan
taiwan*
ZRANK 定位
ta
ZRANGE 取得 2 後面 n 個
回傳
2
回傳
ta
tai
taip
taipe
taipei
taipei*
taiw
taiwa
taiwan
taiwan*
整理後回傳使用者
taipei
taiwan
使用者輸入
ta
73
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
74
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
75
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
先定位
76
搜尋階段 - 使用 ZRANK 及 ZRANGE 搜尋
先定位
再取出部分資料
77
優缺點
78
優缺點
 維運方便
79
優缺點
 維運方便
 資料全部儲存於記憶體,速度快
80
優缺點
 維運方便
 資料全部儲存於記憶體,速度快
 需人工介入的部分較多
81
優缺點
 維運方便
 資料全部儲存於記憶體,速度快
 需人工介入的部分較多
 資料全部儲存於記憶體,成本高
82
來個複雜一點的 Elasticsearch
83
Elasticsearch
84
Elasticsearch
●
分散式的免費開源搜尋和分析引擎
85
Elasticsearch
●
分散式的免費開源搜尋和分析引擎
●
適用於包括文字、數字、地理資訊、結構化和非
結構化資料
86
先介紹 Edge n-gram tokenizer
87
先介紹 Edge n-gram tokenizer
●
Elasticsearch 的其中一種分詞器
88
先介紹 Edge n-gram tokenizer
●
Elasticsearch 的其中一種分詞器
●
可將輸入的單詞固定從頭分割 n 個字元
89
先介紹 Edge n-gram tokenizer
●
Elasticsearch 的其中一種分詞器
●
可將輸入的單詞固定從頭分割 n 個字元
●
以 taipei 舉例
90
先介紹 Edge n-gram tokenizer
●
Elasticsearch 的其中一種分詞器
●
可將輸入的單詞固定從頭分割 n 個字元
●
以 taipei 舉例
– t
91
先介紹 Edge n-gram tokenizer
●
Elasticsearch 的其中一種分詞器
●
可將輸入的單詞固定從頭分割 n 個字元
●
以 taipei 舉例
– t
– ta
92
先介紹 Edge n-gram tokenizer
●
Elasticsearch 的其中一種分詞器
●
可將輸入的單詞固定從頭分割 n 個字元
●
以 taipei 舉例
– t
– ta
– tai
93
先介紹 Edge n-gram tokenizer
●
Elasticsearch 的其中一種分詞器
●
可將輸入的單詞固定從頭分割 n 個字元
●
以 taipei 舉例
– t
– ta
– tai
– taip
94
先介紹 Edge n-gram tokenizer
●
Elasticsearch 的其中一種分詞器
●
可將輸入的單詞固定從頭分割 n 個字元
●
以 taipei 舉例
– t
– ta
– tai
– taip
– taipe
95
先介紹 Edge n-gram tokenizer
●
Elasticsearch 的其中一種分詞器
●
可將輸入的單詞固定從頭分割 n 個字元
●
以 taipei 舉例
– t
– ta
– tai
– taip
– taipe
– taipei
96
前置設定 - Settings
97
前置設定 - Settings
98
前置設定 - Settings
設定最大值,避免切出過多不必要的詞
99
前置設定 - Mappings
100
前置設定 - Mappings
101
前置設定 - Mappings
搜尋時使用 keyword analyzer ,避免切詞
102
索引階段
103
索引階段
104
索引階段
會利用 edge n-gram 切詞後寫入索引
105
搜尋階段
106
搜尋階段
107
搜尋階段
搜尋時利用 keyword analyzer 不切詞搜尋
108
Elasticsearch 的 filter​context
109
Elasticsearch 的 filter​context
●
Elasticsearch 搜尋時會依照計算出來的分數排序
110
Elasticsearch 的 filter​context
●
Elasticsearch 搜尋時會依照計算出來的分數排序
●
filter 不計算分數
111
Elasticsearch 的 filter​context
●
Elasticsearch 搜尋時會依照計算出來的分數排序
●
filter 不計算分數
●
經常使用相同的 filter 會被 cache ,加快搜尋速度
112
優缺點
113
優缺點
 內建機制即可達成
114
優缺點
 內建機制即可達成
 資料全部儲存於硬碟,成本低
115
優缺點
 內建機制即可達成
 資料全部儲存於硬碟,成本低
 維運成本高
116
各種使用情境
117
文字包括 metadata
118
文字包括 metadata - Redis
119
文字包括 metadata - Redis
t
ta
tai
taip
taipe
taipei
taipei*123456
taiw
taiwa
taiwan
taiwan*556677
120
文字包括 metadata - Redis
t
ta
tai
taip
taipe
taipei
taipei*123456
taiw
taiwa
taiwan
taiwan*556677
121
文字包括 metadata - Elasticsearch
122
文字包括 metadata - Elasticsearch
123
依照使用頻率排序
124
依照使用頻率排序 - Redis
125
依照使用頻率排序 - Redis
126
依照使用頻率排序 - Redis
index name
127
依照使用頻率排序 - Redis
index name
score
128
依照使用頻率排序 - Redis
index name
score
candidate
129
依照使用頻率排序 - Redis
130
依照使用頻率排序 - Redis
131
依照使用頻率排序 - Redis
依照分數
132
依照使用頻率排序 - Redis
依照分數
降冪排序
133
依照使用頻率排序 - Redis
依照分數
降冪排序
總共取前 50 筆
134
依照使用頻率排序 - Elasticsearch
135
依照使用頻率排序 - Elasticsearch
136
依照使用頻率排序 - Elasticsearch
137
依照使用頻率排序 - Elasticsearch
138
依照使用頻率排序 - Elasticsearch
加上 sort 即可
139
Live DEMO
140
Conclusion
141
Conclusion
項目 client RDBMS Redis Elasticsearch
儲存空間
( 少→多 )
維運成本
( 便宜→貴 )
讀取速度
( 快→慢 )
擴充性
( 易→難 )
142
Conclusion
項目 client RDBMS Redis Elasticsearch
儲存空間
( 少→多 )
1
維運成本
( 便宜→貴 )
讀取速度
( 快→慢 )
擴充性
( 易→難 )
143
Conclusion
項目 client RDBMS Redis Elasticsearch
儲存空間
( 少→多 )
1 2 4 3
維運成本
( 便宜→貴 )
讀取速度
( 快→慢 )
擴充性
( 易→難 )
144
Conclusion
項目 client RDBMS Redis Elasticsearch
儲存空間
( 少→多 )
1 2 4 3
維運成本
( 便宜→貴 )
1
讀取速度
( 快→慢 )
擴充性
( 易→難 )
145
Conclusion
項目 client RDBMS Redis Elasticsearch
儲存空間
( 少→多 )
1 2 4 3
維運成本
( 便宜→貴 )
2 1 3 4
讀取速度
( 快→慢 )
擴充性
( 易→難 )
146
Conclusion
項目 client RDBMS Redis Elasticsearch
儲存空間
( 少→多 )
1 2 4 3
維運成本
( 便宜→貴 )
2 1 3 4
讀取速度
( 快→慢 )
1
擴充性
( 易→難 )
147
Conclusion
項目 client RDBMS Redis Elasticsearch
儲存空間
( 少→多 )
1 2 4 3
維運成本
( 便宜→貴 )
2 1 3 4
讀取速度
( 快→慢 )
1 4 2 3
擴充性
( 易→難 )
148
Conclusion
項目 client RDBMS Redis Elasticsearch
儲存空間
( 少→多 )
1 2 4 3
維運成本
( 便宜→貴 )
2 1 3 4
讀取速度
( 快→慢 )
1 4 2 3
擴充性
( 易→難 )
1
149
Conclusion
項目 client RDBMS Redis Elasticsearch
儲存空間
( 少→多 )
1 2 4 3
維運成本
( 便宜→貴 )
2 1 3 4
讀取速度
( 快→慢 )
1 4 2 3
擴充性
( 易→難 )
4 1 3 2
150
Conclusion
151
Conclusion
●
沒錢的時候用 Redis
152
Conclusion
●
沒錢的時候用 Redis
●
有維運技術用 Elasticsearch
153
Conclusion
●
沒錢的時候用 Redis
●
有維運技術用 Elasticsearch
●
複雜排序用 Elasticsearch
154
One more thing
155
Practical Autocomplete
156
157
References
●
Practical Autocomplete
●
Auto Complete with Redis
●
Edge n-gram tokenizer
●
Debounce ThrottleTest
158

深入淺出 autocomplete