插入技巧
简单插入命令:
db.test.insert({
title:'测试标题',
author:'文章作者',
createTime: new Date()
})
mongodb里面的创建时间可以通过new Date函数来获取到。
插入数据的时候,背后发生了什么?
首先会检查是否有包含_id,没有的话,就会自动用objectid创建。
插入的单个文档数据大小是否有超过16m大小。(mongodb为了方式过大的文档数据对数据结构造成影响,会有这种限制)
mongodb如果没有开启安全模式的话,每次操作的背后都不会返回对应的数值响应。
复杂对象插入:
针对比较复杂的对象插入,我们可以借助mongodb的document对象封装进行数据插入:
document=({
title:'标题2',
author:'作者2',
createTime:new Date()
});
db.test.insert(document)
插入多条数据信息:
var document0=({
title:'标题0',
author:'作者2',
createTime:new Date()
});
var document1=({
title:'标题3',
author:'作者2',
createTime:new Date()
});
var document2=({
title:'标题4',
author:'作者2',
createTime:new Date()
});
db.test.insertMany(
[document1,document2]
);
如果在测试环境需要插入数据的话,可以考虑这么操作:
var arr=[];
for(var i=1;i<=5;i++){
arr.push({
"title" : "标题"+i,
"author" : "作者2",
"createTime" : new Date()
});
};
db.test.insert(arr);
更新技巧
更新单独一个数据:
这里的 ‘标题1’ 是指条件,后边的set是指更新之后的数据内容
db.test.update(
{'title':'标题1'},{$set:{'title':'MongodbTest'}}
)
更新批量数据:
db.test.update(
{'title':'MongodbTest'},{$set:{'title':'MongodbTest2'}},{multi:true}
)
特殊更新--替换
有些时候我们会需要对数据结构的内容做调整,这个时候可以通过编写javascript来实现,具体编写脚本如下:
var item=db.test.findOne({"_id":-1});
item.relationships={"friends":item.friends,"enemies":item.enemies};
item.username=item.name;
#删除item对象的部分字段
delete item.friends;
delete item.enemies;
delete item.name;
#更新item整个对象
db.test.update({"_id":-1},item);
此时查询的结果就会发生了变化。
UPSERT和MULTI模式
来看看这么一条语句:
db.users.update({ "name" : "joe" }, joe, true, true);
这里面的后边两个参数涉及到了下边两个概念,分别是upsert模式和multi模式
UPSERT模式
如果有查询到匹配的记录则更新,反之则创建一条新的记录。
MULTI模式
默认的时候update语句只会更新一个文档数据,如果需要修改所有匹配的文档,就需要开启multi模式的参数了。
db.users.update({ "name" : "joe" }, joe, [UPSERT], [MULTI] );
如果更新的时候不希望更新整个文档,使用update语句的时候,默认会更新整个文档,如果只需要做局部字段的更新,那么我们使用修改器会更好。
修改器
最常用的$set修改器:
db.test.update(
{"author":"作者2"},
{"$set":{"title":"更新后的标题2"}},false,true);
$inc修改器: 对某个属性进行原子性的增加操作
db.test.update({"author":"作者2"},{"$inc":{"num":2}},false,true);
如何给文档添加属性
for循环统一为文档添加属性, 如果以后需要统一对数据做格式修改的话,可以使用下边这种方式:
var item=db.test.find({"title":"更新后的标题2"});
for(var i=0;i<item.size();i++){
var newItem=item[i];
newItem.num=i;
db.test.update({"_id":item[i]._id},newItem,false,false);
}
查询技巧
日期查询
db.getCollection('PadContract')
.find({"createTime":{$gte:new Date(2021,0,1)
,$lte:new Date(2021,0,2)}})
注意,中间的月份写11,就是12月
精确查询
db.test.find({
"title":"测试标题"
})
distinct查询
db.collection_name.distinct(field,query,options)
field -----指定要返回的字段(string)
query-----条件查询(document)
options-----其他的选项(document)
or查询
查询title是xxx 或者 author是xxx的数据
db.getCollection('test').find({
$or: [{"title":"MongodbTest2"},{"author":"作者"}]
}).pretty();
打印查询的一些内容
var item=db.test_db.find({});for(var i=0;i<item.size();i++){ console.log(item[i]);}
大于$gt查询
db.getCollection('test_db').find({
title: {$gt :'sadasd'}
}).pretty();
同理类比其他查询,例如:
lte , gt,$ne
查询字段不为空
db.getCollection('test').find({'likes':{$ne:null} })
为空
db.getCollection('test').find({'likes':{$eq:null} })
多个条件查询
db.getCollection('test').find({
title: {$lt :'sadasd' ,$gt :'asdasd'}
}).pretty();
属性类型匹配
如果想获取 "col" 集合中 title 为 String 的数据,你可以使用以下命令:
db.col.find({"title" : {$type : 2}})
或
db.col.find({"title" : {$type : 'string'}})
模糊查询
获取文档里面 tilte字段 以 “标题” 为开始的数据
db.getCollection('test').find({
"title": /^标题/
}).pretty();
包含关键字查询
获取文档里面 tilte字段包含 “标题” 的数据
db.getCollection('test').find({
"title": /标题/
}).pretty();
或者
db.getCollection('test').find({
"title": /标题.*/
}).pretty();
考虑分页情况
db.getCollection('test').find({
"title": /标题.*/
}).limit(2).skip(4).pretty();
保证查询两条,而且跳过原先的前四条数据。可以参考这种方式来实现翻页功能。
排序查询
sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。
db.getCollection('test').find({
}). sort({
"title":1
}).pretty();
管道统计
统计每个作者编写的文章总数为多少?
match相当于条件过滤
group是分组统计
db.test.aggregate(
[
{$match:{by_user :{$ne : null}}},
{$group:{
//注意这里要写为_id才生效
_id: "$by_user",articalTotal: {$sum:1}
}}
]
)
查询结果只显示部分字段
db.BugPO.find(
{'severity': {$ne : null}},
{'severity':1}
)
#多个字段展示可以这么写
db.getCollection('PadContract').find(
{'recommendNum': {$ne : null}},
{'memberId':1,'recommendNum':1,'createTime':1,'workerId':1}
)
Group分组
select title,author,sum(money) from [表]
where title!=null
group by title,author
db.test.group({
'key':{
'title':true,
'author':true
},
'cond':{
"title":{$ne:null}
},
'reduce': function(obj,prev){
prev.csum+=obj.money;
},
'initial':{
'csum':0
}}
)
Robomongo工具查询数量总限制
解决使用Robomongo工具中对于查询数量总限制的问题
可以加入DBQuery.shellBatchSize = 3000;这个参数来扩展一次查询的总数限制。
删除数据
我使用的mongodb是4.0.3版本:
删除所有数据:
db.test.remove({})
如果要按条件删除·,那么可以如下操作:
db.test.remove({
"baz":"b"
});
额外补充
查看mongodb的版本号:
db.version();
目前笔者使用的是4.0.3版本。