最近在公司做一个数据仓储等项目,在项目中使用到以前没有用过的mongoDB,下面对使用mongodb中的一些技巧进行记录和分享。文章中的示例以mongo的原生sql和Java进行说明(ps:会不断进行更新)
查询
查询有两个点需要了解,一个是查询内嵌文档,另一个则是返回数据的筛选。查询部分就这两个点展开描述。
内嵌文档查询
内嵌文档由是有深度的层级结构,普通的表示查询不能在深度上进行查询操作。mongo提供一种点表示法来处理内嵌文档的操作需求。点表示法是指通过"字段1.字段2.字段3"这样的方式来定位查询,mongo在字段定位上全面支持点表示法,如更新的字段、新增的字段等。另外上述表述找到字段1下面的字段2下面的字段3来进行相应的处理操作。
/* 1 */
{
"_id" : ObjectId("59a3edde06edb18e9ecb3252"),
"name" : "jack",
"address" : {
"province" : "上海",
"region" : "浦东新区"
},
"age" : 23.0
}
上面是mongo里面的一条内嵌文档数据,匹配地址为上海的人的sql为:
db.study_test.find({"address.province":"上海"})
所以在mongo中,数据的key值是不能有“.”的,点是mongo的关键字。
#####
限定返回字段
因为mongo中的内嵌文档数据一般比较大,如果不限制返回的字段,按照关系型数据库的语法操作的话,会返回整条数据,这里需要说名的是:mongo的查询定位的是一条数据,但是不能限定该条数据中的部分数据,及如果不进行返回字段限定操作,则每次query返回的最小单位为一条整的数据,及有一个"_id"的完整数据.
现在用上例数据再次进行演示。查找jack所处的区(region)
db.study_test.find({"name":"jack"},{"address.region":1})
查询结果显示:
/* 1 */
{
"_id" : ObjectId("59a3edde06edb18e9ecb3252"),
"address" : {
"region" : "浦东新区"
}
}
0表示不显示,大于0表示显示该字段。很明显,这样的操作就限定了返回的数据,只返回了满足条件的jack的region。
干货分享
- 限定返回字段后,其返回的层级结构并不会变,及深度不会变,在取值的时候需要按照限定的键值更具点切割后循环取值。如限定的key为:address.region:1,如果需要取到region的值,就需要将address.region按照"."进行切割,然后去取address的值,再去取region的值。在Java中可以将每步取出来的结果转为DBObject。
如果数据库中存储的值是一串数组,则取出的结果集为以序号为key数组中的每一行数据为value的键值对。所以在结果集中数组的key为1.2.3…的序号值
示例数据如下:
数据录入语句
db.study_test.update({"name" : "jack"},{$set:{"dataType":[{"name":"王者农药","star":"5星"},
{"name":"红警","star":"4星"},{"name":"魔兽","star":"4星"}]}})
mongo中的树形结构:
{
"_id" : ObjectId("59a3edde06edb18e9ecb3252"),
"name" : "jack",
"books" : [
"程序员的修养",
"JAVA从入门到转行"
],
"games" : [
{
"name" : "王者农药",
"star" : "5星"
},
{
"name" : "红警",
"star" : "4星"
},
{
"name" : "魔兽",
"star" : "4星"
}
]
}
通过Java获取games的值,下面是debug模式下的显示:
更新
更新需要注意的是insert ,save ,update的使用。insert是插入一条新纪录,save是进行文档替换,update是进行字段更新。所以insert是直接insert(document),而save和update都需要进行查找定位(query,update/save);在使用上,mongo提供了许多的处理器,使用都是以\$开头,如修改器set的使用是:$set,其运行机制是查找query的document的需要set的字段,如果该字段存在,就更新这个字段的值,如果不存在就添加这个字段,并赋值。db.study_test.update({"name" : "jack"},{$set:{"address":{"province":"上海","region":{"area":"浦东新区","detail":"世纪大道"}}}})
这条语句执行的效果就是更新jack的地址,如果jack没有地址就添加地址信息,如果有就将address更新为上海-浦东新区-世纪大道。
mongo还有许多的这种处理器,如针对数组进行添加的$addToSet、$push、删除数组中最后一个元素的$pop,以及删除字段的$unset,这里不展开说明。
2017-08-29 16:00更新