Quantcast
Channel: CodeSection,代码区,数据库(综合) - CodeSec
Viewing all articles
Browse latest Browse all 6262

MogoDB学习笔记(二)CURD

$
0
0
一、创建、更新及删除文档 创建

创建一个 db.foo.insert();

批量插入

减少tcp请求

文档发送到数据库会有头部信息,标志是否是插入

不能插入多个文档到多个集合

mongodb消息最大为16mb

插入原理

将数据转换成bson

检验是否包含_id键,并且文档不超过4mb

副作用

无效数据

好处:无注入式攻击风险

删除

db.user.remove

删除所有文档 保留集合和原有索引 数据无法恢复 删除整个集合和索引速度会更快,db.drop_collection('coolection_name'); 更新文档

两个参数

一个查询文档 一个更新文档

冲突解决

最后的执行胜利 文档替换 db.collection.update{query,document} joe = db.people.findOne({"name":}); {"_id" : ObjectId("numbers"),"name" : "joe","age" : 20} joe.age++; db.people.update({"name" : "joe"}, joe); duplicate key on update 修改文档

db.blog.update({a:1},{" $inc ":b});

$set

设置字段

插入与更新

可以修改字段类型

$unset 删除字段

不使用$set修改会将文档覆盖

$inc

{" $inc ":{"score":50}}

只能用于整数、浮点数、双精度浮点型

不能自动进行类型转换

数组修改器 $push 向数组末尾添加一个元素 判断值不在数组中,插入到数组 db.blog.update({a:{`$ne`:123}},{`$push`:{a:123}}); $addToSet db.users.update({"_id" : ObjectId("fljkasdfjkjklw234123kjv")},...\n{"$addToSet":{"emails":{"$each":["joe@php.net", "joe@example.com", "joe@python.org"]}}}) 使用addtoset和each可以添加多个数据 $pop 从数组删除一个元素 {$pop:{key:1}} //从末端删除 {$pop:{key:-1}} //从头部删除 $pull 根据条件删除元素 db.lists.update({}, {"$pull" : {"todo" : "laundry"}}); 定位修改器 db.blog.update({"post": post_id}, {"$inc":{"comments.0.votes":1}}); //0,1,2,3 db.blog.update({"post": post_id}, {"$inc":{"comments.$.votes":1}}); //定位符$

note

需要修改文档大小的操作比较慢(数组大小越大,修改查询速度越慢) mongodb会预留一部分空白来适应文档大小的改变 upsert 文档存在更新,不存在插入 db.blog.update({},{},true); 第三个参数代表upsert 原子性 save db.blog.save(document); 文档中有_id则更新,没有则插入 多文档更新

update的第四个参数为是否多文档更新

查看文档更新的数量:db.runCommand({getLastError : 1});

