Mongodb基础命令与用法

查看版本号

[[email protected]_0_12_centos bin]# ./mongo -version
MongoDB shell version v3.6.5
git version: a20ecd3e3a174162052ff99913bc2ca9a839d618
OpenSSL version: OpenSSL 1.0.1e-fips 11 Feb 2013
allocator: tcmalloc
modules: none
build environment:
    distmod: rhel70
    distarch: x86_64
    target_arch: x86_64

查看

show dbs; 查看数据库,查看库占用空间

查找

db.tablename.find()  查找所有

使用

use databaseName 选库

show tables/collections 显示表

注意 system开头的表不要动

admin和Local这两个自带的库不要动

show databases; 个别版本可以使用

db.help(); 查看帮助

创建

mongodb是隐式创建数据库,直接use就能创建一个不存在的数据库。

use newdbName;

表也可以隐式创建。

db.goods.insert({_id:1,name:‘NOKIAn86‘,price:29.9})

db.createCollection(‘user‘);  创建user表

插入

db.user.insert({name:‘zhangsan‘,age:22});   插入数据

db.user.find();   查看user表数据,会查到一个主键,_id,也是主键,自动生成的

db.user.insert({_id:2,name:‘poly‘,age:23});  指定主键的插入方式

mongodb可以插入格式不一样的文档格式

例如:

db.user.insert({_id:3,name:‘hmm‘,hobby:[‘basketball‘,‘football‘],intro:{‘title‘:‘my intro‘,‘content‘:‘from china‘}})

以上这种格式和之前的格式并不冲突,没有结构的特点。

删除

db.user.drop();  删除表

db.dropDatabase(); 删除库

增删改查:

需要传一个json对象。

修改:

语法:

db.collection.update(查询表达式,新值,选项)

db.table.update(匹配条件,新文档,true(upsert),true(修改多个值))

例:

db.news.update({name:‘QQ‘},{name:‘MSN‘});

查找news表中name值为QQ的文档,并将值改为msn,注意:这是替换,其他的值也会不见。

如果只想修改某一列,用$set关键字

db.collectionName.update(query,{$set:{name:‘QQ‘}})

$set 修改某列的值

$unset 删除某个列

$rename 重命名某个列

$inc 增长某个列

$setOnInsert 当upsert为true时,并发生了Isnert操作时,可以补充的字段。



在mongodb的命令交互界面中可以执行以下命令:

db   查看目前指向的数据库

还可以执行数学计算

x = 200

x / 5 ;

可以使用JavaScript标准库

Math.sin(Math.PI / 2);

new Date("2010/1/1");

"Hello,World".replace("World","Mongodb");



新建表

> post={"title":"My Blog Post","content":"Here‘s my blog post.","date":new Date()}

{

"title" : "My Blog Post",

"content" : "Here‘s my blog post.",

"date" : ISODate("2018-07-06T02:35:57.716Z")

}

> db.blog.insert(post)

WriteResult({ "nInserted" : 1 })

> show collections;

blog

fuzzing_agent.configuration

system.users

system.version

定义一个字典

然后db.表名.insert(变量)

只查看一个文档:

findOne()

> db.blog.findOne();

{

"_id" : ObjectId("5b3ed5c1de8e397067390e0d"),

"title" : "My Blog Post",

"content" : "Here‘s my blog post.",

"date" : ISODate("2018-07-06T02:35:57.716Z")

}

find命令一次最多显示20个匹配的文档。

update

update需要两个参数,第一个是限定条件(老文档,被替换的),第二个是新的文档。

> post.comments = []

[ ]

> db.blog.update({title:"My Blog Post"},post)

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.blog.find()

{ "_id" : ObjectId("5b3ed5c1de8e397067390e0d"), "title" : "My Blog Post", "content" : "Here‘s my blog post.", "date" : ISODate("2018-07-06T02:35:57.716Z"), "comments" : [ ] }

>

删除

remove

db.blog.remove({title:"My Blog Post"})

修改

$set

需要用$修改器,如果不用,直接update({目标文档},{新文档}),会将原来的文档直接替换。

db.tester.update({"baz":0},{"$set":{"favorite book":"war and peace"}})

如果{"baz":0}这个字段中没有"favorite book"这个字段,则添加;有则修改

修改内嵌文档

例:

> db.blog.findOne();

{

"_id" : ObjectId("5b431029f9cc01fb9708024b"),

"title" : "A Blog Post",

"content" : "...",

"author" : {

"name" : "joe",

"email" : "[email protected]"

}

}

> db.blog.update({"author.name":"joe"},{"$set":{"author.name":"michel"}})

> db.blog.findOne();

{

"_id" : ObjectId("5b431029f9cc01fb9708024b"),

"title" : "A Blog Post",

"content" : "...",

"author" : {

"name" : "michel",

"email" : "[email protected]"

}

}

