使用mongoDB不是很多,記得以前做“家長(zhǎng)助手”的時(shí)候舆逃,使用過(guò)一點(diǎn)。只是在去年做“派單系統(tǒng)”的時(shí)候戳粒,又再一次使用mongoDB路狮。
在這里先簡(jiǎn)單介紹一下派單系統(tǒng),派單系統(tǒng)在云足療(O2O蔚约,上門足療)里一個(gè)專門負(fù)責(zé)訂單派送奄妨,提高訂單完成效率的一個(gè)系統(tǒng)。主要是當(dāng)一個(gè)來(lái)了之后苹祟,會(huì)根據(jù)訂單的服務(wù)項(xiàng)目砸抛、服務(wù)時(shí)間和服務(wù)地點(diǎn),快速找到最合適最優(yōu)秀的技師树枫,返回給用戶锰悼。由于上門足療特殊行業(yè)的要求,不能給訂單指定技師直接下單团赏。而是將篩選的一些優(yōu)秀的技師返回給用戶,讓用戶自己去選擇指派給哪位技師耐薯。
項(xiàng)目背景說(shuō)完了之后舔清,就是技術(shù)方案選擇的問(wèn)題。一開(kāi)始曲初,是想基于HBase一個(gè)分布式的体谒、面向列的開(kāi)源數(shù)據(jù)庫(kù)去存儲(chǔ)技師上報(bào)經(jīng)緯度。然后通過(guò)storm流式計(jì)算技師的位置臼婆。后來(lái)抒痒,感覺(jué)HBase過(guò)重而且還不便于維護(hù)。同時(shí)颁褂,又考慮到小公司的都會(huì)面對(duì)的一個(gè)問(wèn)題——成本問(wèn)題故响。就放棄了這一種方案。然后颁独,就想選擇一個(gè)非關(guān)系型數(shù)據(jù)庫(kù)去存住數(shù)據(jù)彩届,這時(shí)候就想到了Mongodb。好了誓酒,這是數(shù)據(jù)層樟蠕。分布式架構(gòu)我們使用的阿里的dubbo。選擇它的原因就不多說(shuō)了。首先是寨辩,市面上使用廣泛吧吓懈。以后,會(huì)具體講述其特點(diǎn)靡狞。分布式的管控使用的是zookeeper耻警,跨系統(tǒng)中間件使用的是ActiveMq。這個(gè)還是要簡(jiǎn)單說(shuō)一下為什么要選擇這個(gè)耍攘,而沒(méi)有選擇市面上用的比較多的RocketMq榕栏。最重要的一個(gè)原因時(shí)以前的工作中使用過(guò),而對(duì)MQ的應(yīng)用場(chǎng)景是師傅端經(jīng)緯度上報(bào)蕾各,消息的可靠性又不是很高扒磁,同時(shí)降低了學(xué)習(xí)成本。說(shuō)到這里式曲,感覺(jué)說(shuō)的太多了妨托,今天主要說(shuō)的是mongodb的應(yīng)用。
接下來(lái)就寫一個(gè)基于mongodb的地理檢索的實(shí)現(xiàn)吧吝羞!
Controller層
//查詢附近@ResponseBody@RequestMapping(value = "/geoNearN", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})public String testQueryMongoTopN() { CarPointNearQuery personQuery = new CarPointNearQuery(); Random random = new Random(); double[] arr = MongoUtil.getRandomLocation(); //最多查100條記錄 personQuery.setCount(100); //隨機(jī)1km米到10km int distance = random.nextInt(10); personQuery.setDistance(distance); personQuery.setLongitude(arr[0]); personQuery.setLatitude(arr[1]); return JSON.toJSONString(mongoLbsService.geoNearCarPoint(personQuery));}
Service層
public CarPointNearResult geoNearCarPoint(CarPointNearQuery carPointNearQuery) { CarPointNearResult carPointNearResult = new CarPointNearResult(); if(carPointNearQuery != null && carPointNearQuery.getLongitude() != 0.0D && carPointNearQuery.getLatitude() != 0.0D) { Point point = new Point(carPointNearQuery.getLongitude(), carPointNearQuery.getLatitude()); NearQuery near = NearQuery.near(point, Metrics.KILOMETERS); Query query = new Query(); //數(shù)量 query.limit(carPointNearQuery.getCount() == 0?100:carPointNearQuery.getCount()); near.query(query); //距離 near.maxDistance(new Distance(carPointNearQuery.getDistance() == 0.0D?1.0D:carPointNearQuery.getDistance(), Metrics.KILOMETERS)); near.spherical(true); //調(diào)用DAO層,獲取數(shù)據(jù) GeoResults geoResults = this.carPointDao.geoNear(near, CarPoint.class, "carPoint"); carPointNearQuery.setCount(geoResults.getContent().size()); carPointNearQuery.setDistance(near.getMaxDistance().getValue()); carPointNearResult.setCarPointNearQuery(carPointNearQuery); List geoResultsContent = geoResults.getContent(); ArrayList resultsList = new ArrayList(); Iterator i$ = geoResultsContent.iterator(); while(i$.hasNext()) { GeoResult geoResult = (GeoResult)i$.next(); CarPointResult carPointResult = new CarPointResult(); carPointResult.setDistance(geoResult.getDistance().getValue()); carPointResult.setCarPoint((CarPoint)geoResult.getContent()); resultsList.add(carPointResult); } carPointNearResult.setCarPointList(resultsList); return carPointNearResult; } else { logger.error("geoNear 參數(shù)異常"); carPointNearResult.setErrorCode(ErrorCode.PARAM_ERROR); return null; }}
DAO層
public GeoResults<T> geoNear(NearQuery near, Class<T> clazz, String collectionName) { //直接使用mongoTemplate就可以了 GeoResults geoResults = this.mongoTemplate.geoNear(near, clazz, collectionName); return geoResults;}
以上就是使用mongodbTemplate實(shí)現(xiàn)地理檢索的功能兰伤,關(guān)于mongodb地理檢索的方式有很多種,具體可以參考mongodb中文社區(qū)钧排,里面都有具體的介紹敦腔。