TableStore實戰:GEO索引打造億量級店鋪搜尋系統

wangtantan發表於2019-01-14

一、方案背景

對於一套GEO管理系統,其核心點與瓶頸在於資料庫的儲存效能與查詢能力;一方面,儲存服務需要應對海量資料的低延遲存、讀,另一方面,儲存服務也要提供高效的GEO+多維度資料檢索。表格儲存(TableStore),作為一款Serverless分散式NoSQL資料庫,完全具備該系統的需求。 下面我們將基於TableStore打造一個【億量級GEO管理系統】;

需求場景

某店鋪搜尋平臺,提供了億量級的店鋪資訊。使用者通過平臺提供的PC端、移動端網頁,按照自己的需求維度組合,搜尋使用者心儀的店鋪。平臺需要在地圖上展示店鋪的具體位置、店鋪詳細資訊、店鋪主頁的跳轉; 維度一:【距離1km內】【人均100以內】【評分最高】【奶茶店】; 維度二:【杭州市內】【評分最高的】【沈家*】店鋪; ...... 實現快速、多維GEO查詢功能,是GEO管理解決方案的核心功能,樣例如下: 注:該樣例提供了【億量級】店鋪資料。官網控制檯樣例地址:專案樣例

testGeo

基於表格儲存搭建的店鋪搜尋系統頁面一覽,樣例內嵌在表格儲存控制檯中,使用者可登入控制檯體驗系統(若為表格儲存的新使用者,需要點選開通服務後體驗,開通免費,訂單資料儲存在公共例項中,體驗不消耗使用者儲存、流量、Cu)。

表格儲存(TableStore)方案

使用表格儲存(TableStore)研發的多元索引(SearchIndex)方案,可以輕鬆搭建一套:億量級店鋪搜尋系統。多元索引功能可以建立GEO索引、分詞字串索引等,為使用者提供了GEO檢索、多維組合檢索等能力,使用者可隨時建立,存量、增量資料自動同步。 TableStore作為阿里雲提供的一款全託管、零運維的分散式NoSql型資料儲存服務,具有【海量資料儲存】、【熱點資料自動分片】、【海量資料多維檢索】等功能,有效的地解決了GEO資料量大膨脹這一挑戰; 使用者可以僅在需要的時候建立、開通索引。由TableStore來保證資料同步的一致性,這極大的降低了使用者的方案設計、服務運維、程式碼開發等工作量。

二、搭建準備

若您對於基於TableStore實現的【億量級店鋪搜尋系統】體驗不錯,並希望開始自己系統的搭建之旅,只需按照如下步驟便可以著手搭建了:

1、開通表格儲存

通過控制檯開通表格儲存服務,表格儲存即開即用(後付費),採用按量付費方式,已為使用者提供足夠功能測試的免費額度。表格儲存官網控制檯免費額度說明

2、建立例項

通過控制檯建立表格儲存例項,選擇支援多元索引的Region。(當前階段SearchIndex功能尚未商業化,暫時開放北京,上海,杭州和深圳四地,其餘地區將逐漸開放)

image | left

建立例項後,提交工單申請多元索引功能邀測(商業化後預設開啟,不使用不收費)。

  • 邀測地址:提工單,選擇【表格儲存】>【產品功能、特性諮詢】>【建立工單】,申請內容如下:
  • 問題描述:請填寫【申請SearchIndex邀測】
  • 機密資訊:請填寫【地域+例項名】,例:上海+myInstanceName

image | left

3、SDK下載

使用具有多元索引(SearchIndex)的SDK,官網地址,暫時java、go、node.js三種SDK增加了新功能

java-SDK

<dependency>
    <groupId>com.aliyun.openservices</groupId>
    <artifactId>tablestore</artifactId>
    <version>4.8.0</version>
</dependency>
複製程式碼

go-SDK

$ go get github.com/aliyun/aliyun-tablestore-go-sdk
複製程式碼

Nodejs-SDK

$ npm install tablestore@4.1.0
複製程式碼

C#-SDK

$ Install-Package Aliyun.TableStore.SDK -Version 4.1.0
複製程式碼

4、表設計

店鋪檢索系統樣例,僅簡易使用一張店鋪表,主要包含欄位:店鋪型別、店鋪名稱、店鋪地理位置、店鋪平均評分、人均消費消等。表設計如下: 表名:geo_positon