$inc增加某个键的数字值

例:

> db.games.findOne();

{

"_id" : ObjectId("5b431235f9cc01fb9708024c"),

"game" : "pinball",

"user" : "tom"

}

> db.games.update({"user":"tom"},{"$inc":{"score":50}})             #没有则新建

注意,$inc必须是数字格式,用于整型,长整型,双精度浮点型,不能用于null,布尔型,数字构成的字符串

> db.games.findOne();

{

"_id" : ObjectId("5b431235f9cc01fb9708024c"),

"game" : "pinball",

"user" : "tom",

"score" : 50

}

$inc的用处如下:

> db.games.update({"user":"tom"},{"$inc":{"score":1000}})

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.games.findOne();

{

"_id" : ObjectId("5b431235f9cc01fb9708024c"),

"game" : "pinball",

"user" : "tom",

"score" : 1050

}

会将score这个值在原有50的基础上增加1000,改为1050

$push,向某个数组中添加元素

例:

> db.blog.findOne({"title":"A blog post"});

{

"_id" : ObjectId("5b431538f9cc01fb9708024d"),

"title" : "A blog post",

"content" : "...",

"commnet" : [

{

"name" : "joe",

"email" : "[email protected]",

"content" : "nice post"

}

]

}

之前没有commnet这个键值对,通过

> db.blog.update({"title" : "A blog post", "content" : "..."},{"$push":{"commnet":{"name":"joe","email":"[email protected]","content":"nice post"}}})

增加,会生成commnet:[]这个格式。

在原有基础上,向commnet这个集合中添加内容:

> db.blog.update({"title":"A blog post"},{"$push":{"commnet":{"name":"michel","email":"[email protected]","content":"good job"}}})

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.blog.findOne({"title":"A blog post"});

{

"_id" : ObjectId("5b431538f9cc01fb9708024d"),

"title" : "A blog post",

"content" : "...",

"commnet" : [

{

"name" : "joe",

"email" : "[email protected]",

"content" : "nice post"

},

{

"name" : "michel",

"email" : "[email protected]",

"content" : "good job"

}

]

}

列表中的多了一个文档。

其他:

$each  可以通过一次push添加多个值

$slice slice必须是负数,限制包含最后加入的slice个数,比如-10,就会只保留最后添加的10个数,如果不够10个则全保留。

$sort 排序

注意,不能只将slice或sort与push配合使用,必须使用$each

$addToSet,可以避免添加重复内容:

db.users.update({"_id":ObjectId("123")},{"$addToSet":{"emails":"[email protected]"}})

如上,添加[email protected]的时候,会检查是否已经存在,如果已经存在则不变,不存在则添加

一次添加多个邮件地址,并去重:

db.users.update({"_id":ObjectId("123")},{"$addToSet":{"emails":{"$each":["[email protected]","[email protected]","[email protected]"]}}})

$ne也是避免添加重复内容,在查找条件中写,效果不如addToSet

基于位置的数组修改器

通过数组的下标找到对应元素,下标从0开始。

db.blog.update({"post":"post_id"},{"$inc":{"comments.0.vates":1}})

如上,找到comments集合中下标为0的元素,将其vates+1

如果不知道下标位置,但知道需要更改的内容,可以通过一下方法修改:

db.blog.update({"comments.author":"John"},{"$set":{"comments.$.author":"jim"}})

如上,将已经匹配的John修改为jim,不知道下标则写$

修改器的速度

有的修改器速度比较快,如$inc,可以就地更改,不需要修改文档的大小,只需要改值。

有的会修改文档的大小,速度就会慢一些,$set能在文档大小不发生变化时立即修改,否则性能也会下降。

文档在插入Mongodb的时候,依次插入的文档会在磁盘上的位置是相邻的,因此如果一个文档变大了,原先的位置放不下了,这个文档就会被移动到集合的另一个位置。

比如

{"x":"a"}

{"x":"b"}

{"x":"c"}

将x:b改为x:bbbbbb

结果是

{"x":"a"}

{"x":"c"}

{"x":"bbbbb"}

填充因子

db.tablename.stats()

原理:

填充因子是Mongodb为每个新文档预留的增长空间,如果一个文档增大之后,填充因子会随之增加,当初没有多余空间的时候,文档会移动位置,然后之前的位置被填充因子覆盖,填充因子变大之后,所有的空间都会增加

到填充因子的大小,直到文档不在继续变大,之后,填充因子会缓慢变小。

填充因子的大小无法手动设置。

upsert

特殊的更新机制,如果没找到符合更新条件的文档,就会以这个条件和更新文档为基础,创建一个新的文档。

传统的修改方式:

js

