作者:奋斗LXH_393 | 来源:互联网 | 2014-05-28 16:53
概述如果插入数据,mongodb会自动创建集合和数据库.如果查询不存在的集合,mongodb认为是一个空集.即usemydb(不存在),并不会创建mydb,也不会报错,但如果插入了数据,则自动创建相应的数据库和集合,showdbs可以显示mydb.mongodb的collection(集合)可对应传
概述
如果插入数据,
mongodb会自动创建集合和数据库.如果查询不存在的集合,
mongodb认为是一个空集.
即use mydb(不存在),并不会创建mydb,也不会报错,但如果插入了数据,则自动创建相应的数据库和集合, show
dbs可以显示mydb.
mongodb的collection(集合)可对应传统关系数据库的table, document 对应行(记录)
按照时间先后顺序更新,the last update will “win.”,所以冲突不会破坏数据.
在MongoDB 中,写操作默认是通过 fire-and-forget
的模式来进行的,也就是说写操作通常不关心是否成功,发完请求后客户端就认为成功了。
Mongodb,也是支持IP限制,用户权限限制等一些常用的数据库权限设定,但一般不做限制,官方默认也是无权限认证的.
管理员常用的命令
help show help
show dbs show database names
show collections show collections in current database
show users show users in current database
show profile show most recent system.profile entries with time >= 1ms
use
set curent database to
db.addUser (username, password)
db.removeUser(username)
db.cloneDatabase(fromhost)
db.copyDatabase(fromdb, todb, fromhost)
db.createCollection(name, { size : ..., capped : ..., max : ... } )
db.getName()
db.dropDatabase()
// runs the collstats] command on each collection in the database
db.printCollectionStats()
db.currentOp() displays the current operation in the db
db.killOp() kills the current operation in the db
db.getProfilingLevel()
db.setProfilingLevel(level) 0=off 1=slow 2=all
db.getReplicationInfo()
db.printReplicationInfo()
db.printSlaveReplicationInfo()
db.repairDatabase()
db.version() current version of the server
db.shutdownServer()
Commands for manipulating and inspecting a
collection:
db.foo.drop() drop the collection
db.foo.dropIndex(name)
db.foo.dropIndexes()
db.foo.getIndexes()
db.foo.ensureIndex(keypattern,options) - options object has these possible
fields: name, unique, dropDups
db.foo.find( [query] , [fields]) - first parameter is an optional
query filter. second parameter
is optional
set of fields to return.
e.g. db.foo.find(
{ x : 77 } ,
{ name : 1 , x : 1 } )
db.foo.find(...).count()
db.foo.find(...).limit(n)
db.foo.find(...).skip(n)
db.foo.find(...).sort(...)
db.foo.findOne([query])
db.foo.getDB() get DB object associated with collection
db.foo.count()
db.foo.group( { key : ..., initial: ..., reduce : ...[, cond: ...] } )
db.foo.renameCollection( newName ) renames the collection
db.foo.stats()
db.foo.dataSize()
db.foo.storageSize() - includes free space allocated to this collection
db.foo.totalIndexSize() - size in bytes of all the indexes
db.foo.totalSize() - storage allocated for all data and indexes
db.foo.validate() (slow)
db.foo.insert(obj)
db.foo.update(query, object[, upsert_bool])
db.foo.save(obj)
db.foo.remove(query) - remove objects matching query
remove({}) will remove all
##示例
##SELECT * FROM things WHERE name=”mongo”
> db.things.find({name:”mongo”}).forEach(printjson);
> db.things.find({name:”mongo”});
##SELECT * FROM things WHERE x=4
> db.things.find({x:4}).forEach(printjson);
# { a:A, b:B, … } means “where a=A and b=B and …”.
##SELECT j FROM things WHERE x=4
db.things.find({x:4}, {j:true}).forEach(printjson);
##findOne()函数,这个函数比较方便,仅返回第一个document,或者null
> printjson(db.things.findOne({name:”mongo”}));
等同于
> db.things.find({name:”mongo”}).limit(1)
2. 查看当前数据库状态
db.stats()
3. 在collection foo中存储document {a:1} ,并显示记录(最近20条)
mongo
> db.foo.save( { a : 1 } )
>
db.foo.find() #最多显示20条记录
>
it
#显示更多记录
> db.things.find().limit(3); #限制返回的记录数,
4. 插入和保存数据
> db.foo.insert({“bar” : “baz”})
也可以如下方式,插入数据测试
> j = { name : “mongo” };
> t = { x : 3 };
> db.things.save(j);
> db.things.save(t);
> db.things.find();
> for (var i = 1; i <= 20; i++) db.things.save({x : 4, j :
i});
getLastError 可获知影响的记录数
5. 删除数据(类似delete from ).无法撤消.
> db.users.remove()
> db.mailing.list.remove({“opt-out” : true})
如果不能忍受,想快速删除数据,最好drop然后重建(with index).
6. 更新数据
a=
{
“name” : “joe”,
“friends” : 32,
“enemies” : 2
}
db.users.save(a)
> var joe = db.users.findOne({“name” : “joe”});
> joe.relatiOnships= {“friends” : joe.friends, “enemies” :
joe.enemies};
> joe.username = joe.name;
> delete joe.friends;
> delete joe.enemies;
> delete joe.name;
> db.users.update({“name” : “joe”}, joe);
Using Modifiers
部分更新,更高效率,更少io
$inc #比其他的修改器(modifier)高效,不更改size,仅改值.
而array修改器会更改size,$set有可能也需要修改size.虽然mongodb会预留一些空间供修改,但如果比初始值大太多的话.仍然需要分配新空间.
作者在一个MacBook Air上的测试, 13000次/秒以上.
如计数器的实现.
> db.analytics.update({“url” : “www.example.com”},
… {“$inc” : {“pageviews” : 1}}) #不过使用$对于Php和perl有些不方便.
When using modifiers, the value of “_id” cannot be changed.
(
Positional array modifications
(方便获取下标,不然需要每次查询检验之后才知道匹配的元素的下标)如以下的”0″.
> db.blog.update({“post” : post_id},
… {“$inc” : {“comments.0.votes” : 1}})
而使用”$”,我们可以用$来标记数组下标.
Arrays use 0-based indexing.
db.blog.update({“comments.author” : “John”},
… {“$set” : {“comments.$.author” : “Jim”}})
#这个$,可以用来表示满足前面查询条件的下标
以上改名,只更改匹配的第一条记录.
修改器的效率对比
$inc更高效,而其他修改器,如array,可能需要分配新空间,效率较差.
如以下的测试,一个苹果笔记本MacBook Air上. 网上查是4200转硬盘,性能低下.
for i in range(100000):
collection.update({}, {‘$push’ : {‘x’ : 1}})
1500次/秒. #而使用$inc操作,可以达到15000次/秒.
所以如果$push成为瓶颈,有必要权衡考虑,把这个嵌入文档 分离出来 放到一个collection里.
Upserts
一种很方便的特殊的update操作,如果按条件查找不存在记录,则新建,如果存在,则正常更新.
原子操作
否则你需要检查,create.update操作,可能并发下插入重复的记录.
db.analytics.update({“url” : “/blog”}, {“$inc” : {“visits” :
1}}, true)
> db.math.remove()
> db.math.update({“count” : 25}, {“$inc” : {“count” : 3}},
true)
> db.math.findOne()
{
“_id” : ObjectId(“4b3295f26cc613d5ee93018f”),
“count” : 28
}
save
shell函数,方便我们修改数据.不存在记录的话,插入,如已经存在该记录,更新.
> var x = db.foo.findOne()
> x.num = 42
42
> db.foo.save(x)
查询,使用游标
> var cursor = db.things.find();
> while (cursor.hasNext()) printjson(cursor.next());
#Javascript shell, we can also use the functional features of
the language
> db.things.find().forEach(printjson);
可以把游标当作数组来访问.不适合访问大结果集,会缓存到数组下标的所有数据,可能out of memory .
> var cursor = db.things.find();
> printjson(cursor[4]);
转换为数组访问
> var arr = db.things.find().toArray();
> arr[5];
Arrays
数组类型,元素可以是不同的类型,
arrays can contain different data types as values .
mongodb可以查询数组内的元素,甚至建立索引.可仅更改数组内某个元素.
Embedded Documents
比关系型数据库更自然直观的表示,当然了也多了许多重复数据.
如同Arrays一样,mongodb也可以深入’嵌入文档’结构内部,查询修改,建立索引.
_id and ObjectIds
12 bytes of storage
every document
must have a unique value for
“_id”,默认是ObjectId类型.可以在不同的主机上生成全局唯一的标识.而使用自增id却实现很难
12个字节存储
0 1 2 3 4 5 6 7 8 9 10 11
Timestamp Machine(一般主机名哈希) PID(process identifier,不同主机可能并发很多进程)
Increment
Timestamp:各主机时间不同步没有关系.
These first nine bytes of an ObjectId guarantee its uniqueness
across machines and processes for a single second. The last three
bytes are simply an incrementing counter that is responsible for
uniqueness within a second in a single process
Autogeneration of _id
一般从客户端实现,插入自动生成的id, 理由如下:
虽然很轻量级 ,也是有开销的, 应用层更容易扩展.
##以Javascript脚本来做一些测试
mongo scriptname.js
vi scriptname.js
// check if we have an entry for this page
blog = db.analytics.findOne({url : “/blog”})
// if we do, add one to the number of views and save
if (blog) {
blog.pageviews++;
db.analytics.save(blog);
}
// otherwise, create a new document for this page
else {
db.analytics.save({url : “/blog”, pageviews : 1})
}
并发竞争下,有可能同一个url插入多条记录哦.
使用如下的高效的原子操作.
db.analytics.update({“url” : “/blog”}, {“$inc” : {“visits” :
1}}, true)
我的测试,可以有17000次/秒的$inc操作.
mongo test1.js
// test1.js
//db.testgary.insert({“x”: 1});
startTime = new Date().getTime();
for (i = 0; i <= 50000; i++)
{
db.testgary.update({}, {“$inc” : {“x” : 1}});
}
db.testgary.find();
var endTime=(new Date().getTime()- startTime) / 1000;
db.testgary.update({“what” : “test”}, {“$set” : {“seconds” :
endTime }}, true);
##Advanced Topics 一些高级应用 略
Database Commands
Capped Collections ,Tailable Cursors
GridFS: Storing Files
Server-Side Scripting:不好调试,使用> db.eval(“print(‘Hello,
world’);”);打印日志调试吧.
Stored Javascript:
可设置javascrip变量,供其他任意代码调用,比较适合一个公共的简单函数需要多处调用或多种语言调用,当然了,对于频繁调用的冗长的代码,也有利于减少网络开销;
Security:防止注入的编码方式;
Database References:可以引用其他集合里的文档.一般不建议使用.标准的方式更容易使用.