列名 資料型別 索引型別 欄位說明
_id(主鍵列) String MD5(pId)避免熱點
pId Stirng 店鋪編號
type String KEYWORD 型別
name String TEXT 店鋪名,TEXT型別索引可模糊查詢,但不能排序
pos String GEO_POINT 店鋪位置:"30.132,120.082"(緯度,精度)
point double DOUBLE 評分
... ... ... ...

三、開始搭建(核心程式碼)

1、建立資料表

使用者僅需在完成邀測的例項下建立“店鋪資訊表”:通過控制檯建立、管理資料表(使用者也可以通過SDK直接建立):

image.png | left | 827x351

2、建立資料表索引

TableStore自動做全量、增量的索引資料同步:使用者可以通過控制檯建立索引、管理索引(也可以通過SDK建立索引)

image.png | left | 827x444

image.png | left | 827x266

3、資料匯入

插入測試資料(控制檯樣例中插入了1億條資料,使用者自己可以插入少量測試資料);

image.png | left | 747x156

店鋪編號 店鋪(md5)(主鍵) 型別 店鋪名稱 店鋪位置 店鋪評分 人均消費
o0057022192 0000000f470ef0f548b925ceffe1a7e3 杭幫菜 韓村杭幫菜 36.76613,111.41461 2.87 63.67

4、資料讀取

資料讀取分為兩類:

主鍵讀取

基於原生表格儲存的主鍵列獲取:getRow, getRange, batchGetRow等。主鍵讀取用於索引(自動)反查,使用者也可以提供主鍵(訂單md5)的單條查詢的頁面,億量級下查詢速度極快。單主鍵查詢方式不支援多維度檢索;

索引讀取(店鋪查詢)

基於新SearchIndex功能Query:search介面。使用者可以自由設計索引欄位的多維度條件組合查詢。通過設定選擇不同的查詢引數,構建不同的查詢條件、不同排序方式;目前支援:精確查詢、範圍查詢、字首查詢、匹配查詢、萬用字元查詢、短語匹配查詢、分詞字串查詢,並通過布林與、或組合。 如【"36.76613,111.41461"周邊1km米範圍內的奶茶店】,查詢條件如下: ####Node.js程式碼

client.search({
    tableName: TABLE_NAME,
    indexName: INDEX_NAME,
    searchQuery: {
        offset: 0,
        limit: 10, 
        query: {
            queryType: TableStore.QueryType.BOOL_QUERY,
            query: {
                mustQueries: [ 
                    { //查詢條件一:TermQuery,cId這一列的值要匹配"c0001"
                        queryType: TableStore.QueryType.TERM_QUERY,
                        query: {
                            fieldName: "type",
                            term: "奶茶"
                        }
                    },
                    { //查詢條件二:RangeQuery,totalPrice這一列的值要大於99.99
			            queryType: TableStore.QueryType.GEO_DISTANCE_QUERY,
			            query: {
			                fieldName: "pos",
			                centerPoint: "36.76613,111.41461", // 設定中心點(緯度,經度)
			                distance: 10000 // 設定到中心點的距離條件,不超過10000米
			            }
                    },
                ],
            }
        },
        getTotalCount: true
    },
    columnToGet: {
        returnType: TableStore.ColumnReturnType.RETURN_ALL
    }
}, callback);
複製程式碼

####Java程式碼:

List<Query> mustQueries = new ArrayList<Query>();

TermQuery termQuery = new TermQuery();
termQuery.setFieldName("type");
termQuery.setTerm(ColumnValue.fromString(奶茶));
mustQueries.add(termQuery);

GeoDistanceQuery geoDistanceQuery = new GeoDistanceQuery();
geoDistanceQuery.setFieldName("pos");
geoDistanceQuery.setCenterPoint("36.76613,111.41461");
geoDistanceQuery.setDistanceInMeter(1000);
mustQueries.add(geoDistanceQuery);

BoolQuery boolQuery = new BoolQuery();
boolQuery.setMustQueries(mustQueries);
複製程式碼

四、歡迎加入

這樣,系統的核心程式碼已經完成,基於表格儲存搭億量級“店鋪搜尋系統”,是不是很簡單? 對錶格儲存(TableStore)感興趣的使用者,歡迎加入【表格儲存公開交流群】,群號:11789671。

image | left

相關文章