> blog=db.analytics.findOne({"url":"/blog"})   #判断是否有这个文档

null

> if (blog){blog.pageviews++;db.analytics.save(blog);} else{db.analytics.save({"url":"/blog",pageviews:1})}    #如果有则+1,没有则保存

WriteResult({ "nInserted" : 1 })

> show tables;

analytics

blog

games

list

tester

> db.analytics.find();

{ "_id" : ObjectId("5b432c34f9cc01fb9708024f"), "url" : "/blog", "pageviews" : 1 }

>

使用upsert,既可以避免竞态问题,又可以缩减代码量,

第三个参数表示这个是upsert

db.analytics.update({"url":"/blog"},{"$inc":{"pageviews":1}},true)

作用和上面的一样,但是更高效,并且是原子性。

> db.users.update({"rep":25},{"$inc":{"rep":3}},true)

WriteResult({

"nMatched" : 0,

"nUpserted" : 1,

"nModified" : 0,

"_id" : ObjectId("5b432dc2764f0dcf8c8302cf")

})

如上,upsert创建一个rep值为25的文档,随后将这个值+3,最后得到28.

如果不加这个true,也就是不用upsert,update则匹配不到这个rep:25,然后就不会对集合进行任何更新。

如果再执行这条代码。则会在次创建一个文档,因为没有匹配到rep:25,唯一一个文档是rep:28

$setOnInsert

创建文档的同时并为他赋值,但是在之后的所有更新操作中,这个字段的值不在改变。

例:

> db.time.update({},{"$setOnInsert":{"createdAt":new Date()}},true)

WriteResult({

"nMatched" : 0,

"nUpserted" : 1,

"nModified" : 0,

"_id" : ObjectId("5b432f81764f0dcf8c8302dc")

})

> db.time.find();

{ "_id" : ObjectId("5b432f81764f0dcf8c8302dc"), "createdAt" : ISODate("2018-07-09T09:48:48.986Z") }

> db.time.update({},{"$setOnInsert":{"createdAt":new Date()}},true)

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })

> db.time.find();

{ "_id" : ObjectId("5b432f81764f0dcf8c8302dc"), "createdAt" : ISODate("2018-07-09T09:48:48.986Z") }

>

再次运行这个更新,会匹配到这个文档已存在,所以不会再插入文档,因此createdAt的值也不会改变。

同时更新多个文档

默认情况,更新只针对第一个匹配的文档执行操作,要是需要有多个文档符合条件并被更新,需要将Update的第四个参数设置为true。

> db.users.find();

{ "_id" : ObjectId("5b44117cf9cc01fb97080252"), "name" : "tom", "birthday" : "10/13/1991" }

{ "_id" : ObjectId("5b441194f9cc01fb97080253"), "name" : "jerry", "birthday" : "05/24/1993" }

{ "_id" : ObjectId("5b4411a6f9cc01fb97080254"), "name" : "mike", "birthday" : "10/13/1991" }

{ "_id" : ObjectId("5b4411bff9cc01fb97080255"), "name" : "michel", "birthday" : "03/14/1989" }

{ "_id" : ObjectId("5b4411d0f9cc01fb97080256"), "name" : "lucy", "birthday" : "10/13/1991" }

> db.users.update({"birthday":"10/13/1991"},{"$set":{"gift":"happy birthday!!!"}},false,true)

WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 3 })

> db.users.find();

{ "_id" : ObjectId("5b44117cf9cc01fb97080252"), "name" : "tom", "birthday" : "10/13/1991", "gift" : "happy birthday!!!" }

{ "_id" : ObjectId("5b441194f9cc01fb97080253"), "name" : "jerry", "birthday" : "05/24/1993" }

{ "_id" : ObjectId("5b4411a6f9cc01fb97080254"), "name" : "mike", "birthday" : "10/13/1991", "gift" : "happy birthday!!!" }

{ "_id" : ObjectId("5b4411bff9cc01fb97080255"), "name" : "michel", "birthday" : "03/14/1989" }

{ "_id" : ObjectId("5b4411d0f9cc01fb97080256"), "name" : "lucy", "birthday" : "10/13/1991", "gift" : "happy birthday!!!" }

如上,给users表生日为10/13/1991的人一个gift,效果如上。

删除

删除某个键

db.tester.update({"baz":1},{"$unset":{"favorite book":"Ender‘s Game"}})

删除baz:1这个条目的favorite book字典

删除数组中的元素

$pop

把数组看成队列,可以用$pop

{"$pop":{"key":1}} 从数组最后一个元素删除

{"$pop":{"key":-1}} 从数组第一个元素删除

$pull

根据条件删除数组元素

> db.list.insert({"todo":["dishes","laundry","dry cleaning"]})

WriteResult({ "nInserted" : 1 })

