javascript
mongodb lbs java_LBS JAVA Spring mongoDB
基本介紹
位置服務(LBS)解決的主要問題是當前位置周圍某個范圍內的人或場所.
在傳統的解決方案,開發人員需要根據復雜的幾何運算與大量的SQL語句進行查找,這無疑加大的開發人員的開發難度.
現在我們需要更為方便的解決方案,MongoDB為我們完美解決此類LBS問題.此篇文章也主要使用SpringData,將spring與MongoDB進行整合.
二維地圖
MongoDB目前支持二維的地圖查詢,查詢區域包括圓形與矩形,距離單位包括MILES,KILOMETERS,NEUTRAL,下面的示例演示距離單位為NEUTRAL,而實際生產應用中則會用到MILES與KILOMETERS.
MongoDB示例
首先定義一個位置集合,給定a,b,c,d節點.
1
2
3
4
5
6
7
8
>
db
.
createCollection
(
"location"
)
{
"ok"
:
1
}
>
db
.
location
.
save
(
{
_id
:
"A"
,
position
:
[
0.1
,
-
0.1
]
}
)
>
db
.
location
.
save
(
{
_id
:
"B"
,
position
:
[
1.0
,
1.0
]
}
)
>
db
.
location
.
save
(
{
_id
:
"C"
,
position
:
[
0.5
,
0.5
]
}
)
>
db
.
location
.
save
(
{
_id
:
"D"
,
position
:
[
-
0.5
,
-
0.5
]
}
)
接著指定location索引
1
db
.
location
.
ensureIndex
(
{
position
:
"2d"
}
)
現在我們可以進行簡單的GEO查詢
查詢point(0,0),半徑0.7附近的點
1
2
3
4
>
db
.
location
.
find
(
{
position
:
{
$near
:
[
0
,
0
]
,
$maxDistance
:
0.7
}
}
)
{
"_id"
:
"A"
,
"position"
:
[
0.1
,
-
0.1
]
}
查詢point(0,0),半徑0.75附近的點
1
2
3
4
5
6
>
db
.
location
.
find
(
{
position
:
{
$near
:
[
0
,
0
]
,
$maxDistance
:
0.75
}
}
)
{
"_id"
:
"A"
,
"position"
:
[
0.1
,
-
0.1
]
}
{
"_id"
:
"C"
,
"position"
:
[
0.5
,
0.5
]
}
{
"_id"
:
"D"
,
"position"
:
[
-
0.5
,
-
0.5
]
}
我們可以看到半徑不一樣,查詢出的點也不一樣,因為c點坐標為[0.5,0.5],c至圓點的距離根據勾股定理可得出Math.sqrt(0.25 +0.25) ≈ 0.707,所以最大距離0.7時查找不到你要的點.
查詢[0.25, 0.25], [1.0,1.0]區域附近的點
1
2
3
4
5
>
db
.
location
.
find
(
{
position
:
{
$within
:
{
$box
:
[
[
0.25
,
0.25
]
,
[
1.0
,
1.0
]
]
}
}
}
)
{
"_id"
:
"C"
,
"position"
:
[
0.5
,
0.5
]
}
{
"_id"
:
"B"
,
"position"
:
[
1
,
1
]
}
Spring Data示例
spring data為我們封裝了mongoDB訪問接口與實現,我們可以像使用hibernateTemplate一樣使用mongoTemplate.
首先我們需要像hibernate一樣定義pojo類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import
org
.
springframework
.
data
.
annotation
.
Id
;
import
org
.
springframework
.
data
.
mongodb
.
core
.
mapping
.
Document
;
@Document
(
collection
=
"location"
)
public
class
Location
{
@Id
private
String
id
;
private
double
[
]
position
;
/** getter setter hashcode equals toString ...??*/
}
定義Dao,我們先使用最簡單的mongoTemplate來實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import
java
.
util
.
List
;
import
org
.
springframework
.
beans
.
factory
.
annotation
.
Autowired
;
import
org
.
springframework
.
data
.
mongodb
.
core
.
MongoTemplate
;
import
org
.
springframework
.
data
.
mongodb
.
core
.
geo
.
Box
;
import
org
.
springframework
.
data
.
mongodb
.
core
.
geo
.
Point
;
import
org
.
springframework
.
data
.
mongodb
.
core
.
query
.
Criteria
;
import
org
.
springframework
.
data
.
mongodb
.
core
.
query
.
Query
;
import
org
.
springframework
.
stereotype
.
Repository
;
@Repository
public
class
LocationDao
{
@Autowired
MongoTemplate
mongoTemplate
;
public
List
findCircleNear
(
Point
point
,
double
maxDistance
)
{
return
mongoTemplate
.
find
(
new
Query
(
Criteria
.
where
(
"position"
)
.
near
(
point
)
.
maxDistance
(
maxDistance
)
)
,
Location
.
class
)
;
}
public
List
findBoxNear
(
Point
lowerLeft
,
Point
upperRight
)
{
return
mongoTemplate
.
find
(
new
Query
(
Criteria
.
where
(
"position"
)
.
within
(
new
Box
(
lowerLeft
,
upperRight
)
)
)
,
Location
.
class
)
;
}
}
最后我們寫一個test類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import
java
.
util
.
Collection
;
import
java
.
util
.
List
;
import
org
.
junit
.
Before
;
import
org
.
junit
.
Test
;
import
org
.
junit
.
runner
.
RunWith
;
import
org
.
springframework
.
beans
.
factory
.
annotation
.
Autowired
;
import
org
.
springframework
.
data
.
mongodb
.
core
.
MongoTemplate
;
import
org
.
springframework
.
data
.
mongodb
.
core
.
geo
.
Point
;
import
org
.
springframework
.
data
.
mongodb
.
core
.
index
.
GeospatialIndex
;
import
org
.
springframework
.
test
.
context
.
ContextConfiguration
;
import
org
.
springframework
.
test
.
context
.
junit4
.
SpringJUnit4ClassRunner
;
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@ContextConfiguration
(
locations
=
{
"classpath:/applicationContext.xml"
,
"classpath:/application-mongo.xml"
}
)
public
class
MongoDBTest
{
@Autowired
LocationDao
locationDao
;
@Autowired
MongoTemplate
template
;
@Before
public
void
setUp
(
)
{
// 等同db.location.ensureIndex( {position: "2d"} )
template
.
indexOps
(
Location
.
class
)
.
ensureIndex
(
new
GeospatialIndex
(
"position"
)
)
;
// 初始化數據
template
.
save
(
new
Location
(
"A"
,
0.1
,
-
0.1
)
)
;
template
.
save
(
new
Location
(
"B"
,
1
,
1
)
)
;
template
.
save
(
new
Location
(
"C"
,
0.5
,
0.5
)
)
;
template
.
save
(
new
Location
(
"D"
,
-
0.5
,
-
0.5
)
)
;
}
@Test
public
void
findCircleNearTest
(
)
{
List
locations
=
locationDao
.
findCircleNear
(
new
Point
(
0
,
0
)
,
0.7
)
;
(
locations
)
;
System
.
err
.
println
(
"-----------------------"
)
;
locations
=
locationDao
.
findCircleNear
(
new
Point
(
0
,
0
)
,
0.75
)
;
(
locations
)
;
}
@Test
public
void
findBoxNearTest
(
)
{
List
locations
=
locationDao
.
findBoxNear
(
new
Point
(
0.2
,
0.2
)
,
new
Point
(
1
,
1
)
)
;
(
locations
)
;
}
public
static
void
(
Collection
locations
)
{
for
(
Location
location
:
locations
)
{
System
.
err
.
println
(
location
)
;
}
}
}
大家可以看到運行結果與我們直接在mongoDB上的一樣.
MongoRepository
MongoRepository提供了對MongoTemplate的封裝與實現,只需要繼承MongoRepository接口,填上對應的bean類與ID類型,無需實現里面的方法即可使用,先看代碼.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import
org
.
springframework
.
data
.
mongodb
.
core
.
geo
.
Box
;
import
org
.
springframework
.
data
.
mongodb
.
core
.
geo
.
Distance
;
import
org
.
springframework
.
data
.
mongodb
.
core
.
geo
.
Point
;
import
org
.
springframework
.
data
.
mongodb
.
repository
.
MongoRepository
;
public
interface
LocationRepository
extends
MongoRepository
<
Location
,
String
>
{
List
findByPositionNear
(
Point
p
,
Distance
d
)
;
List
findByPositionWithin
(
Box
b
)
;
}
然后在test類中引用此類即可,MongoRepository實現了最基本的增刪改查的功能,要想增加額外的查詢方法,可以按照以下規則定義接口的方法.
自定義查詢方法,格式為findBy+字段名+方法名,方法傳進的參數即字段的值,此外還支持分頁查詢,通過傳進一個Pageable對象會返回Page集合.
原理相信大家也很清楚,即aop,細節就不說拉.
小提示
near與within方法區別,near方法查詢后會對結果集對distance進行排序且有大小限制,而within是無序的也無大小限制.
如果大家有新發現,也可回帖,我會及時補充.
總結
以上是生活随笔為你收集整理的mongodb lbs java_LBS JAVA Spring mongoDB的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《绍古辞》是谁的作品?
- 下一篇: js html 导出word 不用act