標籤:
簡介
快遞物流系統裡最常見的一種業務類型就是訂單的查詢和記錄。訂單的特點是隨著遞送過程,訂單資料需要隨時更新路徑。資料結構上需要可以靈活應對,這點非常符合Document模型,並且MongoDB支援GIS功能,非常適用於MongoDB來支撐物流業務。並且MongoDB具備Sharding能力,而物流行業裡訂單比較獨立,誇訂單的操作很少,而對單訂單來說,更新追加的操作會較多,比如再物流中轉處理上。所以物流業務模型上與MongoDB非常的匹配。以下講解一個虛擬DEMO,可供參考,用到的特性:
- MongoDB Document的數組結構
- TTL索引,自動到期曆史資料
- 複合索引,多條件查詢索引
- Partial Indexes,條件索引,只索引有效資料,降低索引的佔用空間
- MongoDB GIS功能,支援GeoJSON標準,可以接入第三方系統處理GEO資訊。
資料結構定義
{ "_id": <String>, // 訂單ID "status": <String>, // 訂單狀態,shipping,deliveried等 "order_image_url": <String>, // 訂單圖片資訊 "create_date": <ISODate>, // 訂單建立日期 "from": { // 發貨資訊 "city": <String>, "address": <String>, "name": <String>, "phone": <String>, "location": <GeoJSON> }, "delivery": { // 收貨資訊 "city": <String>, "address": <String>, "name": <String>, "phone": <String>, "location": <GeoJSON> }, "details": [ // 物流詳情,數組結構 { "action": "reviced", // 物流動作 "operator": "快遞小哥1號", // 操作員 "date": <ISODate> }... ]}
例如:
{ "_id": "E123456789", "status": "delivering", "create_date": ISODate("2016-06-21T09:00:00+08:00"), "order_image_url": "http://oss/xxxxx.jpg", "from": { "city": "Hangzhou", "address": "文一西路969號", "name": "小王", "phone": "18657112345", "location": { "type": "Point", "coordinates": [ 120, 30 ] } }, "delivery": { "city": "北京", "address": "朝陽區", "name": "朝陽群眾", "phone": "18601011011", "location": { "type": "Point", "coordinates": [ 116, 39 ] } }, "details": [ { "action": "reviced", "operator": "快遞小哥1號", "date": ISODate("2016-06-21T09:00:00+08:00") }, { "action": "shipping", "station": "hangzhou-airport", "date": ISODate("2016-06-22T01:00:00+08:00") }, { "action": "shipping", "station": "beijing-airport", "date": ISODate("2016-06-22T07:00:00+08:00") }, { "action": "shipping", "station": "chaoyang-station", "date": ISODate("2016-06-22T15:00:00+08:00") }, { "action": "delivering", "operator": "快遞小哥2號", "date": ISODate("2016-06-23T10:00:00+08:00") } ]}
幾個注意點:
- 利用了GEO特性,使用GeoJSON標準,但是座標繫上需要注意座標標準問題;
- 時間處理上,物流行業會涉及到國際化,所以嚴格按照ISO的標準,定義時間,CN
+80:00
;
- 訂單詳情裡很好的利用了Document的數組特性;
- 快遞訂單是唯一的,可以作為MongoDB的主鍵;
insert到collection中後的文檔:
> db.order.find().pretty(){ "_id" : "E123456789", "status" : "delivering", "create_date" : ISODate("2016-06-21T01:00:00Z"), "order_image_url" : "http://oss/xxxxx.jpg", "from" : { "city" : "Hangzhou", "address" : "文一西路969號", "name" : "小王", "phone" : "18657112345", "location" : { "type" : "Point", "coordinates" : [ 120, 30 ] } }, "delivery" : { "city" : "北京", "address" : "朝陽區", "name" : "朝陽群眾", "phone" : "18601011011", "location" : { "type" : "Point", "coordinates" : [ 116, 39 ] } }, "details" : [ { "action" : "reviced", "operator" : "快遞小哥1號", "date" : ISODate("2016-06-21T01:00:00Z") }, { "action" : "shipping", "station" : "hangzhou-airport", "date" : ISODate("2016-06-21T17:00:00Z") }, { "action" : "shipping", "station" : "beijing-airport", "date" : ISODate("2016-06-21T23:00:00Z") }, { "action" : "shipping", "station" : "chaoyang-station", "date" : ISODate("2016-06-22T07:00:00Z") }, { "action" : "delivering", "operator" : "快遞小哥2號", "date" : ISODate("2016-06-23T02:00:00Z") } ]}
資料操作
物流快遞的訂單修改主要是查詢和資訊追加兩種,主要介紹這兩種:
訂單資訊查詢,最常見的操作,使用者的訂單查詢:
db.order.find({_id:"E123456789"});
有時需要做資訊統計,按照狀態來查詢:
db.order.find({"status":"delivering", "delivery.city":"北京", "delivery.address":"朝陽區"});
物流狀態更新時,需要更新相應的訂單,MongoDB上直接 $push
過去即可:
db.order.update( { _id:"E123456789"}, {$push: {details: {"action":"delivering", "operator" : "快遞小哥3號", "date" : ISODate("2016-06-23T13:00:00+8:00")}}})
索引建立
_id
索引,預設存在,不需要再建立;當資料量較大時,可以使用sharding結構,shardkey的選擇上可以使用 Hash(_id)
。
TTL索引,欄位 create_date
,180天后自動清理資料:
db.order.createIndex({"create_date":1}, {"expireAfterSeconds":15552000})
位置和狀態索引,為了能快速處理“某地未處理訂單”查詢,這是一個多條件的查詢,所以是一個複合索引, status
欄位放在前面,因為多數的查詢都會依賴狀態欄位
db.order.createIndex({"status":1, "delivery.city":1, "delivery.address":1})
在這個Demo裡,還有一種加快查詢速度的方法就是,建立一個只包含指定狀態的一個Partial Indexes索引。比如 status
必須為 delivering
才加入到索引中,有效控制索引的大小,加快查詢速度。
db.order.createIndex({"delivery.city":1, "delivery.address":1},{partialFilterExpression:{‘status‘:{$eq:"delivering"}}})
MongoDB GIS
MongoDB遵循的事GeoJSON規範,對象的描述上通過一個type欄位描述GeoJSON類型,coordinates欄位描述空間資訊。
{ type: "<GeoJSON type>" , coordinates: <coordinates> }
coordinates是一個 [longitude, latitude]
的數群組類型。另外值得關注的是MongoDB GEO的使用的是WGS84標準。WGS84也是國際標準,中國使用的著名的火星座標GCJ-02,還有一套百度座標BD09,三者的座標轉換可以參考附錄相關的連結。
附錄
GeoJSON
- https://docs.mongodb.com/manual/reference/geojson/
- http://geojson.org/geojson-spec.html
- https://docs.mongodb.com/manual/reference/glossary/#term-wgs84
MongoDB Geo Index
- https://docs.mongodb.com/manual/core/2dsphere/
- https://docs.mongodb.com/manual/reference/glossary/#term-legacy-coordinate-pairs
GeoHack
- https://tools.wmflabs.org/geohack/geohack.php?pagename=Hangzhou¶ms=30\_15\_N\_120\_10\_E\_type:city(9018000)_region:CN-33_
- https://tools.wmflabs.org/geohack/geohack.php?pagename=Beijing¶ms=39\_55\_N\_116\_23\_E\_type:city(21700000)_region:CN-11_
- https://en.wikipedia.org/wiki/World\_Geodetic\_System
Geo Datum
- https://github.com/wandergis/coordtransform
MongoDB助力快速搭建物流訂單系統