> db.list.find();

{ "_id" : ObjectId("5b431e50f9cc01fb9708024e"), "todo" : [ "dishes", "laundry", "dry cleaning" ] }

> db.list.update({},{"$pull":{"todo":"laundry"}})

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.list.find();

{ "_id" : ObjectId("5b431e50f9cc01fb9708024e"), "todo" : [ "dishes", "dry cleaning" ] }

如上,删除了laundry

$pull会将所有匹配的文档删除,而不是只删除一个,对数组[1,1,2,1]执行Pull 1 则结果只剩2.

数组操作符只能用于包含数组值得键,例如,不能将一个整数插入数组,也不能将一个字符串从数组中弹出,要修改标量值,需要$set和$inc。

getLastError

检查最后一次操作中的错误。编写脚本的时候可能会用到。

db.runCommand({getLastError:1})

findAndModify

更新文档并返回被更新的文档

db.runCommand({"findAndModify":"processes","query":{"status":"READY"},"sort":{"priority":-1},"update":{"$set":{"status":"RUNNING"}}})

findAndModify的其他字段

query 查询文档,用于检索文档的条件

sort  排序结果的条件

update 修改文档,用于对匹配的文档进行更新

remove 布尔类型,表示是否删除文档

new 布尔类型,表示返回更新前还是更新后的文档,默认是更新前的文档

fields 文档中需要返回的字段

upsert   布尔类型,值为true表示upsert,默认为false

查询

查询条件

db.table.find(匹配条件,指定返回内容)

db.users.find({"name":"tom","age":27})    两个查询条件,条件1 and 条件2

指定返回内容

通过find或findOne的第二个参数来指定想要返回的键

db.users.find({},{"username":1,"email":1})

默认情况下,_id这个键是被返回的。

不希望返回_id的做法:

db.users.find({},{"username":1,"id":0})

如上返回了username,但是没有返回id

$lt =  ‘<‘

$lte = ‘<=‘

$gt = ‘>‘

$gte =‘>=‘

$ne  不等于 <>

例:

db.users.find({"age":{"$gte":18,"$lte":30}})

如上查找大于等于18 and小于等于30的人

注意:

{"x":5}

{"x":15}

{"x":25}

{"x":[5,25]}

>db.test.find({"x":{"$gt":10,"$lt":20}})

{"x":15}

{"x":[5,25]}

如上,之所以会返回[5,25] 是因为25大于等于10,所以也一同返回了,

db.test.find({"x":{"$elemMatch":{"$gt":10,"$lt":20}}})

$elemMatch可以同时查询条件中两个语句与一个数组元素做比较,但是$elemMatch不会匹配非数组元素,所以在这里找不到任何匹配内容。

如果当前字段创建过索引,可以使用min()和max()将查询条件遍历的索引范围限制为$gt和$lt的值

>db.test.find({"x":{"$gt":10,"$lt":20}}).min({"x":10}).max({"x":20})

这种方法对日期也同样有用

例:

start=new Date("01/01/2007")

db.users.find({"registered":{"$lt":start}})

如上,查找01/01/2007以前注册的人。

$ne用法

db.users.find("username":{"$ne":"joe"})

查找名字不叫Joe的人

OR查询

$in

$or

$nin

$not

$in

例:

查找中奖号码是725,542,390的所有中奖文档。

db.raffle.find({"ticket_no":{"$in":[725,542,390]}})

例:

超找需要同时匹配id和用户名

db.users.find({"user_id":{"$in":[12345,"joe"]}})

如上,会匹配user_id是12345的,也会匹配user_id是joe的

$nin

与$in相反

例:

找到所有没中奖的人

db.raffle.find({"ticket_no":{"$nin":[725,542,390]}})

$or

例:

找到中奖的人

db.raffle.find({"$or":[{"ticket_no":725},{"winner":true}]})

如上,找到ticket_no为725的或者有winner为true的人

复杂一点的查找中奖人,结合$or和$in:

db.raffle.find({"$or":[{"ticket_no":{"$in":[725,542,390]}},{"winner":true}]})

如上,为查找ticket_no为725或542或390的,或者winner为true的人。

$or可以同时使用不同的查询条件,而$in只能或同样类型的条件。

$not

db.users.find({"id_num":{"$not":{"$mod":[5,1]}}})

如上$not为取反,$mod为取模

null

匹配null

如果直接通过"z":null,会将其他键不是z但值是null的也匹配出来,所以需要写成以下方式:

db.c.find({"z":{"$in":[null],"$exists":true}})

如上,匹配z的值为null的同时判断是否存在。

正则表达式

匹配名字为Joe或者joe的用户

db.users.find({"name":/joe/i})

Mongodb使用PCRE正则表达式库来匹配正则,可以先用js检查一下语法。

