入门
1.1 文档
多个键及其关联的值有序的放在一起便是文档,类似于关系型数据库中的行,以json的样子展现 注:1.文档中的键是有序的。 2.值可以是各种不同的类型 3.区分大小写 4.不能有重复的键
1.2 集合与子集合
**集合:**集合是一组文档,类似于关系型数据库的表 子集合用.字符分开的按命名空间的子集合,如blog.posts和blog.authors,目的使让组织结构更好,其实父子集合没有任何关系
1.3 数据库
数据库由多个集合组成,一个mongoDB实例承载多个数据库,每个数据库有独立的权限. eg:cms.blog.posts
1.4 mongodb运行
./mongod 启动mongo,./mongo 客户端,是一个javascript shell
1.5: mongodb 基本操作
do.blog.find() 查找 db.blog.insert(post)插入 post={"title":"aa"} 赋值
db.blog.findOne()查找一个文档
db.blog.update({"title":"aa"},post) 更新
db.blog.remove()删除文档
1.6:数据类型
ObjectId() 12字节的唯一ID, 文档可以包含javascript代码:{x:function{…}},也可以包含数组[1,2,3,4],文档中也可以包含文档
创建,更新以及删除文档
2.1修改器
"$set" 用来指定一个键的值,如果键不存在,则创建它 {"$set":{"favorite book":"war and peace"}}
"$unset"将键完全删除
"$inc"用来修改已有键的值 db.games.update({"game":"pinball","user":"joe},{"$inc":{"scope":50}})
$push:往数组中加入一个元素,如果不存在该数组,则创建一个
$addToSet 能避免重复
$pull:删除第一个
comments.$.author 表示已经查询到的作者
2.2 upinsert和 save
upinsert: 是一种特殊的更新,要是没有文档符合更新条件,就会以这个条件和更新文档为基础创建一个新的文档.如果找到了匹配的文档,则正常更新.(update最后一个参数为true,则为upinsert)
save: 可以再文档不存在时插入,存在时更新。它只有一个参数:文档。要是这个文档含有"_id"键,save会调用upsert。否则,会调用插入。
默认情况下,更新只能对符合条件的第一个文档执行操作。要是多个文档符合条件,其余的文档没有变化。要使所有的匹配到的文档都得到更新,可以设置Update的第四个参数为true。 getLastError:查看更新了多少个文档. findAndModify:返回更新的文档
find查询
3.1 基础查询
- 只要查询username和email:db.users.find({}, {“username”:1, “email”:1})
- 不希望有username: db.users.find({}, “username”:0)
- $lt, $lte, $gt, $gte,$ne 分别对应 <, <=, >, >=,!=操作符 eg:{“index”:{"$gt":new Date(“01/01/2007”)}}
- $in db.users.find(age,{"$in",[10,11,12]})
- $or db.users.find("$or", [{“age”:10}, {“name”:“aaa”}])
- $not db.users.find(“id_num”:{"$not":{"$mod":[5,1]}})
- $exists:db.users.find()
3.2 查询数组
- 数组中的每个元素都是键的值
- $all 需要通过多个元素来匹配数组 db.food.find({“fruit”:{$all : [“apple”, “banana”]}}),顺序无关紧要,如果经过精确匹配,就要求顺序
- $size 可以查询到符合元素个数的文档
- $slice用来返回数组的一个子集合,用于find的第二个参数 $slice:10前10条评论, $slice:-10 后10条评论, $slice:[23, 10]返回24~33条记录,slice不特别说明的话,会默认返回所有的键
3.3 查询内嵌文档
查询内嵌文档可以用点来表示层级结构,加点以后,就与顺序无关了,不加点,查询内嵌文档需要与整个内嵌文档相匹配
3.4 $eleMatch
将限定条件进行分组,仅当需要对一个内嵌文档的多个键操作时才会起作用
3.5 $where
$where 能提供一个javascript来作为查询的条件
eg 如果一个文档中的一个键的值和另一键的值相等,则返回
db.foo.find({$where:function(){
for(var current in this){
for(var other in this){
if(current != other && this[current] == this[other]){return true;}
}
}
}});
也可以用一个表达式来作为条件
db.foo.find({$where: function(){return this.x + this.y == 10;}})
注:不是非常必要,一定要避免使用$where查询,因为速度上会比普通查询慢很多
3.6 游标
使用eg:
var cursor=db.collection.find();
while(cursor.hasNext()) {
obj = cursor.next();
};
cursor.forEach(function(x){});
3.7 limit, skip和sort
limit上限,skip跳过 sort 参数是一组键值对,db.c.find().sort({username:1,age:-1}) , 1是升序, -1是降序,三个方法可以组合使用,注:避免使用skip略过大量的结果,分页的另外一种方法:
var page1 = db.foo.find().sort({"date":-1}).limit(100)
var lastest = null;
while(page1.hasNext()) {
lastest = page1.next();
display(lastest);
}
var page2 = db.foo.find({"date":{"$gt":latest.date}})
page2.sort({"date":-1}).limit(100);
索引
- ensureIndex创建索引, 创建索引只对查询该键的速度有帮助,对于其他键没有帮助,即使包含了该键,所以应该对所有要查询的键创建索引 eg:db.ensureIndex({username:1})
- 索引会造成插入,更新等操作造成额外的开销
- ensureIndex第二个参数为索引命名
- 唯一索引:db.people.ensureIndex({“username”:1},{“unique”,true})
- 消除重复: db.people.ensureIndex({username,1},{“unique”:true,“dropDups”:true})
- 复合唯一索引:单个建可以相同,只要所有键的组合起来不同就行
- .explain()会出现更多查询的信息, hint严格使用某个索引
- 索引的元信息存储在每个数据库的system.indexes集合中,这是一个保留集合
- {background:true} 可以使建立索引在后台进行
- dropIndexes:删除索引
- 地理空间索引: eg:db.map.ensureIndex({“gps”:2d}); gps键必须是某种形式的一对值: {“gps”:[0,100]},键名是可以随意的, db.star.trek.ensureIndex({“light-years”:“2d”},{“min”:-1000, “max”:1000}); 然后使用find来查询 db.map.find({“gps”:{"$near":[40, -73]}})这会按照[40,74]由近到远的方式将map集合的所有文档都返回
聚合
- count:查询文档数量
- distinct:用来找出给定键的所有不同的值,使用时必须指定集合和键 db.runCommand({“distinct”:“people”,“key”:“age”})
- eg 查看股市30天内每天的收盘价:
db.runCommand({group:{
ns:“stocks”, //集合
key:“day”, //键
initial:{“time”:0}, //每一组reduce函数调用的时间
$reduce:function(doc,prev){
if(doc.time>prev.time){
prev.price = doc.price;prev.time=doc.time; (doc当前文档, prev累加文档)
}
}
}}) 4.精简器:finalizer用于精简传到用户的数据; 5.$keyf:能依据各种复杂的条件进行分组 6.mapReduce:
暂时学习到这里,比较粗略的学习了一些语法与概念,后续有详细使用和学习,再继续更新