{ "err" : null, "updatedExisting" : true, // 对已有文档更新 "n" : 5, //更新的数量 "ok" : true, } findAndModify

原子操作

例子 ps = db.runCommand( { "findAndModify" : "processes", //集合名称 "query" : {"status" : "READY"}, //查询文档 "sort" : {"priority" : -1}, //排序结果的条件 "remove" : true, // 是否删除 "update" : {}, //对找到的文档进行修改 update与remove只能存在一个,只能操作一个文档,不能执行upsert "new" : true, //返回更新后的文档还是更新前的文档 } ).value; do_something(ps);

速度相当于执行一次更新,一次查找和一次getLastError的时间

瞬间完成 客户端将更新文档的请求发送给服务端,服务端不会返回状态,不管有没有服务器都会成功 默认是不会有返回结果的,但是mongodb提供了安全版本,执行语句结束之后,立即执行getLastError

是否选择安全版本的条件

不考虑安全性的数据 需要安全监测-付费系统、账号系统、电子邮件 零散信息-页面、广告、统计信息 开发过程中使用安全版本可以方便调试 请求与连接 数据库为每个mongodb创建一个队列,存放请求 一个连接请求不一定能查询到另外一个连接请求的插入数据,特别是使用连接池的时候 二、查询 find db.c.find(); //返回全部文档 db.users.find({"age" : 27}) //返回文档中age为27的文档 db.users.find({"username" : "joe", "age" : 27}); //默认返回全部字段 db.users.find({}, {"username" : 1, "email" : 1}); //返回username和email字段 _id键总是会被返回,无论是否指定 db.users.find({}, {"fatal_weakness" : 0}); //防止返回字段:fatal_weakness // 查询文档的值必须是常量 查询条件 比较操作符: "$lt" < "$lte" <= "$gt" > "$gte" >= "$ne" !=

$ne能用于所有类型的数据

or查询 $in 兼容不同的类型 $nin 返回与数组中条件都不匹配的文档 $or in只能对单个键查询 or可以对多个键进行查询 and查询将最严苛的条件放在最前面,or查询相反 $not $not与正则表达式联合使用极为有用 条件语句的规则 条件句在内层文档 db.users.find({"age":{"$lt":30,"$gt":20}}); 修改器在外层文档 {"$inc" : {"age" : 1}} 特定类型的查询 null 匹配自身 匹配不存在的 返回缺少这个键的文档 想要匹配键值为null的文档 db.c.find( "z" : {" $in ":[null], "$exists":true} ); 正则表达式

db.users.find({&quot;name&quot; : /joe/i});

索引: mongodb会为前缀型正则表达式查询创建索引

查询数组 db.food.insert({"fruit":["apple", "banana", "peach"]}); db.food.find({"fruit" : "banana"}); $all

多个元素匹配数组

db.food.find({"fruit" : { $all : ["apple", "banana"]}}); // 与顺序无关 db.food.find({"fruit" : ["apple", "banana"]}); // 与顺序有关 $size

可以查询指定长度的数组,不能与 $addToSet 结合使用

db.food.find({"size" : {" $gt " : 3}});

$slice 操作符

返回数组的一个子集合

db.blog.posts.findOne(criteria, {"comments" : {"$slice" : 10}}); //返回前10个 db.blog.posts.findOne(criteria, {"comments" : {"$slice" : -10}}); //返回后10个 db.blog.posts.findOne(criteria, {"comments" : {"$slice" : [start, limit]}}); 查询内嵌文档

有如下文档:

{ "name" : { "first" : "Joe", "last" : "Schmoe" }, "age" : 45 }

查询整个文档

db.people.find({&quot;name&quot; : {&quot;first&quot; : &quot;Joe&quot;, &quot;last&quot; : &quot;Schmoe&quot;}}); // 匹配与顺序相关

点表示法查询内嵌的键 (所以插入的文档中不能包含“.”)

db.people.find({&quot;name.first&quot; : &quot;Joe&quot;, &quot;name.last&quot; : &quot;Schmoe&quot;});

指定一组条件,要试用" $elemMatch "

db.blog.find({&quot;comments&quot; : {&quot;$elemMatch&quot; : {&quot;author&quot; : &quot;joe&quot;, &quot;score&quot; : {&quot;$gte&quot; : 5}}}});

" $elemMatch "将限定条件分组,仅当对一个内嵌文档的多个键操作时才会用到

$where 查询

通过where子句可以借助javascript来完成查询:

db.foo.find({ "$where" : function () { for (var current in this) { for (var other in this) { if (current != other && this[current] == this[other]) { return true; } } } return false; }});

如果函数返回true,文档就作为结果的一部分被返回;如果返回false,则不返回。

where子查询的缺点 速度上较慢 每个文档都要从BSON转换成JavaScript对象,然后通过" $where "的表达式来运行。 不能使用索引 调优 尽量将常规查询作为前置过滤,与" $where "组合使用可以不牺牲性能 用索引将非" $where "子句进行过滤," $where "只用于对结果进行调优 游标 var cursor = db.collection.find(); while (cursor.hasNext()) { obj = cursor.next(); // do stuff } // 游标实现了迭代器接口 var cursor = db.people.find(); cursor.forEach(function(x) { print(lx.name); }); [output] adam matt zak

数据是惰性加载的,只有执行cursor.hasNext()才会取数据。

limit、skip和sort

limit和skip经常用来分页

skip的参数过大会影响性能=>skip会一条一条跳过数据

比较顺序 mongodb处理不同类型的数据是有一个顺序的 mongodb对于混合类型的键排序时,顺序是预先定义好的 最小值 null 数字(整型、长整型、双精度) 字符串 对象、文档 数组 二进制数据 对象id 布尔型 日期型 时间戳 正则表达式 最大值 避免使用skip略过大量结果

最简单的方法就是用limit返回结果的第一页,然后将每个后续页面作为相对开始的偏移量返回

随机选取文档

高级查询选项 $min : document 查询的开始条件 $max : document 查询的结束条件 $hint : document 指定服务器使用哪个索引进行查询 $explain : boolean 获取查询的执行细节,而并非真正执行查询 $snapshot : boolean 确保查询的结果是在查询执行那一刻的一致快照 获取一致结果

数据处理过程中将一个文档经过某种变换再存回去。

数据如果超过原文档预留空间的大小,会将其挪到集合末尾处

如此往复,会获取到已经修改的文档。

应对这个问题的方法就是快照 $snapshot 选项。

游标内幕

服务器端,游标消耗内存和其他资源。游标遍历完结果,或者客户端发来消息终止,数据库会释放这些资源。所以要尽量保证尽快释放游标。

10分钟不使用,游标自动销毁

如果真的希望游标持续时间更长。驱动程序一般都会实现一个叫做immortal的函数或者类似机制,告知数据库不要让游标超时。


Viewing all articles
Browse latest Browse all 6262

Trending Articles