数组查询

数组元素查询和普通查询是一样的。

db.food.insert({"fruit":["apple","banana","peach"]})

查询:

db.food.find({"fruit":"banana"})

也能找到该条数据,效果如下(不合法):

{"fruit":"apple","fruit":"banana","furit":"peach"}

$all

匹配既有a也有b的,和and类似

> db.food.find();

{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }

{ "_id" : 2, "fruit" : [ "apple", "kumquat", "orange" ] }

{ "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }

> db.food.find({"fruit":"apple","fruit":"banana"})

{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }

{ "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }

> db.food.find({"fruit":{"$all":["apple","banana"]}})

{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }

{ "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }

如上第二个,是使用$all的写法,作用是匹配既有apple又有banana的情况。

第一种是我自己想的方法,效果是一样的。

$size

根据指定列表长度,来筛选符合列表长度的文档。

> db.food.find();

{ "_id" : 1, "fruit" : [ "apple", "banana", "peach" ] }

{ "_id" : 2, "fruit" : [ "apple", "kumquat", "orange" ] }

{ "_id" : 3, "fruit" : [ "cherry", "banana", "apple" ] }

{ "_id" : 4, "fruit" : [ "orange", "blueberry" ] }

> db.food.find({"fruit":{"$size":2}})

{ "_id" : 4, "fruit" : [ "orange", "blueberry" ] }

$slice

find的第二个参数是指定返回内容,配合$slice可以指定返回匹配数组元素的一个子集

例如:

db.blog.findOne(匹配条件,{"comments":{"$slice":10}})

如上,查找博客评论前10条评论

例如:

db.blog.findOne(匹配条件,{"comments":{"$slice":-10}})

如上,查找博客评论后10条评论

例如:

db.blog.findOne(匹配条件,{"comments":{"$slice":[23,10]}})

如上,查找评论集合第24-33的元素,23是指跳过前23个元素,10是指取10个元素。

注意,slice会默认返回除了指定子集的其他所有的键,比如_id,title什么的。

例如:

db.blog.find({"comments.name":"bob"},{"comments.$":1})

如上查找评论名为bob的数组元素,并取第一个,如果bob评论了多条也只返回第一个。

内嵌文档查询:

> db.score.findOne()

{

"_id" : ObjectId("5b4468fef9cc01fb97080257"),

"content" : "joe",

"comments" : [

{

"author" : "joe",

"score" : 3,

"comment" : "nice post"

},

{

"author" : "mary",

"score" : 6,

"comment" : "terrible post"

}

]

}

查询mary分数在5分以上的评论

> db.score.find({"comments":{"$elemMatch":{"author":"mary","score":{"$gte":5}}}})

{ "_id" : ObjectId("5b4468fef9cc01fb97080257"), "content" : "joe", "comments" : [ { "author" : "joe", "score" : 3, "comment" : "nice post" }, { "author" : "mary", "score" : 6, "comment" : "terrible post" } ] }

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

内嵌文档不能使用如下查找方式:

db.score.find({"comments":{"author":"mary","score":{"$gte":5}}})

内嵌文档的匹配必须整个文档完全匹配,这个查询不会匹配comments键

db.score.find({"comments.author":"mary","comments.score":{"$gte":5}})

符合author条件的评论和符合score条件的评论可能不是一个评论。

$where

$where可以后面使用javascript语句,所以尽量限制用户使用$where方式查询。

例子

> db.fooo.find();

{ "_id" : ObjectId("5b446d78f9cc01fb97080258"), "apple" : 1, "banana" : 6, "speach" : 3 }

{ "_id" : ObjectId("5b446d92f9cc01fb97080259"), "apple" : 8, "spinach" : 4, "watermelon" : 4 }

查找两个键具有相同值得文档,第二个文档中spinach和watermelon的值相同,所以应该返回它

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

{ "_id" : ObjectId("5b446d92f9cc01fb97080259"), "apple" : 8, "spinach" : 4, "watermelon" : 4 }

>

$where查询比常规查询慢很多,而且有一定危险,所以尽量不用。

每个文档都要从BSON转换成JavaScript对象,然后通过$where表达式运行,而且$where不能使用索引。

limit

>db.c.find().limit(3)

如上,限制返回结果为前三条

skip

db.c.find().skip(3)

如上,跳过前三条结果,如果集合里不足3条则不予显示

sort

db.stock.find().sort({username:1,age:-1})

如上,按照username升序及age降序排序

1为升序,-1为降序

组合使用:

db.stock.find({"desc":"mp3"}).limit(50).sort("price":-1)

如上,可以作为在线商店的分页使用,返回Mp3内容前50条,并按价格从高到低排序。

点击下一页后:

db.stock.find({"desc":"mp3"}).limit(50).skip(50).sort("price":-1)

注意,跳过过多会导致性能问题。

注意,不同类型的优先级:

默认如下:

1 最小值

2 null

3 数字

4 字符串

5 对象/文档

6 数组

7 二进制数据

8 对象ID

9 布尔型

10 日期

11 时间戳

12 正则表达式

13 最大值

索引

创建索引

> db.users.ensureIndex({"name":1})

{

"createdCollectionAutomatically" : false,

"numIndexesBefore" : 1,

"numIndexesAfter" : 2,

"ok" : 1

}

如上,给username字段创建索引。

db.currentOp() 可以查看状态。

因为创建索引是有代价的,在插入更新删除的时候都要更耗费时间,还要更新集合所有的索引。所以Mongodb限制每个集合最多只能有64个索引。

通常在一个特定的集合上,不应该拥有2个以上的索引。

创建复合索引

db.users.ensureIndex({"age":1,"username":1})

复合索引在查询中有多个键,或者查询中有多个排序方向作用比较大。

索引嵌套文档

{

"username":"sid",

"loc":{

"ip":"1.2.3.4",

"city":"Springfield",

"state":"NY"

}

}

db.users.ensureIndex({"loc.city":1})

如上,给city字段建立索引,提高这个字段的查询速度。

注意:给内嵌文档创建索引和给内嵌文档的字段创建索引是不同的,除非查找整个内嵌文档,不然查找内嵌文档的某个字段的时候,内嵌文档的索引是没有作用的,需要建立字段索引。

数组索引

给数组创建索引相当于给数组中所有的元素创建索引,这样对数组的更改会比较耗时。

唯一索引

db.users.ensureIndex({"username":1},{"unique":true})

如上,给username设置了唯一索引,如果你插入两个同名的人就会报错。

_id也是唯一索引,区别是_id不能被删除,而其他唯一索引可以被删除。

强制唯一索引

在创建唯一索引的时候有时候会失败,因为已有的数据可能会有重复,但由于数据过多又不知道哪些数据重复,这个时候可以使用

dropDups

db.people.ensureIndex({"username":1},{"unique":true,"dropDups":true})

dropDups会强制删除重复的文档。慎用

查询计划

如果被查询的字段有多个索引,mongodb会从这个字段的索引子集中为每次查询计划选择一个,这些查询计划是并行执行的,最早返回100个结果的就会保留,其他的计划被终止。

查询计划会被缓存,这个查询以后会使用这条计划直到集合数据发生了比较大的变动。建立索引时或每执行1000次查询之后,查询优化器都会重新评估查询计划。

何时不应该使用索引

当数据比较少的时候,不使用索引反而比有索引快,因为使用索引需要先去索引表查找,再根据指针去数据表查找,需要找两次。

所有的索引都保存在system.index集合中,只能通过ensureIndex或者dropIndexes对其进行操作。

可以通过db.tablename.getIndexes()来查看这个表所有索引信息。

删除索引

db.people.dropIndex("x_1_y_1")

用索引描述信息里name字段的值来指定需要删除的索引。


数据类型

null

{"x":null}

布尔型

{"x":true}

数值

默认64位浮点数

{"x":3.14}

{"x":3}

整型

NumberInt表示4字节带符号整数

NumberLong表示8字符带符号整数

{"x":NumberInt("3")}

{"x":NumberLong("3")}

字符串

UTF-8字符串

{"x":"foobar"}

日期

毫秒数,不存储时区

{"x":new Date()}

正则表达式

使用正则表达式作为限定条件

{"x":/foorbar/i}

数组

{"x":["a","b","c"]}

内嵌文档

{"x":{"foo":"bar"}}

对象id

{"x":ObjectId()}

代码

{"x":function() {/*...*/}}

插入校验

所有文档都必须小于16MB。

批量插入脚本

for (var i=0 ;i<100; i++) {db.tester.insert({"foo":"bar","baz":i,"z":10-i})}


固定集合

固定集合相当于一个队列,如果固定集合已经满了,如果再向固定集合中添加内容,那么最老的文档会被删除。

固定集合不能被分片。

固定集合可以用于记录日志。

固定集合必须在使用之前显式创建。

db.createCollection("my_collection",{"capped":true,"size":100000})

如上方式创建固定集合,创建的固定集合叫my_collection,大小为100000字节,除了大小,固定集合还可以指定固定集合中文档的数量。

> db.createCollection("my_collection2",{"capped":true,"size":100000,"max":100});

{ "ok" : 1 }

固定集合创建之后就不能改变了。如果需要修改只能删除之后再重建。

创建固定集合的另一种方式,可以将常规集合转为固定集合。

db.runCommand({"convertToCapped":"test","size":10000})

test为集合名字。

无法将固定集合转为常规集合。只能删除重建。

自然排序

对于固定集合来说,自然排序就是从旧到新排序,也可以按照从新到旧排序。是按照文档的插入顺序排列的。

db.my_collection.find().sort({"$natural":-1})

创建没有_id索引的集合

如果在调用createCollection创建集合时指定autoIndexId选项为false,创建的集合就不会自动在_id上创建索引

一般不这么用,但是如果对只有插入操作的集合来说,效率会提升一些。

TTL索引

(time-to-live index)具有生命周期的索引。

这种索引允许为每一个文档设置一个超时时间,一个文档到达预期设置的超时时间后会被删除。这种类型的索引对于缓存问题非常有帮助。

db.foo.ensureIndex({"lastUpdated":1},{"expireAfterSecs":60*60*24})

如上,给lastUpdated字段建立了TTL索引,当服务器比对发现文件lastUpdated字段的时间晚expireAfterSecs秒时,文档就会被删除。

mongodb每分钟会对TTL索引进行一次清理。

聚合框架

用于对一连串的文档进行处理

包括:

管道(pipeline)

筛选(filtering)

投射(projecting)

分组(grouping)

排序(sorting)

限制(limiting)

跳过(skipping)

例如

找到发表文章最多的前五个作者

db.articles.aggregate({"$project":{"author":1}},{"$group":{"_id":"$author","count":{"$sum":1}}},{"$sort":{"count":-1}},{"$limit":5})

1 将每个文章中的作者投射出来

2 将作者按照名字排序,统计每个名字出现的次数

指定需要分组的字段author,这个操作完成后,每个作者只对应一个文档结果

3 将作者按照名字出现次数降序排列

4 将返回结果限制为前五个

aggregate()会返回一个文档数组。

$match

用于对文档集合进行筛选,筛选之后可以再对文档子集做聚合。

$match可以使用所有常规的查询操作符($gt,$lt$in等)

通常尽可能将$match放在管道的前面位置,好处1是可以快速将不需要的文档过滤掉,2是在投射分组之前执行match可以使用索引。

$project

使用$project可以从子文档中提取字段,可以重命名字段等等。

db.articles.aggregate({"$project":{"author":1,"_id":0}})

如上,可以只返回author字段内容,却不返回_id

将投射过的字段重命名

db.users.aggregate({"$project":{"userId":"$_id","_id":0}})

如上,将_id重命名为userId

注意需要将_id:0,不然这个字段会返回,也就是相当于返回两次,一个被重命名为userId

数学表达式

可以对数值做操作。

db.employees.aggregate({"$project":{"totalPay":{"$add":["$salary","$bonus"]}}})

如上,是将salary和bonus字段相加。

db.employees.aggregate({"$project":{"totalPay":{"$subtract":[{"$add":["$salary","$bonus"]},"$401k"]}}})

如上,是用salary+bonus-401k

操作符语法

"$add":[expr1,expr2]

这个操作符接收一个或多个表达式作为参数,将这些表达式相加。

"$subtract":[expr1,expr2]

接受两个参数,用第一个参数减去第二个参数作为结果。

"$multiply":[expr1,expr2...]

接收一个或多个表达式,将其相乘。

"$divide":[expr1,expr2]

接收两个表达式,用第一个表达式除以第二个表达式的商作为结果。

"$mod":[expr1,expr2]

接收两个表达式,将第一个表达式除以第二个表达式得到的余数作为结果。

日期表达式

$year

$month

$week

$dayOfMonth

$dayOfWeek

$dayOfYear

$hour

$minute

$second

只能对日期做操作,不能对数字做操作。

字符串表达式

"$substr":[expr,startOffset,numToReturn]

expr必须是字符串,startOffset字节开始到numToReturn字节。

"$concat":[expr1,expr2..]

将给定的字符串连接在一起作为结果返回。

"$toLower":expr

参数expr必须是个字符串,这个操作返回expr小写

"$toUpper":expr

参数expr必须是个字符串,这个操作返回expr大写

例如

db.employees.aggregate({"$project":{"email":{"$concat":[{"$substr":["$firstName",0,1]},".","$lastName","@example.com"]}}})

生成[email protected]格式的例子。

逻辑表达式

"$cmp":[expr1,expr2]

如果expr1=expr2,返回0,如果expr1<2返回一个负数,如果expr1>expr2,返回一个正数

"$strcasecmp":[string1,string2]

比较string1和string2,区分大小写,只对罗马字符组成的字符串有效。

"$eq"/"$ne"/"$gt"/"$gte"/"$lt"/"$lte"

"$and"

"$or"  或

"$not"  取反

控制语句

"$cond":[booleanExpr,trueExpr,falseExpr]

如果booleanExpr为true,返回trueExpr,否则返回falseExpr

"$ifNull":[expr,replacementExpr]

如果expr是null,返回replacementExpr,否则返回expr。

原文地址:https://www.cnblogs.com/ArmoredTitan/p/9309680.html

时间: 2024-10-29 02:39:05

Mongodb基础命令与用法的相关文章

MongoDb基础命令

一些基础忘记随时查看.. #整备恢复 mongodump --port 20001 --authenticationDatabase=admin -u *  -d lvlv -c lvlv -o /home mongorestore --drop  --host 172.16.201.74  --port 20001 --authenticationDatabase=admin -umgbackup -d test /tmp/liding/test/liding.bson #基于时间备份oplo

2、链接数据库+mongodb基础命令行+小demo

链接数据库并且打印出数据的流程:1.在CMD里面输入 mongod 2.在CMD里面输入 mongo 3.在输入mongodb命令行里面进行操作,首先输入 show dbs 来查看是否能够链接得上库4.定义db var db = connect('log'); //链接数据库 链接的是哪一个数据库?5.插入数据:db.login.insert(jsonData); //插入数据 5.命令行一:基础命令行(1).查看存在数据库命令 : show dbs (2).查看数据库版本命令 : db.ver

MongoDB 基础命令行

本文专门介绍MongoDB的命令行操作.其实,这些操作在MongoDB官网提供的Quick Reference上都有,但是英文的,为了方便,这里将其稍微整理下,方便查阅. 登录和退出 mongo命令直接加MongoDB服务器的IP地址(比如:mongo 10.77.20.xx),就可以利用Mongo的默认端口号(27017)登陆Mongo,然后便能够进行简单的命令行操作. 至于退出,直接exit,然后回车就好了. [plain] $ mongo 10.77.20.xx MongoDB shell

MongoDB 基础命令——数据库表的增删改查——遍历操作表中的记录

遍历更新数据表中的记录 /***添加 Order[订单表中 订单中商品ID与商品数量]productionDate 事例数据 [ { "productionId":100001,"count":10 } , { "productionId":100002,"count":9 } ]***/ db.order.find().forEach( function(item){ db.order.update({_id:item._i

MongoDB基础命令杂记

一.MongoDB安装使用 1.安装启动MongoDB 1.1 下载安装 官网: https://www.mongodb.com/ rpm下载地址: http://mirrors.aliyun.com/mongodb/yum/redhat/7/mongodb-org/ [[email protected] ~]# ls mongodb-3.0.0/ mongodb-org-3.0.0-1.el7.x86_64.rpm mongodb-org-mongos-3.0.0-1.el7.x86_64.r

Linux基础命令(之一)详解

Linux基础命令(之一)详解 学习linux的朋友都知道,系统大多数操作都是命令行的操作方式,当然如今也有图形化界面的操作方式,但是多数情况下仍然使用命令的操作模式,所以命令的作用与用法是成为学好.学会Linux系统的必备前提,也是重点之一,所以今天来聊一聊一些基础命令的用法与其作用. 1.系统关机或重启命令(小白也必须要会的) shutdown (win 系统也有) 常用参数:shutdown -h (halt) 直接关机(关闭电源) shutdown -h  now[+10]    现在关

基础命令ls总结

一些基础命令的用法用法:ls [options] [ files_or_dirs ]?示例:ls -a 包含隐藏文件ls -l 显示额外的信息ls -R 目录递归通过ls -ld 目录和符号链接信息ls -1 文件分行显示ls –S 按从大到小排序ls –t 按mtime排序ls –u 配合-t选项,显示并按atime从新到旧排序ls –U 按目录存放顺序显示ls –X 按文件后缀排序1.显示/var目录下所有以l开头,以一个小写字母结尾,且中间出现至少一位数字的文件或目录2.显示/etc目录下

MongoDB 学习笔记一 安装以及基础命令

一.MongoDB安装配置 1.获取最新版本: wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.0.2.tgz 2.解压缩即可执行 tar zxvf mongodb-linux-x86_64-2.0.2.tgz tar zxvf mongodb-linux-x86_64-2.0.2.tgz cd /usr/mongodb-linux-x86_64-2.0.2/bin 但是在运行前,需要创建mongodb需要的存放数据和日志的

正则表达式和grep命令的用法

正则表达式和grep命令的用法: 一.正则表达式: 正则表达式(也称为regular Expression,简称RE)就是由普通字符(例如字符a到z)以及特殊字符(称之为元字符)组成的文字模式. 该模式描述在查找文字主体时待匹配的一个或多个字符串. 正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配.简单的说,正则表示式就是处理字符串的方法,它是以行为单位来进行字符串的处理行为,正则表示通过一些特殊符号的辅助,可以让使用者轻易的达到搜寻/删除/取代某特定字符串的处理程序.vim.gr