SpringBoot整合MongoDB(2)
在用basedbobject拼接json对象时,当json特别长时,下面这个方法是一个合适的方法
String
groupStr
=
"{\"$group\":{\"_id\":\"$name\",\"count\":{\"$sum\":1},\"avg_age\":{\"$avg\":\"$age\"},\"total_age\":{\"$sum\":\"$age\"},\"max_age\":{\"$max\":\"$age\"},\"min_age\":{\"$min\":\"$age\"}}}"
;
DBObject
dbObject
=
(
DBObject
)
JSON
.
parse
(
groupStr
);
User
user
=
new
User
();
user
.
setName
(
"woms"
);
user
.
setAge
(
15
);
//db.user.insert({"name":"woms","age":15})
mongoTemplate
.
insert
(
user
);
//> db.user.insert([{"username":"jj","age":11},{"username":"jj","age":11}])
List
<
User
>
list
=
new
ArrayList
<>
();
User
user
=
new
User
();
user
.
setAge
(
14
);
user
.
setName
(
"jj"
);
list
.
add
(
user
);
mongoTemplate
.
insertAll
(
list
);
db.collectionName.find({查询条件},{控制要显示的字段,可选项}) 数据查询也是使用json形式设置的相等关系 可选项中要显示的字段设置为1,不想显示的字段设置为0 对于查询而言,使用java-api的find()函数,只要知道bson写法,就能写api
不带查询条件,查询全部数据
//db.user.find()
List
<
User
>
findAll
=
mongoTemplate
.
findAll
(
User
.
class
);
// db.user.find({})
mongoTemplate
.
find
(
new
Query
(),
User
.
class
);
不带查询条件
// > db.user.findOne()
User
user
=
mongoTemplate
.
findOne
(
new
Query
(),
User
.
class
);
//> db.user.find({"name":"jj"},{"_id":0,"name":1})
//{ "name" : "jj" }
以下两种方式同效果
//方式一
mongoTemplate
.
find
(
new
BasicQuery
(
"{\"name\":\"jj\"}"
,
"{\"_id\":0,\"name\":1}"
),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
//方式二
mongoTemplate
.
find
(
new
BasicQuery
(
new
BasicDBObject
(
"name"
,
"jj"
),
new
BasicDBObject
(
"_id"
,
0
).
append
(
"name"
,
1
)),
User
.
class
)
.
stream
().
forEach
(
System
.
err
::
println
);
//User [id=null, name=jj, age=null, location=null, arrStr=null, arrInt=null]查询出结果只有name有值
大于("$gt")、小于("$lt")、大于等于("$gte")、小于等于("$lte")、不等于("$ne")、等于({"key":"value"}、"$eq")、模("$mod")
求模bson结构,
db.user.find({"age":{"$mod":[20,1]}})
,查询出所有年龄age除以20余数为1的数据记录,和其他的关系运算符不同,求模需要两个 数据运算,所以用数字表示
范例:查询name=woms95 and age >= 95的记录
//相等关系可以用{key:value}也可以使用"$eq"操作符,以下两种写法等效
//> db.user.find({"age":{"$gte":95},"name":{"$eq":"woms-95"}})
//> db.user.find({"age":{"$gte":95},"name":"woms-95"})
mongoTemplate
.
find
(
new
BasicQuery
(
"{\"age\":{\"$gte\":95},\"name\":{\"$eq\":\"woms-95\"}}"
),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
//{"age":{"$gte":95},"name":{"$eq":"woms-95"}}这个json串可以使用下面BasicDBObject对象
new
BasicDBObject
(
"age"
,
new
BasicDBObject
(
"$gte"
,
95
)).
append
(
"name"
,
new
BasicDBObject
(
"$eq"
,
"woms-95"
))
//也可以使用下面这种构造方法
Map
<
String
,
Object
>
map
=
new
HashMap
<>
();
map
.
put
(
"age"
,
new
BasicDBObject
(
"$gte"
,
95
));
map
.
put
(
"name"
,
new
BasicDBObject
(
"$eq"
,
"woms-95"
));
BasicDBObject
basicDBObject
=
new
BasicDBObject
(
map
);
-
1.一个json串“{}”就是一个BasicDBObject对象,查询条件可以使用json串,也可以使用BasicDBObject对象
-
2.json串中逗号相隔的key:value,使用append(key,value)拼接
-
3.语法是json语法,格式是bson格式
与($and)、或($or)、非($not 、$nor)
bson结构中,逻辑运算付的级别最高
范例:name=woms-35 or age = 99
//> db.user.find({"$or":[{"name":"woms-33"},{"age":99}]})
// 方式一
mongoTemplate
.
find
(
new
BasicQuery
(
"{\"$or\":[{\"name\":\"woms-33\"},{\"age\":99}]}"
),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
// 方式二
List
<
BasicDBObject
>
list
=
new
ArrayList
<>
();
list
.
add
(
new
BasicDBObject
(
"name"
,
"woms-33"
));
list
.
add
(
new
BasicDBObject
(
"age"
,
99
));
BasicDBObject
basicDBObject
=
new
BasicDBObject
(
"$or"
,
list
);
mongoTemplate
.
find
(
new
BasicQuery
(
basicDBObject
),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
-
1.一个{}就是一个BasicDBObject,{}的嵌套就是BasicDBObject的嵌套
-
2.嵌套中如果嵌套{},还用BasicDBObject如果嵌套[]就使用list
-
3.nor是一个或(or)的求反功能
加深理解
//> > db.user.find({"$or":[{"name":"woms-33"},{"age":{"$gte":95}}]})
//方式一
new
BasicQuery
(
"{\"$or\":[{\"name\":\"woms-33\"},{\"age\":{\"$gte\":95}}]}"
)
//方式二
List
<
BasicDBObject
>
list
=
new
ArrayList
<>
();
list
.
add
(
new
BasicDBObject
(
"name"
,
"woms-33"
));
list
.
add
(
new
BasicDBObject
(
"age"
,
new
BasicDBObject
(
"$gte"
,
95
)));
new
BasicQuery
(
new
BasicDBObject
(
"$or"
,
list
));
在范围内("$in")、不在范围内("$nin")
范围的内容有多个,所以要用数组表示
范例:查询age范围在[1,3,5,7,9]内的所有记录数据
// > db.user.find({"age":{"$in":[1,3,5,7,9]}})
mongoTemplate
.
find
(
new
BasicQuery
(
"{\"age\":{\"$in\":[1,3,5,7,9]}}"
),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
//方式二
BasicDBObject
basicDBObject
=
new
BasicDBObject
(
"age"
,
new
BasicDBObject
(
"$in"
,
Arrays
.
asList
(
1
,
3
,
5
,
7
,
9
)));
mongoTemplate
.
find
(
new
BasicQuery
(
basicDBObject
),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
在MongoDB中支持数组保存,一旦支持了数组保存,就需要针对数组的数据进行匹配 可以使用MongoDB的BSON的几个操作符:all、size、slice、elemMathc
范例1:查询同时参加语文和数学的学生{“$all”,[内容1,内容2,…]}
//查询数组中包含aa和dd的数据记录
//> db.user.find({"arr_str":{"$all":["aa","dd"]}})
//方式一
mongoTemplate
.
find
(
new
BasicQuery
(
"{\"arr_str\":{\"$all\":[\"aa\",\"dd\"]}}"
),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
//方式二
mongoTemplate
.
find
(
new
BasicQuery
(
new
BasicDBObject
(
"arr_str"
,
new
BasicDBObject
(
"$all"
,
Arrays
.
asList
(
"aa"
,
"dd"
)))),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
范例2:控制数组显示的内容
//控制数组返回的个数2:表示前两个,-2:表示后两个,[1,2]:表示第一个到第二个元素
//因为这个只是控制显示映射的结果集,所以放在可选项的位置,不在查询条件内
//> db.user.find({"name":"woms"},{"arr_str":{"$slice":2}})
mongoTemplate
.
find
(
new
BasicQuery
(
"{\"name\":\"woms\"}"
,
"{\"arr_str\":{\"$slice\":2}}"
),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
范例3:指定索引位置元素查询
//> db.user.find({"arr_str.1":"bb"})
mongoTemplate
.
find
(
new
BasicQuery
(
"{\"arr_str.1\":\"bb\"}"
),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
mongoTemplate
.
find
(
new
BasicQuery
(
new
BasicDBObject
(
"arr_str.1"
,
"bb"
)),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
基础语法:
{key:正则标记}
完整语法:
{key:{“$regex":正则标记,"regex":正则标记,"$options”:"i"}}
对于options主要是设置正则的信息查询的标记:
“i” :忽略字母大小写; “m” :多行查找; “x” :空白字符除了被转义的或者在字符类中以外的完全被忽略; “s” :匹配所有的字符(圆点、”.”),包括换行内容
两种写法效果相同,但是第一种用java-api没找到怎么写一直包json解析异常
因为第一种写法不能加双引号,使用“/”标示正则表达式,如果加了双引号就成了字符串匹配了
> db.user.find({"name":/wo/i})
> db.user.find({"name":{"$regex":"wo","$options":"i"}})
mongoTemplate.find(new BasicQuery("{\"name\":{\"$regex\":\"wo\",\"$options\":\"i\"}}"), User.class).stream().forEach(System.err::println);
// BasicDBObject basicDBObject = new BasicDBObject("name", new BasicDBObject("$regex", "wo").append("$options", "i"));
// BasicDBObject basicDBObject = new BasicDBObject("name", new BasicDBObject("$regex", Pattern.compile("wo")).append("$options", "i"));
mongoTemplate.find(new BasicQuery(basicDBObject), User.class).stream().forEach(System.err::println);
// db.user.find().skip(5).limit(5).sort({"age":-1})
BasicQuery
basicQuery
=
new
BasicQuery
(
"{}"
);
basicQuery
.
setSortObject
(
new
BasicDBObject
(
"age"
,
-
1
));
mongoTemplate
.
find
(
basicQuery
.
skip
(
5
).
limit
(
5
),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
mongoTemplate
.
find
(
new
Query
().
skip
(
5
).
limit
(
5
).
with
(
new
Sort
(
Direction
.
ASC
,
"age"
)),
User
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
//分页排序--mongoTemplate
BasicDBObject
basicDBObject
=
new
BasicDBObject
();
//模糊查询
basicDBObject
.
put
(
"lastName"
,
new
BasicDBObject
(
"$regex"
,
Pattern
.
compile
(
"mit"
)).
append
(
"$options"
,
"i"
));
Query
query
=
new
BasicQuery
(
basicDBObject
);
query
.
with
(
new
PageRequest
(
0
,
20
));
query
.
with
(
new
Sort
(
Direction
.
ASC
,
"lastName"
));
List
<
Customer
>
list
=
mongoTemplate
.
find
(
query
,
Customer
.
class
);
for
(
Customer
customer
:
list
)
{
System
.
out
.
println
(
customer
);
}
-
1.必须创建地理位置索引,而且在插入数据之前就预先创建好
db.car_info.createIndex( { "location": "2dsphere" } ) -
2.索引字段使用的是geojson数据格式,格式如下,注意type的首字母是大写location: {type: "Point",coordinates: [-73.856077, 40.848447]}
范例1:计算点[115.21,40.31]半径为1英里范围内的所有点,这里1英里=1.6公里 3963.2为大约地球半径
//db.car_info.find({"location":{"$geoWithin":{"$centerSphere":[[115.21,40.31],1/3963.2]}}})
BasicDBObject
basicDBObject
=
new
BasicDBObject
();
basicDBObject
.
put
(
"location"
,
new
BasicDBObject
(
"$geoWithin"
,
new
BasicDBObject
(
"$centerSphere"
,
Arrays
.
asList
(
Arrays
.
asList
(
115.21
,
40.31
),
1
/
3963.2
))));
mongoTemplate
.
find
(
new
BasicQuery
(
basicDBObject
),
CarInfo
.
class
).
stream
().
forEach
(
System
.
err
::
println
);
注意:
[[115.21,40.31],1/3963.2]
java-json解析异常了,需要使用BasicDBObject结合数组使用
范例2:查询距离最近的点并且排序
>
db
.
car_info
.
find
({
"location"
:
{
"$near"
:
{
"$geometry"
:
{
"type"
:
"Point"
,
coordinates
:
[
115.21
,
40.31
]},
"$maxDistance"
:
10000
}}})
upsert : 如果更新的数据不存在,就增加一条新的内容(true为增加,false不增加),默认false multi :表示是否只更新满足条件的第一条记录(false:只更新第一条记录,ture全部更新)默认false
整行更新,只跟新满足条件的第一条数据
//这三个写法是等效的
//db.user.update({"name":"woms"},{"username":"www"})
//db.user.update({"name":"woms"},{"username":"www"},{"multi":false})
//db.user.updateOne({"name":"woms"},{"username":"www"})
//下面两个写法是等效的
mongoTemplate
.
updateFirst
(
new
BasicQuery
(
new
BasicDBObject
(
"name"
,
"woms"
)),
new
BasicUpdate
(
"{\"username\":\"www\"}"
),
User
.
class
);
mongoTemplate
.
updateFirst
(
new
BasicQuery
(
new
BasicDBObject
(
"name"
,
"woms"
)),
new
BasicUpdate
(
new
BasicDBObject
(
"username"
,
"www"
)),
User
.
class
);
多行同时更新(注意:多行更新不能整行覆盖,只能指定字段指定更新,这也正符合开发的规则)
//这两个写法是等效的
//db.user.update({"name":"woms"},{"$set":{"username":"hhh"}},{"multi":true})
//db.user.updateMany({"username":"ggg"},{"$set":{"username":"hhh"}})
//下面两个写法是等效的
mongoTemplate
.
updateMulti
(
new
BasicQuery
(
"{\"username\":\"hhh\"}"
),
new
BasicUpdate
(
"{\"$set\":{\"username\":\"kkk\"}}"
),
User
.
class
);
mongoTemplate
.
updateMulti
(
new
BasicQuery
(
new
BasicDBObject
(
"username"
,
"www"
)),
new
Update
().
set
(
"username"
,
"ggg"
),
User
.
class
);